diff --git a/src/customer/managers.py b/src/customer/managers.py index 5ee86d1..fe787eb 100644 --- a/src/customer/managers.py +++ b/src/customer/managers.py @@ -30,22 +30,31 @@ class UserProfileFiltersManager(models.Manager): class BankAccountManager(models.Manager): def get_main(self, company): - """Возвращает основной расчетный счет пользователя или None если у него еще нет расчетных счетов.""" + """ + Возвращает основной расчетный счет пользователя или None, + если у него еще нет расчетных счетов. + """ try: return self.filter(company=company).order_by('-is_main', 'created_at')[0] except IndexError: return None def get_all(self, company): - """Возвращает все расчетные счета пользователя. - Отсортированы так, что первым идет основной счет, а потом остальные в порядке их добавления.""" + """ + Возвращает все расчетные счета пользователя. + Отсортированы так, что первым идет основной счет, + а потом остальные в порядке их добавления. + """ try: return self.filter(company=company).order_by('-is_main', 'created_at') except: return self.none() def have_main(self, company): - """Возвращает True, если у пользователя есть основной расчетный счет, и False в противном случае.""" + """ + Возвращает True, если у пользователя есть основной расчетный счет, + и False в противном случае. + """ return True if self.filter(company=company, is_main=True) else False def force_main(self, company): diff --git a/src/customer/middleware.py b/src/customer/middleware.py index 549acef..7cddcb9 100644 --- a/src/customer/middleware.py +++ b/src/customer/middleware.py @@ -13,15 +13,22 @@ def _get_profile(request): class ProfileMiddleware(object): + def process_request(self, request): - assert hasattr(request, 'user'), "The Profile middleware requires authentication middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.auth.middleware.AuthenticationMiddleware'." + assert hasattr(request, 'user'),\ + "The Profile middleware requires authentication middleware to be installed. " \ + "Edit your MIDDLEWARE_CLASSES setting to insert " \ + "'django.contrib.auth.middleware.AuthenticationMiddleware'." request.profile = SimpleLazyObject(lambda: _get_profile(request)) try: if request.user.is_authenticated() and request.session and request.user: if request.user.profile.user_session_key != request.session.session_key and \ request.profile.user_session_key != '': django_logout(request) - messages.add_message(request, messages.ERROR, u'Другой пользователь вошёл под этим логином.') + messages.add_message( + request, messages.ERROR, + 'Другой пользователь вошёл под этим логином.' + ) except: # print 'no user profile' pass diff --git a/src/customer/models.py b/src/customer/models.py index 7f070b0..5256f50 100644 --- a/src/customer/models.py +++ b/src/customer/models.py @@ -89,8 +89,18 @@ class UserProfile(models.Model): fax_code = models.CharField(u'Код города', max_length=10, blank=True, default='') fax = models.CharField(u'Номер телефона', max_length=20, blank=True, default='') - email = models.EmailField(u'Электронная почта', max_length=75, blank=True, default='') - site = models.CharField(u'Сайт', max_length=256, blank=True, default='') + email = models.EmailField( + 'Электронная почта', + max_length=75, + blank=True, + default='' + ) + site = models.CharField( + 'Сайт', + max_length=256, + blank=True, + default='' + ) # поля, только для ИП svid_gos_reg = models.CharField( @@ -104,8 +114,12 @@ class UserProfile(models.Model): ip_reg_date = models.DateField(u'Дата регистрации ИП', blank=True, null=True) # поля, только для Организации - name = models.CharField(u'Краткое название организации', max_length=256, default='', - help_text=u'Будет подставляться в создаваемые документы.') + name = models.CharField( + 'Краткое название организации', + max_length=256, + default='', + help_text=u'Будет подставляться в создаваемые документы.' + ) full_name = models.CharField( 'Полное название организации', max_length=256, @@ -116,26 +130,57 @@ class UserProfile(models.Model): kpp = models.CharField(u'КПП', max_length=9, default='') - boss_title = models.CharField(u'Должность руководителя', max_length=256, blank=True, default='') - na_osnovanii = models.CharField(u'Действует на основании', max_length=256, blank=True, default='') + boss_title = models.CharField( + u'Должность руководителя', + max_length=256, + blank=True, + default='' + ) + na_osnovanii = models.CharField( + u'Действует на основании', + max_length=256, + blank=True, + default='' + ) # подписи, печать и логотип - boss_sign = models.ImageField(u'Подпись руководителя', blank=True, default='', - upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'boss_sign.png')) - glavbuh_sign = models.ImageField(u'Подпись бухгалтера', blank=True, default='', - upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'glavbuh_sign.png')) - stamp = models.ImageField(u'Печать', blank=True, default='', - upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'stamp.png')) - logo = models.ImageField(u'Логотип', blank=True, default='', - upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'logo.png')) + boss_sign = models.ImageField( + 'Подпись руководителя', + blank=True, + default='', + upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'boss_sign.png') + ) + glavbuh_sign = models.ImageField( + u'Подпись бухгалтера', + blank=True, + default='', + upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'glavbuh_sign.png') + ) + stamp = models.ImageField( + u'Печать', + blank=True, + default='', + upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'stamp.png') + ) + logo = models.ImageField( + 'Логотип', + blank=True, + default='', + upload_to=UploadAndRename(PROFILE_IMAGES_UPLOAD_DIR, 'logo.png') + ) created_at = models.DateTimeField(u'Создан', auto_now_add=True) updated_at = models.DateTimeField(u'Изменен', auto_now=True) active = models.BooleanField(u'Активен', default=False) confirmed = models.BooleanField(u'Подтверждён', default=False) - user_session_key = models.CharField(u'Ключ сессии (служебная информация)', max_length=256, blank=True, default='', - help_text=u'Руками не трогать...') + user_session_key = models.CharField( + u'Ключ сессии (служебная информация)', + max_length=256, + blank=True, + default='', + help_text=u'Руками не трогать...' + ) objects = managers.UserProfileManager() @@ -219,7 +264,9 @@ class UserProfile(models.Model): return self.kpp == '' def get_company_name(self): - """`ИП ФИО` или `Название Организации`.""" + """ + `ИП ФИО` или `Название Организации`. + """ if self.profile_type == consts.IP_PROFILE: return u'ИП %s' % self.get_boss_full_fio() elif self.profile_type == consts.ORG_PROFILE: @@ -255,12 +302,14 @@ class UserProfile(models.Model): def get_glavbuh_fio(self): """Фамилия и инициалы главного бухгалтера.""" if self.glavbuh_surname and self.glavbuh_name and self.glavbuh_midname: - return (u'%s %s. %s.' % (self.glavbuh_surname, self.glavbuh_name[0], self.glavbuh_midname[0],)).strip() + return (u'%s %s. %s.' % (self.glavbuh_surname, self.glavbuh_name[0], + self.glavbuh_midname[0],)).strip() return u'' def get_glavbuh_full_fio(self): """Полное ФИО главного бухгалтера.""" - return (u'%s %s %s' % (self.glavbuh_surname, self.glavbuh_name, self.glavbuh_midname,)).strip() + return (u'%s %s %s' % (self.glavbuh_surname, self.glavbuh_name, + self.glavbuh_midname,)).strip() def get_full_phone(self): """(Код города) Номер телефона.""" @@ -297,7 +346,12 @@ class BankAccount(models.Model): bik = models.CharField(u'БИК', max_length=10) name = models.CharField(u'Наименование банка', max_length=256) - short_name = models.CharField(u'Сокращенное название банка', max_length=100, blank=True, default='') + short_name = models.CharField( + 'Сокращенное название банка', + max_length=100, + blank=True, + default='' + ) korr_account = models.CharField(u'Корр. счет', max_length=20) account = models.CharField(u'Расчетный счет', max_length=20) @@ -327,8 +381,10 @@ class BankAccount(models.Model): super(BankAccount, self).save(*args, **kwargs) if self.is_main: - # если задано, что это будет основной счет, то сбросить у остальных счетов пользователя этот признак - BankAccount.objects.filter(company=self.company, is_main=True).exclude(pk=self.pk).update(is_main=False) + # если задано, что это будет основной счет, то + # сбросить у остальных счетов пользователя этот признак + BankAccount.objects.filter( + company=self.company, is_main=True).exclude(pk=self.pk).update(is_main=False) else: # если нет основного счета, то установить его принудительно BankAccount.objects.force_main(company=self.company) @@ -345,8 +401,18 @@ class Client(models.Model): name = models.CharField(u'Наименование', max_length=256, db_index=True) - name_short_self = models.CharField(u'Короткое наименование', max_length=256, null=True, blank=True, ) - name_short_dadata = models.CharField(u'Наименование из Dadata', max_length=256, null=True, blank=True, ) + name_short_self = models.CharField( + 'Короткое наименование', + max_length=256, + null=True, + blank=True + ) + name_short_dadata = models.CharField( + 'Наименование из Dadata', + max_length=256, + null=True, + blank=True + ) inn = models.CharField(u'ИНН', max_length=12) kpp = models.CharField(u'КПП', max_length=9, blank=True, default='') # Организация @@ -357,7 +423,12 @@ class Client(models.Model): # банковские реквизиты bank_bik = models.CharField(u'БИК', max_length=10, blank=True, default='') bank_name = models.CharField(u'Наименование банка', max_length=256, blank=True, default='') - bank_short_name = models.CharField(u'Сокращенное наименование банка', max_length=256, blank=True, default='') + bank_short_name = models.CharField( + 'Сокращенное наименование банка', + max_length=256, + blank=True, + default='' + ) bank_korr_account = models.CharField(u'Корр. счет', max_length=20, blank=True, default='') bank_account = models.CharField(u'Расчетный счет', max_length=20, blank=True, default='') @@ -409,7 +480,9 @@ class Client(models.Model): class UserProfileFilters(models.Model): - """Фильтрация реквизитов: какие данные показывать/скрывать при генерации карточки компании.""" + """ + Фильтрация реквизитов: какие данные показывать/скрывать при генерации карточки компании. + """ company = models.OneToOneField(UserProfile, related_name='profile_filters', primary_key=True) # общие фильтры @@ -422,8 +495,14 @@ class UserProfileFilters(models.Model): show_glavbuh = models.BooleanField(u'Главный бухгалтер', default=True) show_bank_account = models.BooleanField(u'Банковские реквизиты', default=True) - bank_account = models.ForeignKey(BankAccount, related_name='+', verbose_name=u'Расчетный счет', blank=True, - null=True, default=None) + bank_account = models.ForeignKey( + BankAccount, + related_name='+', + verbose_name=u'Расчетный счет', + blank=True, + null=True, + default=None + ) show_contact_info = models.BooleanField(u'Контактная информация', default=True) show_address = models.BooleanField(u'Фактический адрес', default=True) @@ -468,7 +547,11 @@ class UserProfileFilters(models.Model): class License(models.Model): - company = models.ForeignKey(UserProfile, related_name='licenses', verbose_name=u'пользователь') + company = models.ForeignKey( + UserProfile, + related_name='licenses', + verbose_name='пользователь' + ) term = models.IntegerField(verbose_name=u'срок лицензии') date_from = models.DateField(u'дата начала', null=True, blank=True) date_to = models.DateField(u'дата окончания', null=True, blank=True) @@ -504,8 +587,10 @@ class License(models.Model): ) def save(self, *args, **kwargs): + if not self.__prev_date and self.paid_date: - max_date_license = License.objects.filter(company=self.company).aggregate(Max('date_to'))['date_to__max'] + max_date_license = License.objects.\ + filter(company=self.company).aggregate(Max('date_to'))['date_to__max'] today = datetime.now().date() if max_date_license < today: max_date_license = today - timedelta(1) @@ -525,13 +610,17 @@ class License(models.Model): if self.status == 0: if self.payform == 0: - return u'Скачать счёт' % reverse('customer_license_get_doc', - kwargs={'order_num': self.id}) + return u'Скачать счёт' % reverse( + 'customer_license_get_doc', + kwargs={'order_num': self.id} + ) elif self.payform == 1: return u'Оплатить счёт' elif self.payform == 2: - return u'Скачать квитанцию' % reverse('customer_license_get_doc', - kwargs={'order_num': self.id}) + return u'Скачать квитанцию' % reverse( + 'customer_license_get_doc', + kwargs={'order_num': self.id} + ) elif self.status in [1, 2]: return u'История операций' else: @@ -552,7 +641,8 @@ class License(models.Model): left = relativedelta(self.date_to, datetime.today()) if left.months: left_str = '%d %s %d %s' % (left.months, - numeral.choose_plural(left.months, u"месяц, месяца, месяцев"), + numeral.choose_plural( + left.months, u"месяц, месяца, месяцев"), left.days, numeral.choose_plural(left.days, u"день, дня, дней"), ) diff --git a/src/customer/tasks.py b/src/customer/tasks.py index 3021210..da88dde 100644 --- a/src/customer/tasks.py +++ b/src/customer/tasks.py @@ -5,7 +5,7 @@ from datetime import datetime, timedelta import traceback from django.core.mail import mail_admins -from dokumentor.celery import shared_task +from celery import shared_task from .models import License, UserProfile from .utils import check_one_profile @@ -16,18 +16,20 @@ def check_license(): profiles = UserProfile.objects.all() now = datetime.today() - #licenses = License.objects.filter(date_to__lt=now, status__in=[-1, 2], deleted=False) - #licenses.update(status=3) - - licenses = License.objects.filter(order_date__lte=now - timedelta(10), status=0, deleted=False) + licenses = License.objects.filter( + order_date__lte=now - timedelta(10), + status=0, + deleted=False + ) licenses.update(status=4) for profile in profiles: try: check_one_profile(profile, License, now) except Exception as e: - mail_admins(subject=u'customer: check_license error', - message=u'Profile id=%s.\n\n%s' % (profile.pk, traceback.format_exc(e)) + mail_admins( + subject='customer: check_license error', + message=f'Profile id={profile.pk}.\n\n{traceback.format_exc(e)}' ) return None diff --git a/src/customer/utils.py b/src/customer/utils.py index 0c4fd88..8b348e7 100644 --- a/src/customer/utils.py +++ b/src/customer/utils.py @@ -10,7 +10,9 @@ SUPPORT_EMAIL = getattr(settings, 'SUPPORT_EMAIL') def check_one_profile(profile, License, now, manual=False): profile_is_active = profile.active - licenses = License.objects.filter(company=profile, date_from__lte=now, date_to__gte=now, status__in=[-1, 1, 2], deleted=False) + licenses = License.objects.\ + filter(company=profile, date_from__lte=now, date_to__gte=now, + status__in=[-1, 1, 2], deleted=False) licenses.filter(status=1).update(status=2) if licenses: @@ -33,11 +35,13 @@ def check_one_profile(profile, License, now, manual=False): email = EmailMessage(subject=subject, to=(user_email,), body=email_body) email.send() - licenses_remain = License.objects.filter(company=profile, date_from__gt=now + timedelta(1), status=1, deleted=False) + licenses_remain = License.objects.filter(company=profile, date_from__gt=now + timedelta(1), + status=1, deleted=False) licenses_to_pay = License.objects.filter(company=profile, status=0, deleted=False) if not licenses_remain and not manual: - licenses = License.objects.filter(company=profile, date_to__lt=now, status__in=[-1, 2], deleted=False) + licenses = License.objects.filter(company=profile, date_to__lt=now, status__in=[-1, 2], + deleted=False) licenses.update(status=3) if licenses: @@ -52,7 +56,8 @@ def check_one_profile(profile, License, now, manual=False): email = EmailMessage(subject=subject, to=(user_email,), body=email_body) email.send() - licenses = License.objects.filter(company=profile, date_to=now + timedelta(1), status__in=[-1, 2], deleted=False) + licenses = License.objects.filter(company=profile, date_to=now + timedelta(1), + status__in=[-1, 2], deleted=False) if licenses: template_name = 'myauth/license_ends.txt' @@ -67,7 +72,8 @@ def check_one_profile(profile, License, now, manual=False): email.send() if not manual: - licenses = License.objects.filter(company=profile, order_date=now - timedelta(9), status=0, deleted=False) + licenses = License.objects.filter(company=profile, order_date=now - timedelta(9), + status=0, deleted=False) if licenses: template_name = 'myauth/license_to_pay.txt' @@ -82,4 +88,5 @@ def check_one_profile(profile, License, now, manual=False): def raise_if_no_profile(request): if not request.user.profile: - raise Exception(u"Profile not found for user: %d, '%s'" % (request.user.pk, request.user.username)) + raise Exception(u"Profile not found for user: %d, '%s'" % + (request.user.pk, request.user.username)) diff --git a/src/customer/views/bank_accounts_ajax.py b/src/customer/views/bank_accounts_ajax.py index 092ed63..52d50dd 100644 --- a/src/customer/views/bank_accounts_ajax.py +++ b/src/customer/views/bank_accounts_ajax.py @@ -25,7 +25,8 @@ def bank_accounts_list_ajax(request): raise_if_no_profile(request) fields_list = ['pk', 'bik', 'name', 'korr_account', 'account', 'is_main'] - accounts = models.BankAccount.objects.get_all(company=request.user.profile).values(*fields_list) + accounts = models.BankAccount.objects.get_all( + company=request.user.profile).values(*fields_list) for a in accounts: a['edit_url'] = reverse('customer_bank_accounts_edit', kwargs={'id': a['pk']}) @@ -37,9 +38,11 @@ def bank_accounts_list_ajax(request): @login_required def bank_accounts_get_ajax(request, id): - """Получить счёт - AJAX. - Если в форме редактирования счёта задан атрибут Meta.fields, то дампит только поля, перечисленные в нём. - Иначе дампит вообще все поля, которые есть в модели. + """ + Получить счёт - AJAX. + Если в форме редактирования счёта задан атрибут Meta.fields, + то дампит только поля, перечисленные в нём. + Иначе дампит вообще все поля, которые есть в модели. """ if not request.is_ajax(): return HttpResponseBadRequest() diff --git a/src/customer/views/clients_ajax.py b/src/customer/views/clients_ajax.py index a405688..7103c36 100644 --- a/src/customer/views/clients_ajax.py +++ b/src/customer/views/clients_ajax.py @@ -17,8 +17,9 @@ from customer.utils import raise_if_no_profile @login_required def clients_get_ajax(request, id): """Получить контрагента - AJAX. - Если в форме редактирования контрагента задан атрибут Meta.fields, то дампит только поля, перечисленные в нём. - Иначе дампит вообще все поля, которые есть в модели. + Если в форме редактирования контрагента задан атрибут Meta.fields, + то дампит только поля, перечисленные в нём. + Иначе дампит вообще все поля, которые есть в модели. """ if not request.is_ajax(): return HttpResponseBadRequest() @@ -133,9 +134,14 @@ def clients_delete_ajax(request, id): client = get_object_or_404(models.Client, pk=id, company=request.user.profile) client_docs = [] - doc_list = [(Invoice, u'счета'), (Faktura, u'счета-фактуры'), (Nakladn, u'накладные'), - (AktRabot, u'акты выполненных работ'), (Platejka, u'платёжные поручения'), - (Dover, u'доверенности'), (AktSverki, u'акты сверки')] + doc_list = [ + (Invoice, u'счета'), + (Faktura, u'счета-фактуры'), + (Nakladn, u'накладные'), + (AktRabot, u'акты выполненных работ'), + (Platejka, u'платёжные поручения'), + (Dover, u'доверенности'), (AktSverki, u'акты сверки') + ] for doc in doc_list: docs = doc[0].objects.filter(client=client) if docs: diff --git a/src/customer/views/documents.py b/src/customer/views/documents.py index 0eafb96..7ebdbb7 100644 --- a/src/customer/views/documents.py +++ b/src/customer/views/documents.py @@ -35,7 +35,7 @@ def get_doc(request, order_num=None): else: raise Http404() - response = HttpResponse(mimetype="application/vnd.ms-excel") + response = HttpResponse(content_type="application/vnd.ms-excel") response['Content-Disposition'] = 'attachment; filename=%s' % file_name rb = open_workbook(os.path.join(XLS_ROOT, tmp_name), on_demand=True, formatting_info=True) @@ -45,12 +45,14 @@ def get_doc(request, order_num=None): # отключить колонтитулы ws.show_headers = 0 ws.print_headers = 0 - ws.header_str = '' - ws.footer_str = '' + ws.header_str = b'' + ws.footer_str = b'' - if pm == 0: # заполняем счет + # заполняем счет + if pm == 0: style0 = easyxf('font: name Times New Roman, height 280, bold True;') - style0_center = easyxf('font: name Times New Roman, height 280, bold True; align: horiz center') + style0_center = \ + easyxf('font: name Times New Roman, height 280, bold True; align: horiz center') style1 = easyxf('font: name Times New Roman, height 180;') style2 = easyxf('font: name Times New Roman, height 180, bold True;') style3 = easyxf('font: name Times New Roman, height 180;' @@ -61,7 +63,8 @@ def get_doc(request, order_num=None): ) style4.num_format_str = "#,##0.00" - ws.write(11, 0, u"СЧЕТ № %s от %s" % (order_num, license.order_date.strftime('%d.%m.%Y')), style0_center) + ws.write(11, 0, u"СЧЕТ № %s от %s" % (order_num, license.order_date.strftime('%d.%m.%Y')), + style0_center) ws.write(13, 0, u"Покупатель: %s" % data.name, style1) ws.write(16, 2, u"Лицензия Dokumentor.ru на %s" % (license.get_term()), style3) @@ -76,7 +79,8 @@ def get_doc(request, order_num=None): ws.insert_bitmap(os.path.join(XLS_ROOT, 'stamp.bmp'), 26, 12, y=3, scale_y=1.1) - elif pm == 2: # заполняем квитанцию + # заполняем квитанцию + elif pm == 2: style0 = easyxf('font: name Times New Roman, height 160, bold True;' 'border: bottom thin;' ) diff --git a/src/customer/views/license.py b/src/customer/views/license.py index cb691de..06ab32c 100644 --- a/src/customer/views/license.py +++ b/src/customer/views/license.py @@ -3,7 +3,8 @@ import json import hashlib from django.shortcuts import render, redirect -from django.http import Http404, HttpResponseRedirect, HttpResponseForbidden, HttpResponse +from django.http import Http404, HttpResponseRedirect, HttpResponseForbidden, HttpResponse, \ + HttpResponseBadRequest from django.conf import settings from django.views.decorators.csrf import csrf_exempt from django.utils.http import urlquote @@ -40,7 +41,7 @@ def order_license(request): raise_if_no_profile(request) template_name = 'customer/profile/license.html' - form = LicenseForm(request.POST or None, + form = LicenseForm(request.POST or None, initial = {'term': LicensePrice.objects.all()[1], 'payform': 0}) dictionary = { 'form': form, @@ -48,13 +49,14 @@ def order_license(request): if form.is_valid(): new_license = License(company=request.user.profile, - term=form.cleaned_data['term'].term, - payform=form.cleaned_data['payform'], - pay_sum=form.cleaned_data['term'].price, - ) + term=form.cleaned_data['term'].term, + payform=form.cleaned_data['payform'], + pay_sum=form.cleaned_data['term'].price, + ) new_license.save() if form.cleaned_data['payform'] == '1': - payment, _ = Payment.objects.get_or_create(order_amount=form.cleaned_data['term'].price, + payment, _ = Payment.objects.get_or_create(order_amount=form.cleaned_data['term']. + price, payment_type=Payment.PAYMENT_TYPE.AC, order_number=new_license.id, ) @@ -76,7 +78,8 @@ def license_list(request): raise_if_no_profile(request) template_name = 'customer/profile/license_list.html' - licenses = License.objects.filter(company=request.user.profile, deleted=False, status__gt=-1).order_by('-id') + licenses = License.objects.filter( + company=request.user.profile, deleted=False, status__gt=-1).order_by('-id') dictionary = { 'licenses': licenses, } @@ -90,7 +93,7 @@ def paid_list(request): raise_if_no_profile(request) template_name = 'customer/profile/paid_list.html' - licenses = License.objects.filter(company=request.user.profile, + licenses = License.objects.filter(company=request.user.profile, status__in=[-1, 1, 2, 3, 4], deleted=False).order_by('-id') dictionary = { 'licenses': licenses, @@ -117,7 +120,7 @@ def delete_license(request, pk): data = json.dumps(dictionary) return HttpResponse(data, content_type='application/json') - + @csrf_exempt def payment_result(request): if request.method == 'POST': @@ -126,7 +129,8 @@ def payment_result(request): nOutSum = request.POST.get('OutSum') sSignatureValue = request.POST.get('SignatureValue') - SignatureValue = hashlib.md5('%s:%s:%s' % (nOutSum, nInvId, settings.ROBOKASSA_PASSWORD2)).hexdigest() + SignatureValue = hashlib.md5('%s:%s:%s' % (nOutSum, nInvId, + settings.ROBOKASSA_PASSWORD2)).hexdigest() if sSignatureValue.upper() == SignatureValue.upper(): license = License.objects.get(pk=nInvId) license.status = 1 @@ -154,8 +158,12 @@ def payment_fail(request): try: nInvId = request.GET.get('') - message = u"Возникла проблема. Ваш Заказ не оплачен. Попробуйте оформить заявку снова, или позвоните по номеру." + message = u"Возникла проблема. Ваш Заказ не оплачен. " \ + u"Попробуйте оформить заявку снова, или позвоните по номеру." - return TemplateResponse(request, 'customer/profile/end_order.html', {'message': message, 'success': False}) + return TemplateResponse( + request, + 'customer/profile/end_order.html', + {'message': message, 'success': False}) except Order.DoesNotExist: return HttpResponseForbidden() diff --git a/src/dokumentor/settings/common.py b/src/dokumentor/settings/common.py index 396b977..549ba16 100644 --- a/src/dokumentor/settings/common.py +++ b/src/dokumentor/settings/common.py @@ -108,7 +108,8 @@ TEMPLATES = [ 'django.template.context_processors.csrf', 'sekizai.context_processors.sekizai', 'cms.context_processors.cms_settings', - 'callback.context_processors.add_forms' + 'callback.context_processors.add_forms', + 'src.customer.context_processors.license_check_soon_ends' ], 'loaders': [ 'django.template.loaders.filesystem.Loader', @@ -266,8 +267,10 @@ CELERYBEAT_SCHEDULE = { }, } -CAPTCHA_OUTPUT_FORMAT = u"%(hidden_field)s %(image)s%(text_field)s" +CAPTCHA_OUTPUT_FORMAT = \ + "%(hidden_field)s %(image)s%(text_field)s" + CAPTCHA_FONT_SIZE = 36 CKEDITOR_SETTINGS = { diff --git a/src/dokumentor/templates/base.html b/src/dokumentor/templates/base.html index 8acfdb9..5ab49cc 100644 --- a/src/dokumentor/templates/base.html +++ b/src/dokumentor/templates/base.html @@ -16,11 +16,11 @@ {% cms_toolbar %} + {% if license_15days %}
{% endif %} +
 
