From e6d4988b9e9e1991e223ff4d0692b008b8b1b5a5 Mon Sep 17 00:00:00 2001 From: Evgeniy Shabanov Date: Mon, 19 Mar 2018 14:58:06 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=B2=D1=82=D0=BE=D1=80=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D0=BF=D0=BB=D0=B0=D1=82=D0=B5=D0=B6=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- finance/admin.py | 7 +++++- finance/models.py | 2 ++ finance/signals.py | 4 ++-- finance/tasks.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++ finance/views.py | 7 ++++++ 5 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 finance/tasks.py diff --git a/finance/admin.py b/finance/admin.py index 04b13c6..8143c83 100755 --- a/finance/admin.py +++ b/finance/admin.py @@ -3,5 +3,10 @@ from django.contrib import admin from finance.models import Bill, Invoice + +class InvoiceAdmin(admin.ModelAdmin): + list_display = ('__str__', 'rebilling_on', 'rebilling') + + admin.site.register(Bill) -admin.site.register(Invoice) \ No newline at end of file +admin.site.register(Invoice, InvoiceAdmin) diff --git a/finance/models.py b/finance/models.py index 9516873..9d12e5c 100755 --- a/finance/models.py +++ b/finance/models.py @@ -54,6 +54,8 @@ class Invoice(models.Model): bill = models.ForeignKey(to=Bill, verbose_name="Связный счёт") is_open = models.BooleanField(default=True, verbose_name="Открывает ли платёж курс") date = models.DateTimeField(auto_now_add=True) + rebilling_on = models.BooleanField(verbose_name='Повторять платеж', default=False, editable=False) + rebilling = models.BooleanField(verbose_name='Повторный платеж', default=False, editable=False) def __str__(self): return '%s:%s %s' % (self.id, self.get_status_display(), self.bill.user) diff --git a/finance/signals.py b/finance/signals.py index 110a4f5..85e9d02 100644 --- a/finance/signals.py +++ b/finance/signals.py @@ -16,7 +16,7 @@ def invoice_signal(instance, **kwargs): course = Course.objects.get(token=instance.bill.course_token) - if instance.yandex_pay and instance.method == 'Y' and instance.status == 'P': + if instance.yandex_pay and instance.method == 'Y' and instance.status == 'P' and not instance.rebilling: msg = EmailMessage( 'Вам выставлен новый счёт', '''Вам выставлен счёт, для оплаты перейдите по ссылке @@ -28,7 +28,7 @@ def invoice_signal(instance, **kwargs): ) msg.send() - if instance.status == 'F': + if instance.status == 'F' and not instance.rebilling: if instance.is_open: try: Progress.objects.get( diff --git a/finance/tasks.py b/finance/tasks.py new file mode 100644 index 0000000..8b04a8a --- /dev/null +++ b/finance/tasks.py @@ -0,0 +1,54 @@ +import json +from datetime import datetime, timedelta + +from django_celery_beat.models import CrontabSchedule, PeriodicTask +from yandex_money.models import Payment + +from finance.models import Invoice +from lms import celery_app + + +def setup_periodic_billing(invoice_id): + # TODO: настроить периодичность и срок окончания + schedule, _ = CrontabSchedule.objects.get_or_create( + minute='*', + hour='*', + day_of_week='*', + day_of_month='*', + month_of_year='*' + ) + PeriodicTask.objects.create( + crontab=schedule, + name='Periodic billing #{}'.format(invoice_id), + task='finance.tasks.periodic_billing', + args=json.dumps([invoice_id]), + expires=datetime.utcnow() + timedelta(minutes=5) + ) + + +@celery_app.task +def periodic_billing(invoice_id): + try: + sample = Invoice.objects.get(id=invoice_id) + except Invoice.DoesNotExist: + raise ValueError('Платеж с id={} не найден'.format(invoice_id)) + bill = sample.bill + invoice = Invoice.objects.create( + status='P', + price=sample.price, + method=sample.method, + rebilling=True, + bill=bill + ) + if invoice.method == 'Y': + user = bill.user + yandex_pay = Payment.objects.create( + invoice_id=sample.yandex_pay.invoice_id, + order_amount=invoice.price, + customer_number=user.id, + user=user, + cps_email=user.email + ) + invoice.yandex_pay = yandex_pay + invoice.save() + # TODO: запрос repeatCardPayment diff --git a/finance/views.py b/finance/views.py index c97513f..7cb7489 100644 --- a/finance/views.py +++ b/finance/views.py @@ -17,6 +17,7 @@ from django.conf import settings from courses.api import CourseParamsApi from finance.models import Bill, Invoice from finance.serializers import BillSerializer, InvoiceSerializer +from finance.tasks import setup_periodic_billing from lms.global_decorators import transaction_decorator from lms.tools import get_real_name from django.utils import timezone @@ -155,6 +156,7 @@ class YandexPay(APIView): 'customerNumber': pay.customer_number, 'orderNumber': pay.order_number, 'cps_email': pay.cps_email, + 'rebillingOn': pay.invoice.rebilling_on, 'shopSuccessURL': settings.YANDEX_MONEY_SUCCESS_URL, 'shopFailURL': settings.YANDEX_MONEY_FAIL_URL, }) @@ -273,12 +275,17 @@ class YandexAvisoView(APIView): pay.shop_amount = data['shopSumAmount'] pay.status = Payment.STATUS.SUCCESS + pay.invoice_id = data['invoiceId'] pay.save() xml_res = """ """ % (pay.performed_datetime, str(data['invoiceId']), str(pay.shop_id)) logger_yandex.info(xml_res) + invoice = pay.invoice + if invoice.rebilling_on: + setup_periodic_billing(invoice.id) + return HttpResponse(xml_res, content_type='application/xml')