|
|
|
|
@ -1,5 +1,5 @@ |
|
|
|
|
from decimal import Decimal |
|
|
|
|
import arrow |
|
|
|
|
|
|
|
|
|
from paymentwall import Pingback |
|
|
|
|
from polymorphic.models import PolymorphicModel |
|
|
|
|
from polymorphic.managers import PolymorphicManager |
|
|
|
|
@ -108,6 +108,62 @@ 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, |
|
|
|
|
add_days=False, date_start=None, date_end=None): |
|
|
|
|
if course_payment: |
|
|
|
|
course = course_payment.course |
|
|
|
|
user = course_payment.user |
|
|
|
|
if school_payment: |
|
|
|
|
user = school_payment.user |
|
|
|
|
weekdays = school_payment.weekdays |
|
|
|
|
add_days = school_payment.add_days |
|
|
|
|
date_start = school_payment.date_start |
|
|
|
|
date_end = school_payment.date_end |
|
|
|
|
referral_discount = 0 |
|
|
|
|
referrer_cashback = 0 |
|
|
|
|
if hasattr(user, 'referral') and not user.referral.payment: |
|
|
|
|
referral_discount = user.referral.discount |
|
|
|
|
referrer_cashback = user.referral.referrer_cashback |
|
|
|
|
discount = 0 |
|
|
|
|
if course: |
|
|
|
|
price = course.price |
|
|
|
|
else: |
|
|
|
|
aggregate = SchoolSchedule.objects.filter( |
|
|
|
|
weekday__in=weekdays, |
|
|
|
|
).aggregate( |
|
|
|
|
models.Sum('month_price'), |
|
|
|
|
) |
|
|
|
|
if add_days: |
|
|
|
|
_school_payment = SchoolPayment.objects.filter( |
|
|
|
|
add_days=False, |
|
|
|
|
date_start__lte=date_start, |
|
|
|
|
date_end__gte=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(date_start, date_end, weekdays[0]) |
|
|
|
|
all_weekday_count = weekday_in_date_range(_school_payment.date_start, _school_payment.date_end, |
|
|
|
|
weekdays[0]) |
|
|
|
|
price = Decimal(aggregate.get('month_price__sum', 0) * weekday_count // all_weekday_count) |
|
|
|
|
else: |
|
|
|
|
price = Decimal(aggregate.get('month_price__sum', 0)) |
|
|
|
|
if price >= config.SERVICE_DISCOUNT_MIN_AMOUNT: |
|
|
|
|
discount = config.SERVICE_DISCOUNT |
|
|
|
|
referral_discount = (price - discount) * referral_discount / 100 |
|
|
|
|
referrer_cashback = (price - discount) * referrer_cashback / 100 |
|
|
|
|
amount = price - discount - referral_discount |
|
|
|
|
return { |
|
|
|
|
'price': price, |
|
|
|
|
'amount': amount, |
|
|
|
|
'referral_discount': referral_discount, |
|
|
|
|
'referrer_cashback': referrer_cashback, |
|
|
|
|
'discount': discount, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
def calc_commission(self): |
|
|
|
|
return self.amount * config.SERVICE_COMMISSION / 100 |
|
|
|
|
|
|
|
|
|
@ -136,7 +192,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: |
|
|
|
|
@ -148,6 +205,13 @@ class CoursePayment(Payment): |
|
|
|
|
else: |
|
|
|
|
author_balance.amount = self.amount |
|
|
|
|
author_balance.save() |
|
|
|
|
# Если юзер реферал и нет платежа, где применялась скидка |
|
|
|
|
if hasattr(self.user, 'referral') and not self.user.referral.payment: |
|
|
|
|
# Отправляем кэшбэк |
|
|
|
|
self.user.referral.cashback(amount_data.get('referrer_cashback')) |
|
|
|
|
# Платеж - как сигнал, что скидка применилась |
|
|
|
|
self.user.referral.payment = self |
|
|
|
|
self.user.referral.save() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SchoolPayment(Payment): |
|
|
|
|
@ -168,33 +232,16 @@ 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 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) |
|
|
|
|
# Если юзер реферал и нет платежа, где применялась скидка |
|
|
|
|
if not self.add_days and hasattr(self.user, 'referral') and not self.user.referral.payment: |
|
|
|
|
# Отправляем кэшбэк |
|
|
|
|
self.user.referral.cashback(amount_data.get('referrer_cashback')) |
|
|
|
|
# Платеж - как сигнал, что скидка применилась |
|
|
|
|
self.user.referral.payment = self |
|
|
|
|
self.user.referral.save() |
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
def date_end_humanize(self): |
|
|
|
|
|