|
|
|
|
@ -1,8 +1,17 @@ |
|
|
|
|
# coding=utf-8 |
|
|
|
|
from dateutil.relativedelta import relativedelta |
|
|
|
|
|
|
|
|
|
from django.conf import settings |
|
|
|
|
from django.core.mail import EmailMessage |
|
|
|
|
from django.db import models |
|
|
|
|
from django.utils import timezone |
|
|
|
|
from yandex_money.models import Payment |
|
|
|
|
import logging |
|
|
|
|
|
|
|
|
|
from progress.models import Progress |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
logger_business_rules = logging.getLogger('business_rules') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Bill(models.Model): |
|
|
|
|
@ -13,10 +22,75 @@ class Bill(models.Model): |
|
|
|
|
blank=True, editable=False) |
|
|
|
|
description = models.TextField(verbose_name='Внутренняя заметка', blank=True) |
|
|
|
|
date = models.DateTimeField(verbose_name="Дата выставления", auto_now_add=True) |
|
|
|
|
freeze = models.BooleanField(verbose_name='Отказ от платежей', default=False) |
|
|
|
|
|
|
|
|
|
def __str__(self): |
|
|
|
|
return '%s: %s' % (self.id, self.user) |
|
|
|
|
|
|
|
|
|
def freeze_course(self): |
|
|
|
|
if self.invoice_set.exclude(status='F').exists(): |
|
|
|
|
log = False |
|
|
|
|
try: |
|
|
|
|
p = Progress.objects.get(user=self.user, course_token=str(self.course_token)) |
|
|
|
|
p.is_freeze = True |
|
|
|
|
p.save() |
|
|
|
|
except Progress.DoesNotExist: |
|
|
|
|
log = True |
|
|
|
|
|
|
|
|
|
if log: |
|
|
|
|
logger_business_rules.info('Отказ от платежей прошёл успешно', exc_info=True, extra={ |
|
|
|
|
'description': 'The privileges were not taken away, as they were not granted', |
|
|
|
|
'user': self.user, |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
msg = EmailMessage( |
|
|
|
|
'Вы откозались от оплаты по счёту', |
|
|
|
|
"""Вы откозались от оплаты по счёту. |
|
|
|
|
Вы сможете продолжить оплату в личном кабинете""", |
|
|
|
|
to=[self.user.email], |
|
|
|
|
bcc=[self.opener.email], |
|
|
|
|
reply_to=[self.opener.email], |
|
|
|
|
) |
|
|
|
|
msg.send() |
|
|
|
|
|
|
|
|
|
self.freeze = True |
|
|
|
|
self.save() |
|
|
|
|
|
|
|
|
|
else: |
|
|
|
|
logger_business_rules.warning('Попытка нарушения правила отказа от платежей', exc_info=True, extra={ |
|
|
|
|
'description': 'All payments already paid', |
|
|
|
|
'user': self.user, |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
def unfreeze_course(self, force=False): |
|
|
|
|
if force or self.invoice_set.exclude(status='F')\ |
|
|
|
|
.filter(expected_date__lt=timezone.now() + relativedelta(days=1)).exists(): |
|
|
|
|
if self.invoice_set.filter(status='F').exclude(expected_date__lt=timezone.now()).exists(): |
|
|
|
|
try: |
|
|
|
|
p = Progress.objects.get(user=self.user, course_token=str(self.course_token)) |
|
|
|
|
p.is_freeze = False |
|
|
|
|
p.save() |
|
|
|
|
except Progress.DoesNotExist: |
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
msg = EmailMessage( |
|
|
|
|
'Вы возобновили оплату по счёту', |
|
|
|
|
"""Вы возобновили оплату по счёту.""", |
|
|
|
|
to=[self.user.email], |
|
|
|
|
bcc=[self.opener.email], |
|
|
|
|
reply_to=[self.opener.email], |
|
|
|
|
) |
|
|
|
|
msg.send() |
|
|
|
|
|
|
|
|
|
self.freeze = False |
|
|
|
|
self.save() |
|
|
|
|
|
|
|
|
|
else: |
|
|
|
|
logger_business_rules.warning('Попытка нарушения правила возобновления платежей', exc_info=True, extra={ |
|
|
|
|
'description': 'Excepted date more than one day', |
|
|
|
|
'user': self.user, |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
def get_full_price(self): |
|
|
|
|
return sum([i.price for i in self.invoice_set.all() if not i.price is None]) |
|
|
|
|
|
|
|
|
|
@ -59,7 +133,9 @@ class Invoice(models.Model): |
|
|
|
|
blank=True, editable=False) |
|
|
|
|
bill = models.ForeignKey(to=Bill, verbose_name="Связный счёт") |
|
|
|
|
is_open = models.BooleanField(default=True, verbose_name="Открывает ли платёж курс") |
|
|
|
|
date = models.DateTimeField(auto_now_add=True) |
|
|
|
|
date = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания платежа") |
|
|
|
|
expected_date = models.DateTimeField(default=timezone.now, verbose_name="Ожидаемая дата платежа") |
|
|
|
|
date_of_payment = models.DateTimeField(verbose_name="Дата фактической оплаты", blank=True, null=True) |
|
|
|
|
|
|
|
|
|
def get_comment(self): |
|
|
|
|
return '''Вам выставлен счёт,''' if \ |
|
|
|
|
@ -86,7 +162,19 @@ class Invoice(models.Model): |
|
|
|
|
|
|
|
|
|
class InvoiceRebilling(Invoice): |
|
|
|
|
rebilling_on = models.BooleanField(verbose_name='Повторять платеж', default=False, editable=False) |
|
|
|
|
pay_count = models.SmallIntegerField(verbose_name='Всего платежей', editable=False) |
|
|
|
|
|
|
|
|
|
def create_child_pays(self, count): |
|
|
|
|
for idx in range(int(count)-1): |
|
|
|
|
InvoiceRebilling.objects.create( |
|
|
|
|
bill=self.bill, |
|
|
|
|
comment=self.comment, |
|
|
|
|
method=self.method, |
|
|
|
|
status='W', |
|
|
|
|
is_open=self.is_open, |
|
|
|
|
price=self.price, |
|
|
|
|
rebilling_on=False, |
|
|
|
|
expected_date=(timezone.now() + relativedelta(months=idx+1)), |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
class Meta: |
|
|
|
|
verbose_name = 'Повторный платёж' |
|
|
|
|
|