|
|
|
|
@ -1,5 +1,7 @@ |
|
|
|
|
from decimal import Decimal |
|
|
|
|
import arrow |
|
|
|
|
from django.db.models import Func, F |
|
|
|
|
|
|
|
|
|
from paymentwall import Pingback |
|
|
|
|
from polymorphic.models import PolymorphicModel |
|
|
|
|
from polymorphic.managers import PolymorphicManager |
|
|
|
|
@ -11,7 +13,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 |
|
|
|
|
@ -110,17 +112,14 @@ class Payment(PolymorphicModel): |
|
|
|
|
ordering = ('created_at',) |
|
|
|
|
|
|
|
|
|
@classmethod |
|
|
|
|
def calc_amount(cls, payment=None, user=None, course=None, weekdays=None, |
|
|
|
|
add_days=False, date_start=None, date_end=None): |
|
|
|
|
def calc_amount(cls, payment=None, user=None, course=None, weekdays=None): |
|
|
|
|
if isinstance(payment, CoursePayment): |
|
|
|
|
course = payment.course |
|
|
|
|
user = payment.user |
|
|
|
|
if isinstance(payment, SchoolPayment): |
|
|
|
|
user = payment.user |
|
|
|
|
weekdays = payment.weekdays |
|
|
|
|
add_days = payment.add_days |
|
|
|
|
date_start = payment.date_start |
|
|
|
|
date_end = payment.date_end |
|
|
|
|
price = 0 |
|
|
|
|
referral_bonus = 0 |
|
|
|
|
referrer_bonus = 0 |
|
|
|
|
if hasattr(user, 'referral') and not user.referral.payment: |
|
|
|
|
@ -130,29 +129,40 @@ class Payment(PolymorphicModel): |
|
|
|
|
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( |
|
|
|
|
if user: |
|
|
|
|
school_payments = SchoolPayment.objects.filter( |
|
|
|
|
user=user, |
|
|
|
|
date_start__lte=now().date(), |
|
|
|
|
date_end__gte=now().date(), |
|
|
|
|
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) |
|
|
|
|
) |
|
|
|
|
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) |
|
|
|
|
prev_school_payment = school_payments.last() |
|
|
|
|
add_days = bool(prev_school_payment) |
|
|
|
|
else: |
|
|
|
|
price = Decimal(aggregate.get('month_price__sum', 0)) |
|
|
|
|
if price >= config.SERVICE_DISCOUNT_MIN_AMOUNT: |
|
|
|
|
add_days = False |
|
|
|
|
school_schedules = SchoolSchedule.objects.filter( |
|
|
|
|
weekday__in=weekdays, |
|
|
|
|
) |
|
|
|
|
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 (payment and payment.id) and price >= config.SERVICE_DISCOUNT_MIN_AMOUNT: |
|
|
|
|
discount = config.SERVICE_DISCOUNT |
|
|
|
|
amount = price - discount |
|
|
|
|
referral_bonus = round(amount * referral_bonus / 100) |
|
|
|
|
@ -218,6 +228,7 @@ class CoursePayment(Payment): |
|
|
|
|
verbose_name_plural = 'Платежи за курсы' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SchoolPayment(Payment): |
|
|
|
|
weekdays = ArrayField(models.IntegerField(), size=7, verbose_name='Дни недели') |
|
|
|
|
add_days = models.BooleanField('Докупленные дни', default=False) |
|
|
|
|
|