|
|
|
|
@ -1,4 +1,5 @@ |
|
|
|
|
import arrow |
|
|
|
|
from django.db.models import Func, F |
|
|
|
|
|
|
|
|
|
from paymentwall import Pingback |
|
|
|
|
from polymorphic.models import PolymorphicModel |
|
|
|
|
@ -11,7 +12,7 @@ from django.core.validators import RegexValidator |
|
|
|
|
from django.utils.timezone import now |
|
|
|
|
from django.conf import settings |
|
|
|
|
|
|
|
|
|
from project.utils import weekday_in_date_range |
|
|
|
|
from project.utils import weekdays_in_date_range |
|
|
|
|
|
|
|
|
|
from apps.course.models import Course |
|
|
|
|
from apps.config.models import Config |
|
|
|
|
@ -109,6 +110,58 @@ class Payment(PolymorphicModel): |
|
|
|
|
verbose_name_plural = 'Платежи' |
|
|
|
|
ordering = ('created_at',) |
|
|
|
|
|
|
|
|
|
@classmethod |
|
|
|
|
def calc_amount(cls, course_payment=None, school_payment=None, user=None, course=None, weekdays=None): |
|
|
|
|
if course_payment: |
|
|
|
|
course = course_payment.course |
|
|
|
|
user = course_payment.user |
|
|
|
|
if school_payment: |
|
|
|
|
user = school_payment.user |
|
|
|
|
weekdays = school_payment.weekdays |
|
|
|
|
discount = 0 |
|
|
|
|
price = 0 |
|
|
|
|
if course: |
|
|
|
|
price = course.price |
|
|
|
|
else: |
|
|
|
|
school_payments = SchoolPayment.objects.filter( |
|
|
|
|
user=user, |
|
|
|
|
date_start__lte=now().date(), |
|
|
|
|
date_end__gte=now().date(), |
|
|
|
|
add_days=False, |
|
|
|
|
status__in=[ |
|
|
|
|
Pingback.PINGBACK_TYPE_REGULAR, |
|
|
|
|
Pingback.PINGBACK_TYPE_GOODWILL, |
|
|
|
|
Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED, |
|
|
|
|
], |
|
|
|
|
) |
|
|
|
|
school_schedules_purchased = school_payments.annotate( |
|
|
|
|
joined_weekdays=Func(F('weekdays'), function='unnest', ) |
|
|
|
|
).values_list('joined_weekdays', flat=True).distinct() |
|
|
|
|
weekdays = set(map(int, weekdays)) - set(school_schedules_purchased) |
|
|
|
|
school_schedules = SchoolSchedule.objects.filter( |
|
|
|
|
weekday__in=weekdays, |
|
|
|
|
) |
|
|
|
|
prev_school_payment = school_payments.last() |
|
|
|
|
add_days = bool(prev_school_payment) |
|
|
|
|
if add_days: |
|
|
|
|
weekdays_count = weekdays_in_date_range(now().date(), prev_school_payment.date_end) |
|
|
|
|
all_weekdays_count = weekdays_in_date_range(prev_school_payment.date_start, prev_school_payment.date_end) |
|
|
|
|
for ss in school_schedules: |
|
|
|
|
price += ss.month_price // all_weekdays_count.get(ss.weekday, 0) * weekdays_count.get( |
|
|
|
|
ss.weekday, 0) |
|
|
|
|
else: |
|
|
|
|
price = school_schedules.aggregate( |
|
|
|
|
models.Sum('month_price'), |
|
|
|
|
).get('month_price__sum', 0) |
|
|
|
|
if not (school_payment and school_payment.id) and price >= config.SERVICE_DISCOUNT_MIN_AMOUNT: |
|
|
|
|
discount = config.SERVICE_DISCOUNT |
|
|
|
|
amount = price - discount |
|
|
|
|
return { |
|
|
|
|
'price': price, |
|
|
|
|
'amount': amount, |
|
|
|
|
'discount': discount, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
def calc_commission(self): |
|
|
|
|
return self.amount * config.SERVICE_COMMISSION / 100 |
|
|
|
|
|
|
|
|
|
@ -137,7 +190,8 @@ class CoursePayment(Payment): |
|
|
|
|
verbose_name_plural = 'Платежи за курсы' |
|
|
|
|
|
|
|
|
|
def save(self, *args, **kwargs): |
|
|
|
|
self.amount = self.course.price |
|
|
|
|
amount_data = Payment.calc_amount(course_payment=self) |
|
|
|
|
self.amount = amount_data.get('amount') |
|
|
|
|
super().save(*args, **kwargs) |
|
|
|
|
author_balance = getattr(self, 'authorbalance', None) |
|
|
|
|
if not author_balance: |
|
|
|
|
@ -169,32 +223,8 @@ class SchoolPayment(Payment): |
|
|
|
|
return days |
|
|
|
|
|
|
|
|
|
def save(self, *args, **kwargs): |
|
|
|
|
aggregate = SchoolSchedule.objects.filter( |
|
|
|
|
weekday__in=self.weekdays, |
|
|
|
|
).aggregate( |
|
|
|
|
models.Sum('month_price'), |
|
|
|
|
) |
|
|
|
|
if self.add_days: |
|
|
|
|
_school_payment = SchoolPayment.objects.filter( |
|
|
|
|
add_days=False, |
|
|
|
|
date_start__lte=self.date_start, |
|
|
|
|
date_end__gte=self.date_end, |
|
|
|
|
status__in=[ |
|
|
|
|
Pingback.PINGBACK_TYPE_REGULAR, |
|
|
|
|
Pingback.PINGBACK_TYPE_GOODWILL, |
|
|
|
|
Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED, |
|
|
|
|
], |
|
|
|
|
).last() |
|
|
|
|
weekday_count = weekday_in_date_range(self.date_start, self.date_end, self.weekdays[0]) |
|
|
|
|
all_weekday_count = weekday_in_date_range(_school_payment.date_start, _school_payment.date_end, self.weekdays[0]) |
|
|
|
|
month_price_sum = aggregate.get('month_price__sum', 0) * weekday_count // all_weekday_count |
|
|
|
|
else: |
|
|
|
|
month_price_sum = aggregate.get('month_price__sum', 0) |
|
|
|
|
if self.id is None and month_price_sum >= config.SERVICE_DISCOUNT_MIN_AMOUNT: |
|
|
|
|
discount = config.SERVICE_DISCOUNT |
|
|
|
|
else: |
|
|
|
|
discount = 0 |
|
|
|
|
self.amount = month_price_sum - discount |
|
|
|
|
amount_data = Payment.calc_amount(school_payment=self) |
|
|
|
|
self.amount = amount_data.get('amount') |
|
|
|
|
super().save(*args, **kwargs) |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
|