|
|
|
|
@ -128,7 +128,7 @@ class Payment(PolymorphicModel): |
|
|
|
|
ordering = ('created_at',) |
|
|
|
|
|
|
|
|
|
@classmethod |
|
|
|
|
def ajust_date_bounds(cls, date_start=None, date_end=None, is_camp=False): |
|
|
|
|
def adjust_date_bounds(cls, date_start=None, date_end=None, is_camp=False): |
|
|
|
|
school_start = date(now().year, 9, 1) |
|
|
|
|
school_end = date(now().year, 5, 31) |
|
|
|
|
camp_start = date(now().year, 6, 1) |
|
|
|
|
@ -158,7 +158,7 @@ class Payment(PolymorphicModel): |
|
|
|
|
date_start = date_start or now().date() |
|
|
|
|
if isinstance(date_start, datetime): |
|
|
|
|
date_start = date_start.date() |
|
|
|
|
date_start = cls.ajust_date_bounds(date_start=date_start, is_camp=is_camp) |
|
|
|
|
date_start = cls.adjust_date_bounds(date_start=date_start, is_camp=is_camp) |
|
|
|
|
if is_camp and date_start.month == 6 and date_start.day > 16: |
|
|
|
|
date_start = date_start.replace(month=7, day=1) |
|
|
|
|
date_end = arrow.get(date_start + timedelta(days=days), settings.TIME_ZONE).shift(months=months).date() - timedelta(1) |
|
|
|
|
@ -166,11 +166,11 @@ class Payment(PolymorphicModel): |
|
|
|
|
if is_camp or (date_start.month == 2 and date_start.day >= 28) or (date_start.day == 31 and date_end.day <= 30) \ |
|
|
|
|
or (date_start.month == 1 and date_start.day >= 29 and date_end.day == 28): |
|
|
|
|
date_end = date_start.replace(day=1, month=date_start.month + 1) - timedelta(1) |
|
|
|
|
date_end = cls.ajust_date_bounds(date_end=date_end, is_camp=is_camp) |
|
|
|
|
date_end = cls.adjust_date_bounds(date_end=date_end, is_camp=is_camp) |
|
|
|
|
return [date_start, date_end] |
|
|
|
|
|
|
|
|
|
@classmethod |
|
|
|
|
def calc_amount(cls, payment=None, user=None, course=None, date_start=None, weekdays=None, is_camp=False): |
|
|
|
|
def calc_amount(cls, package=None, payment=None, user=None, course=None, date_start=None, weekdays=None, is_camp=False): |
|
|
|
|
price = 0 |
|
|
|
|
discount = 0 |
|
|
|
|
referral_bonus = 0 |
|
|
|
|
@ -180,14 +180,14 @@ class Payment(PolymorphicModel): |
|
|
|
|
user = payment.user |
|
|
|
|
if isinstance(payment, SchoolPayment): |
|
|
|
|
user = payment.user |
|
|
|
|
weekdays = payment.weekdays |
|
|
|
|
date_start = payment.date_start |
|
|
|
|
package=payment.package |
|
|
|
|
if isinstance(payment, DrawingCampPayment): |
|
|
|
|
user = payment.user |
|
|
|
|
date_start = payment.date_start |
|
|
|
|
if issubclass(cls, DrawingCampPayment): |
|
|
|
|
is_camp = True |
|
|
|
|
date_start, date_end = Payment.get_date_range(date_start, months=1, is_camp=is_camp) |
|
|
|
|
date_start, date_end = Payment.get_date_range(date_start, months=package.duration if package else 1, is_camp=is_camp) |
|
|
|
|
if hasattr(user, 'referral') and not user.referral.payment: |
|
|
|
|
referral_bonus = user.referral.bonus |
|
|
|
|
referrer_bonus = user.referral.referrer_bonus |
|
|
|
|
@ -215,40 +215,22 @@ class Payment(PolymorphicModel): |
|
|
|
|
date_end__gte=date_start, |
|
|
|
|
status__in=Payment.PW_PAID_STATUSES, |
|
|
|
|
) |
|
|
|
|
school_schedules_purchased = school_payments.annotate( |
|
|
|
|
joined_weekdays=Func(F('weekdays'), function='unnest', ) |
|
|
|
|
).values_list('joined_weekdays', flat=True).distinct() |
|
|
|
|
weekdays = list(set(map(int, weekdays)) - set(school_schedules_purchased)) |
|
|
|
|
prev_school_payment = school_payments.filter(add_days=False).last() |
|
|
|
|
add_days = bool(prev_school_payment) |
|
|
|
|
else: |
|
|
|
|
add_days = False |
|
|
|
|
school_schedules = SchoolSchedule.objects.filter( |
|
|
|
|
weekday__in=weekdays, |
|
|
|
|
is_camp=False, |
|
|
|
|
) |
|
|
|
|
if add_days: |
|
|
|
|
date_end = prev_school_payment.date_end |
|
|
|
|
weekdays_count = weekdays_in_date_range(date_start, 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) |
|
|
|
|
if prev_school_payment: |
|
|
|
|
date_start, date_end = Payment.get_date_range(prev_school_payment.date_end + timedelta(1), |
|
|
|
|
months=package.duration, is_camp=False) |
|
|
|
|
school_schedules = SchoolSchedule.objects.filter(is_camp=False).exclude(title='') |
|
|
|
|
weekdays = list(school_schedules.values_list('weekday', flat=True)) |
|
|
|
|
# FIXME после мая 2019 убрать? |
|
|
|
|
# Если хотят купить школу в мае, то оплатить ее можно только до 31 мая, потом школа закроется |
|
|
|
|
if date_start.month == 5: |
|
|
|
|
weekdays_count = weekdays_in_date_range(date_start, date_end) |
|
|
|
|
weekdays_count = sum(weekdays_count[wd] for wd in weekdays) |
|
|
|
|
all_weekdays_count = weekdays_in_date_range(date_start.replace(day=1), date_end) |
|
|
|
|
all_weekdays_count = sum(all_weekdays_count[wd] for wd in weekdays) |
|
|
|
|
price = package.price // all_weekdays_count * weekdays_count |
|
|
|
|
else: |
|
|
|
|
# FIXME после мая 2019 убрать? |
|
|
|
|
# Если хотят купить школу в мае, то оплатить ее можно только до 31 мая, потом школа закроется |
|
|
|
|
if date_start.month == 5: |
|
|
|
|
weekdays_count = weekdays_in_date_range(date_start, date_end) |
|
|
|
|
all_weekdays_count = weekdays_in_date_range(date_start.replace(day=1), 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 |
|
|
|
|
price = package.price |
|
|
|
|
amount = price - discount |
|
|
|
|
referral_bonus = round(amount * referral_bonus / 100) |
|
|
|
|
referrer_bonus = round(amount * referrer_bonus / 100) |
|
|
|
|
@ -299,35 +281,6 @@ class Payment(PolymorphicModel): |
|
|
|
|
self.weekdays = amount_data.get('weekdays') |
|
|
|
|
super().save(*args, **kwargs) |
|
|
|
|
if self.is_paid(): |
|
|
|
|
if isinstance(self, PackagePayment): |
|
|
|
|
year_start = date(now().year, 1, 1) |
|
|
|
|
year_end = date(now().year, 12, 31) |
|
|
|
|
school_start = date(now().year, 9, 1) |
|
|
|
|
school_end = date(now().year, 5, 31) |
|
|
|
|
camp_start = date(now().year, 6, 1) |
|
|
|
|
camp_end = date(now().year, 8, 31) |
|
|
|
|
# TODO |
|
|
|
|
if dates_overlap(self.date_start, self.date_end, camp_start, camp_end): |
|
|
|
|
cp_amount_date = DrawingCampPayment.calc_amount() |
|
|
|
|
DrawingCampPayment.objects.create( |
|
|
|
|
user=self.user, |
|
|
|
|
roistat_visit=self.roistat_visit, |
|
|
|
|
date_start=self.date_start, |
|
|
|
|
date_end=self.date_end, |
|
|
|
|
amount=0, |
|
|
|
|
status=self.status, |
|
|
|
|
) |
|
|
|
|
if dates_overlap(self.date_start, self.date_end, school_start, year_end)\ |
|
|
|
|
or dates_overlap(self.date_start, self.date_end, year_start, school_end): |
|
|
|
|
SchoolPayment.objects.create( |
|
|
|
|
user=self.user, |
|
|
|
|
weekdays=[1, 2, 3, 4, 5, 6, 7], |
|
|
|
|
roistat_visit=self.roistat_visit, |
|
|
|
|
date_start=self.date_start, |
|
|
|
|
date_end=self.date_end, |
|
|
|
|
amount=0, |
|
|
|
|
status=self.status, |
|
|
|
|
) |
|
|
|
|
if isinstance(self, CoursePayment): |
|
|
|
|
if not getattr(self, 'authorbalance', None): |
|
|
|
|
AuthorBalance.objects.create( |
|
|
|
|
@ -368,6 +321,7 @@ class CoursePayment(Payment): |
|
|
|
|
class SchoolPayment(Payment): |
|
|
|
|
weekdays = ArrayField(models.IntegerField(), size=7, verbose_name='Дни недели') |
|
|
|
|
add_days = models.BooleanField('Докупленные дни', default=False) |
|
|
|
|
package = models.ForeignKey(Package, null=True, blank=True, on_delete=models.SET_NULL) |
|
|
|
|
date_start = models.DateField('Дата начала подписки', null=True, blank=True) |
|
|
|
|
date_end = models.DateField('Дата окончания подписки', null=True, blank=True) |
|
|
|
|
|
|
|
|
|
@ -415,14 +369,6 @@ class GiftCertificatePayment(Payment): |
|
|
|
|
verbose_name_plural = 'Платежи за подарочные сертификаты' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PackagePayment(Payment): |
|
|
|
|
date_start = models.DateField('Дата начала подписки', null=True, blank=True) |
|
|
|
|
date_end = models.DateField('Дата окончания подписки', null=True, blank=True) |
|
|
|
|
package = models.ForeignKey(Package, on_delete=models.CASCADE) |
|
|
|
|
school_payment = models.ForeignKey(SchoolPayment, on_delete=models.SET_NULL, null=True, blank=True) |
|
|
|
|
camp_payment = models.ForeignKey(DrawingCampPayment, on_delete=models.SET_NULL, null=True, blank=True) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class UserBonus(models.Model): |
|
|
|
|
ACTION_FILL_PROFILE = 'fill_profile' |
|
|
|
|
ACTION_PAID_ONE_MORE = 'paid_one_more' |
|
|
|
|
|