{% block bg %} - {% endblock %} + {% endblock bg %}
diff --git a/src/myauth/models.py b/src/myauth/models.py index 425be9b..90c0d4f 100644 --- a/src/myauth/models.py +++ b/src/myauth/models.py @@ -12,7 +12,8 @@ from myauth import managers class DokUser(AbstractBaseUser, PermissionsMixin): - """(не)Самопальная модель пользователя - содрано у caktusgroup.com, + """ + (не)Самопальная модель пользователя - содрано у caktusgroup.com, также проблемы с добавлением юзера в админке решены при помощи stackoverflow, да хранит гугл имя его. """ @@ -21,11 +22,13 @@ class DokUser(AbstractBaseUser, PermissionsMixin): first_name = models.CharField(_('first name'), max_length=30, blank=True) last_name = models.CharField(_('last name'), max_length=30, blank=True) is_staff = models.BooleanField(_('staff status'), default=False, - help_text=_('Designates whether the user can log into this admin ' - 'site.')) + help_text=_( + 'Designates whether the user can log into this admin ' + 'site.')) is_active = models.BooleanField(_('active'), default=True, - help_text=_('Designates whether this user should be treated as ' - 'active. Unselect this instead of deleting accounts.')) + help_text=_( + 'Designates whether this user should be treated as ' + 'active. Unselect this instead of deleting accounts.')) date_joined = models.DateTimeField(_('date joined'), default=timezone.now) profile = models.ForeignKey('customer.UserProfile', null=True, related_name='users') @@ -49,7 +52,9 @@ class DokUser(AbstractBaseUser, PermissionsMixin): return full_name.strip() def get_short_name(self): - "Returns the short name for the user." + """ + Returns the short name for the user. + """ return self.first_name def email_user(self, subject, message, from_email=None): @@ -59,16 +64,12 @@ class DokUser(AbstractBaseUser, PermissionsMixin): send_mail(subject, message, from_email, [self.email]) -# def has_perm(perm, obj=None): -# return True -# -# def has_module_perms(self, app_label): -# return True - - class ConfirmEmail(models.Model): - """Подтверждение Email.""" - user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='confirm_email', primary_key=True) + """ + Подтверждение Email. + """ + user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='confirm_email', + primary_key=True) is_confirmed = models.BooleanField(u'email подтвержден?', default=False) created_at = models.DateTimeField(u'Создан', auto_now_add=True) @@ -96,16 +97,24 @@ class ConfirmEmail(models.Model): class ResetKey(models.Model): """Ключ на восстановление пароля.""" - user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='restore_key', primary_key=True) - - key = models.CharField(u'Ключ доступа', max_length=40, db_index=True, - validators=[ - RegexValidator(regex='[0-9a-f]{40}', - message=u'Введите значение длиной ' - u'40 символов, состоящее из цифр 0-9 и букв a-f.'), - MinLengthValidator(40), - ] - ) + user = models.OneToOneField( + settings.AUTH_USER_MODEL, + related_name='restore_key', + primary_key=True + ) + + key = models.CharField( + u'Ключ доступа', + max_length=40, + db_index=True, + validators=[ + RegexValidator( + regex='[0-9a-f]{40}', + message=u'Введите значение длиной 40 символов, состоящее из цифр 0-9 и букв a-f.' + ), + MinLengthValidator(40), + ] + ) created_at = models.DateTimeField(u'создан', auto_now_add=True) updated_at = models.DateTimeField(u'изменен', auto_now=True) diff --git a/src/myauth/tasks.py b/src/myauth/tasks.py index 2f982a4..98828dc 100644 --- a/src/myauth/tasks.py +++ b/src/myauth/tasks.py @@ -1 +1,2 @@ -from myauth.emails import send_reset_password_email, send_registration_email, send_new_password_email +from myauth.emails import send_reset_password_email, \ + send_registration_email, send_new_password_email diff --git a/src/myauth/urls.py b/src/myauth/urls.py index 7b747ab..fbc111b 100644 --- a/src/myauth/urls.py +++ b/src/myauth/urls.py @@ -9,19 +9,38 @@ urlpatterns = patterns('', url(r'^register/$', views.register, name='myauth_register'), url(r'^login/$', views.login, name='myauth_login'), - url(r'^confirm/email/(?P[0-9a-f]{30})/$', views.confirm_registered_email, name='myauth_confirm_email'), + url(r'^confirm/email/(?P[0-9a-f]{30})/$', + views.confirm_registered_email, + name='myauth_confirm_email' + ), url(r'^reset/$', views.reset, name='myauth_reset'), - url(r'^reset/ready/$', TemplateView.as_view(template_name="myauth/reset_key_ready.html"), name='myauth_reset_key_ready'), - url(r'^reset/(?P[0-9a-f]{40})/$', views.confirm_reset, name='myauth_confirm_reset'), - - url(r'^change/password/$', views.change_password, name='myauth_change_password'), - url(r'^change/email/$', views.change_email, name='myauth_change_email'), - - url(r'^closed/$', TemplateView.as_view(template_name='myauth/registration_closed.html'), - name='myauth_registration_closed'), + url(r'^reset/ready/$', + TemplateView.as_view(template_name="myauth/reset_key_ready.html"), + name='myauth_reset_key_ready' + ), + url(r'^reset/(?P[0-9a-f]{40})/$', + views.confirm_reset, + name='myauth_confirm_reset' + ), + + url(r'^change/password/$', + views.change_password, + name='myauth_change_password' + ), + url(r'^change/email/$', + views.change_email, + name='myauth_change_email' + ), + + url(r'^closed/$', + TemplateView.as_view(template_name='myauth/registration_closed.html'), + name='myauth_registration_closed' + ), url(r'^logout/$', views.logout, name='auth_logout'), - # url(r'^rm_profile/$', views.rm_profile, name='auth_rm_profile'), - url(r'^confirm_rm_profile/$', views.confirm_rm_profile, name='auth_confirm_rm_profile'), + url(r'^confirm_rm_profile/$', + views.confirm_rm_profile, + name='auth_confirm_rm_profile' + ), ) diff --git a/src/myauth/views.py b/src/myauth/views.py index 0b19cc4..b51a284 100644 --- a/src/myauth/views.py +++ b/src/myauth/views.py @@ -26,7 +26,8 @@ REGISTRATION_OPEN = getattr(settings, 'REGISTRATION_OPEN', True) def _create_user(request, **kwargs): # создать юзера email, password = kwargs['email'], kwargs['password1'] - # сгенерировать имя пользователя. на всякий случай, добавить к нему соль, чтобы снизить вероятность коллизий + # сгенерировать имя пользователя. на всякий случай, + # добавить к нему соль, чтобы снизить вероятность коллизий _random = str(random.getrandbits(256)) username = hashlib.sha1('{}{}'.format(email, _random).encode('utf-8')).hexdigest()[:30] user = models.DokUser.objects.create_user(username=username, email=email, password=password) @@ -41,7 +42,6 @@ def _create_user(request, **kwargs): models.ConfirmEmail.objects.unconfirm(user) # аутентифицировать и залогинить new_user = auth.authenticate(username=username, password=password) - #auth.login(request, new_user) return new_user @@ -66,7 +66,7 @@ def register(request): form_prefix = 'register' template_name = 'myauth/register.html' success_url = 'myauth_login' - success_msg = u'Дождитесь письма на указанный Вами адрес и перейдите по ссылке в письме.' + success_msg = 'Дождитесь письма на указанный Вами адрес и перейдите по ссылке в письме.' registration_closed_url = 'myauth_registration_closed' if not REGISTRATION_OPEN: @@ -91,17 +91,20 @@ def confirm_registered_email(request, key): """Подтверждение зарегистрированного email.""" success_url = 'customer_profile_edit' success_msg = u'Ваш e-mail подтверждён. Спасибо за регистрацию.' - - user = get_object_or_404(models.DokUser, username__iexact = key) # ключ = имя пользователя + # ключ = имя пользователя + user = get_object_or_404(models.DokUser, username__iexact=key) models.ConfirmEmail.objects.confirm(user) messages.add_message(request, messages.INFO, success_msg) licenses = License.objects.filter(company=user.profile) if not licenses: - license = License(company=user.profile, date_from=datetime.today(), - date_to=datetime.today() + relativedelta(days=44), - pay_sum=0, - term=0, - status=-1, payform=-1) + license = License( + company=user.profile, date_from=datetime.today(), + date_to=datetime.today() + relativedelta(days=44), + pay_sum=0, + term=0, + status=-1, + payform=-1 + ) license.save() user.profile.confirmed = True user.profile.active = True @@ -137,11 +140,12 @@ def reset(request): @sensitive_variables() def confirm_reset(request, key): - """Подтверждение запроса на восстановление пароля. - Генерирует новый пароль и отправляет его на почту пользователю. + """ + Подтверждение запроса на восстановление пароля. + Генерирует новый пароль и отправляет его на почту пользователю. """ success_url = 'customer_profile_view' - success_msg = u'Новый пароль выслан на ваш e-mail.' + success_msg = 'Новый пароль выслан на ваш e-mail.' key = get_object_or_404(models.ResetKey, key__iexact=key) # новый пароль @@ -165,7 +169,7 @@ def change_password(request): form_prefix = 'change_password' template_name = 'myauth/change_password.html' success_url = 'customer_profile_view' - success_msg = u'Ваш пароль изменён на новый.' + success_msg = 'Ваш пароль изменён на новый.' if request.method == 'POST': form = form_class(user=request.user, data=request.POST, prefix=form_prefix) diff --git a/src/yandex_money/admin.py b/src/yandex_money/admin.py index 14902a9..7fa5ff8 100644 --- a/src/yandex_money/admin.py +++ b/src/yandex_money/admin.py @@ -7,28 +7,28 @@ from .models import Payment class PaymentAdmin(admin.ModelAdmin): list_display_links = ('customer_number',) list_display = ( - 'customer_number', - 'payment_type', + 'customer_number', + 'payment_type', 'order_number', 'order_amount', 'shop_amount', - 'shop_currency', - 'invoice_id', - 'status', - 'pub_date', + 'shop_currency', + 'invoice_id', + 'status', + 'pub_date', 'user', 'cps_phone', ) list_filter = ( - 'pub_date', + 'pub_date', 'status', ) search_fields = ( - 'customer_number', - 'cps_email', - 'cps_phone', + 'customer_number', + 'cps_email', + 'cps_phone', 'scid', - 'shop_id', + 'shop_id', 'invoice_id', 'order_number', ) @@ -37,4 +37,4 @@ class PaymentAdmin(admin.ModelAdmin): return False -admin.site.register(Payment, PaymentAdmin) \ No newline at end of file +admin.site.register(Payment, PaymentAdmin) diff --git a/src/yandex_money/forms.py b/src/yandex_money/forms.py index 9346f03..ea9532e 100644 --- a/src/yandex_money/forms.py +++ b/src/yandex_money/forms.py @@ -75,7 +75,13 @@ class BasePaymentForm(forms.Form): @classmethod def make_md5(cls, cd): """ - action;orderSumAmount;orderSumCurrencyPaycash;orderSumBankPaycash;shopId;invoiceId;customerNumber;shopPassword + action; + orderSumAmount; + orderSumCurrencyPaycash; + orderSumBankPaycash; + shopId;invoiceId; + customerNumber; + shopPassword """ return md5(';'.join(map(str, ( cd['action'], diff --git a/src/yandex_money/signals.py b/src/yandex_money/signals.py index 06cec6e..53f663f 100644 --- a/src/yandex_money/signals.py +++ b/src/yandex_money/signals.py @@ -3,4 +3,4 @@ from django.dispatch import Signal payment_process = Signal() -payment_completed = Signal() \ No newline at end of file +payment_completed = Signal() diff --git a/src/yandex_money/utils.py b/src/yandex_money/utils.py index 7c68785..e69de29 100644 --- a/src/yandex_money/utils.py +++ b/src/yandex_money/utils.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- \ No newline at end of file diff --git a/src/yandex_money/views.py b/src/yandex_money/views.py index 40cafbc..46d5346 100644 --- a/src/yandex_money/views.py +++ b/src/yandex_money/views.py @@ -65,10 +65,8 @@ class BaseView(View): getattr(settings, 'YANDEX_MONEY_MAIL_ADMINS_ON_PAYMENT_ERROR', True) and params.get('code') != '0' ): - mail_admins('yandexmoney_django error', u'post data: {post_data}\n\nresponse:{response}'.format( - post_data=request.POST, - response=content, - )) + mail_admins( + 'yandexmoney_django error', f'post data: {request.POST}\n\nresponse:{content}') return HttpResponse(content, content_type='application/xml')