From e6d4988b9e9e1991e223ff4d0692b008b8b1b5a5 Mon Sep 17 00:00:00 2001 From: Evgeniy Shabanov Date: Mon, 19 Mar 2018 14:58:06 +0300 Subject: [PATCH 1/9] =?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') From 6c61b81e13fff92946017376b18914f3bded8839 Mon Sep 17 00:00:00 2001 From: Evgeniy Shabanov Date: Wed, 21 Mar 2018 13:13:50 +0300 Subject: [PATCH 2/9] =?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/tasks.py | 54 ++++++++++++++++++++++++++++++++++++++---------- finance/views.py | 5 ++--- lms/settings.py | 3 +++ 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/finance/tasks.py b/finance/tasks.py index 8b04a8a..a28b3ae 100644 --- a/finance/tasks.py +++ b/finance/tasks.py @@ -1,38 +1,51 @@ import json from datetime import datetime, timedelta +import logging + +import os +import requests from django_celery_beat.models import CrontabSchedule, PeriodicTask from yandex_money.models import Payment from finance.models import Invoice from lms import celery_app +from django.conf import settings + + +logger_yandex = logging.getLogger('yandex_money') -def setup_periodic_billing(invoice_id): +def setup_periodic_billing(order_number): # TODO: настроить периодичность и срок окончания + # 12:00 первого числа каждого месяца schedule, _ = CrontabSchedule.objects.get_or_create( - minute='*', - hour='*', + minute='0', + hour='12', day_of_week='*', - day_of_month='*', + day_of_month='1', month_of_year='*' ) PeriodicTask.objects.create( crontab=schedule, - name='Periodic billing #{}'.format(invoice_id), + name='Periodic billing (order_number={})'.format(order_number), task='finance.tasks.periodic_billing', - args=json.dumps([invoice_id]), - expires=datetime.utcnow() + timedelta(minutes=5) + kwargs=json.dumps({ + 'order_number': order_number + }), + expires=datetime.utcnow() + timedelta(days=180) # в течение полугода ) @celery_app.task -def periodic_billing(invoice_id): +def periodic_billing(order_number): try: - sample = Invoice.objects.get(id=invoice_id) + sample = Invoice.objects.get(yandex_pay__order_number=order_number) except Invoice.DoesNotExist: - raise ValueError('Платеж с id={} не найден'.format(invoice_id)) + raise ValueError('Номер заказа {} не найден'.format(order_number)) + bill = sample.bill + invoice = Invoice.objects.create( status='P', price=sample.price, @@ -40,6 +53,7 @@ def periodic_billing(invoice_id): rebilling=True, bill=bill ) + if invoice.method == 'Y': user = bill.user yandex_pay = Payment.objects.create( @@ -51,4 +65,22 @@ def periodic_billing(invoice_id): ) invoice.yandex_pay = yandex_pay invoice.save() - # TODO: запрос repeatCardPayment + + repeat_card_payment(invoice) + + +def repeat_card_payment(invoice): + resp = requests.post(settings.YANDEX_MONEY_MWS_URL + 'repeatCardPayment', + data={ + 'clientOrderId': invoice.id, # уникальное возрастающее целое число + 'invoiceId': invoice.yandex_pay.invoice_id, + 'amount': invoice.price, + 'orderNumber': invoice.yandex_pay.order_number + }, + cert=( + os.path.join(settings.SSL_ROOT, 'skillbox.cer'), + os.path.join(settings.SSL_ROOT, 'skillbox.key') + ), + verify=os.path.join(settings.SSL_ROOT, 'yamoney_chain.cer')) + + logger_yandex.info(resp.text) diff --git a/finance/views.py b/finance/views.py index 7cb7489..0445e70 100644 --- a/finance/views.py +++ b/finance/views.py @@ -282,9 +282,8 @@ class YandexAvisoView(APIView): logger_yandex.info(xml_res) - invoice = pay.invoice - if invoice.rebilling_on: - setup_periodic_billing(invoice.id) + if pay.invoice.rebilling_on: + setup_periodic_billing(pay.order_number) return HttpResponse(xml_res, content_type='application/xml') diff --git a/lms/settings.py b/lms/settings.py index b4ae38d..56153dd 100644 --- a/lms/settings.py +++ b/lms/settings.py @@ -57,6 +57,7 @@ YANDEX_MONEY_SHOP_ID = '157133' YANDEX_MONEY_SHOP_PASSWORD = 'nu5Xefise' YANDEX_MONEY_FAIL_URL = '%s/api/v1/finance/yandex/fail/' % DOMAIN YANDEX_MONEY_SUCCESS_URL = '%s/' % DOMAIN +YANDEX_MONEY_MWS_URL = 'https://penelope.yamoney.ru/webservice/mws/api/' # информировать о случаях, когда модуль вернул Яндекс.Кассе ошибку YANDEX_MONEY_MAIL_ADMINS_ON_PAYMENT_ERROR = True # Application definition @@ -190,6 +191,8 @@ STATIC_ROOT = os.path.join(BASE_DIR, 'static') STATIC_URL = '/static/' +SSL_ROOT = os.path.join(BASE_DIR, 'ssl') + RAVEN_CONFIG = { 'dsn': 'http://1a09557dbd144e52af4b14bea569c114:fbb5dfaa39e64f02a1b4cc7ac665d7d7@sentry.skillbox.ru/7' } From 3976bbf2ff7660a6ee9326886f79c270d88186d1 Mon Sep 17 00:00:00 2001 From: Evgeniy Shabanov Date: Thu, 22 Mar 2018 14:21:36 +0300 Subject: [PATCH 3/9] =?UTF-8?q?=D0=9C=D0=B8=D0=B3=D1=80=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- finance/migrations/0004_auto_20180321_1653.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 finance/migrations/0004_auto_20180321_1653.py diff --git a/finance/migrations/0004_auto_20180321_1653.py b/finance/migrations/0004_auto_20180321_1653.py new file mode 100644 index 0000000..b00a881 --- /dev/null +++ b/finance/migrations/0004_auto_20180321_1653.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.6 on 2018-03-21 16:53 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('finance', '0003_auto_20180315_1358'), + ] + + operations = [ + migrations.AddField( + model_name='invoice', + name='rebilling', + field=models.BooleanField(default=False, editable=False, verbose_name='Повторный платеж'), + ), + migrations.AddField( + model_name='invoice', + name='rebilling_on', + field=models.BooleanField(default=False, editable=False, verbose_name='Повторять платеж'), + ), + ] From a8657d8b5a9a2439cfe8b926dc8a1dcc4c068249 Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 30 Mar 2018 11:22:34 +0300 Subject: [PATCH 4/9] finance email --- ...180321_1653.py => 0006_auto_20180330_1121.py} | 16 ++++++++++++++-- finance/models.py | 16 +--------------- template/mail/sales/back_set_bill.html | 10 ++++++++++ template/mail/sales/back_set_bill.txt | 0 4 files changed, 25 insertions(+), 17 deletions(-) rename finance/migrations/{0004_auto_20180321_1653.py => 0006_auto_20180330_1121.py} (59%) create mode 100644 template/mail/sales/back_set_bill.html create mode 100644 template/mail/sales/back_set_bill.txt diff --git a/finance/migrations/0004_auto_20180321_1653.py b/finance/migrations/0006_auto_20180330_1121.py similarity index 59% rename from finance/migrations/0004_auto_20180321_1653.py rename to finance/migrations/0006_auto_20180330_1121.py index b00a881..d4a8435 100644 --- a/finance/migrations/0004_auto_20180321_1653.py +++ b/finance/migrations/0006_auto_20180330_1121.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2018-03-21 16:53 +# Generated by Django 1.11.6 on 2018-03-30 11:21 from __future__ import unicode_literals from django.db import migrations, models @@ -8,10 +8,14 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('finance', '0003_auto_20180315_1358'), + ('finance', '0005_auto_20180329_1346'), ] operations = [ + migrations.RemoveField( + model_name='installmentplan', + name='bill', + ), migrations.AddField( model_name='invoice', name='rebilling', @@ -22,4 +26,12 @@ class Migration(migrations.Migration): name='rebilling_on', field=models.BooleanField(default=False, editable=False, verbose_name='Повторять платеж'), ), + migrations.AlterField( + model_name='invoice', + name='date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.DeleteModel( + name='InstallmentPlan', + ), ] diff --git a/finance/models.py b/finance/models.py index 956caa7..979f903 100755 --- a/finance/models.py +++ b/finance/models.py @@ -67,18 +67,4 @@ class Invoice(models.Model): class Meta: verbose_name = 'Платёж' - verbose_name_plural = 'Платежи' - - -class InstallmentPlan(models.Model): - bill = models.OneToOneField(to=Bill, verbose_name="Связный счёт") - date = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания") - invoice_amount = models.IntegerField(verbose_name="Количество платежей") - price = models.IntegerField(verbose_name="Цена одного платежа") - - def __str__(self): - return '%s' % self.bill.user.email - - class Meta: - verbose_name = 'Рассрочка' - verbose_name_plural = 'Рассрочки' + verbose_name_plural = 'Платежи' \ No newline at end of file diff --git a/template/mail/sales/back_set_bill.html b/template/mail/sales/back_set_bill.html new file mode 100644 index 0000000..f7e5884 --- /dev/null +++ b/template/mail/sales/back_set_bill.html @@ -0,0 +1,10 @@ + + + + + $Title$ + + +$END$ + + \ No newline at end of file diff --git a/template/mail/sales/back_set_bill.txt b/template/mail/sales/back_set_bill.txt new file mode 100644 index 0000000..e69de29 From cbef6e6fd137283bf385e9e2712c05004cb3420b Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 30 Mar 2018 11:31:14 +0300 Subject: [PATCH 5/9] finance email --- finance/models.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/finance/models.py b/finance/models.py index 979f903..e72e348 100755 --- a/finance/models.py +++ b/finance/models.py @@ -62,6 +62,10 @@ class Invoice(models.Model): rebilling_on = models.BooleanField(verbose_name='Повторять платеж', default=False, editable=False) rebilling = models.BooleanField(verbose_name='Повторный платеж', default=False, editable=False) + def get_comment(self): + return '''Вам выставлен счёт,''' if \ + self.comment == "" else self.comment + def __str__(self): return '%s:%s %s' % (self.id, self.get_status_display(), self.bill.user) From 73d62c897dbe25e3306b2345a2b11202e5ca6b80 Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 30 Mar 2018 17:50:32 +0300 Subject: [PATCH 6/9] finance email --- finance/admin.py | 7 ++-- finance/migrations/0007_auto_20180330_1452.py | 23 +++++++++++ finance/migrations/0008_invoicerebilling.py | 28 +++++++++++++ .../0009_invoicerebilling_pay_count.py | 21 ++++++++++ finance/models.py | 13 ++++-- finance/signals.py | 4 +- finance/views.py | 40 +++++++++++++------ template/mail/sales/back_set_bill.html | 10 ----- template/mail/sales/back_set_bill.txt | 0 9 files changed, 116 insertions(+), 30 deletions(-) create mode 100644 finance/migrations/0007_auto_20180330_1452.py create mode 100644 finance/migrations/0008_invoicerebilling.py create mode 100644 finance/migrations/0009_invoicerebilling_pay_count.py delete mode 100644 template/mail/sales/back_set_bill.html delete mode 100644 template/mail/sales/back_set_bill.txt diff --git a/finance/admin.py b/finance/admin.py index 8143c83..2c74c0c 100755 --- a/finance/admin.py +++ b/finance/admin.py @@ -1,12 +1,13 @@ # coding=utf-8 from django.contrib import admin -from finance.models import Bill, Invoice +from finance.models import Bill, Invoice, InvoiceRebilling class InvoiceAdmin(admin.ModelAdmin): - list_display = ('__str__', 'rebilling_on', 'rebilling') + list_display = ('__str__', 'rebilling_on',) admin.site.register(Bill) -admin.site.register(Invoice, InvoiceAdmin) +admin.site.register(Invoice) +admin.site.register(InvoiceRebilling, InvoiceAdmin) diff --git a/finance/migrations/0007_auto_20180330_1452.py b/finance/migrations/0007_auto_20180330_1452.py new file mode 100644 index 0000000..0cd2288 --- /dev/null +++ b/finance/migrations/0007_auto_20180330_1452.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.6 on 2018-03-30 14:52 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('finance', '0006_auto_20180330_1121'), + ] + + operations = [ + migrations.RemoveField( + model_name='invoice', + name='rebilling', + ), + migrations.RemoveField( + model_name='invoice', + name='rebilling_on', + ), + ] diff --git a/finance/migrations/0008_invoicerebilling.py b/finance/migrations/0008_invoicerebilling.py new file mode 100644 index 0000000..215016d --- /dev/null +++ b/finance/migrations/0008_invoicerebilling.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.6 on 2018-03-30 14:52 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('finance', '0007_auto_20180330_1452'), + ] + + operations = [ + migrations.CreateModel( + name='InvoiceRebilling', + fields=[ + ('invoice_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='finance.Invoice')), + ('rebilling_on', models.BooleanField(default=False, editable=False, verbose_name='Повторять платеж')), + ], + options={ + 'verbose_name': 'Повторный платёж', + 'verbose_name_plural': 'Повторные платежи', + }, + bases=('finance.invoice',), + ), + ] diff --git a/finance/migrations/0009_invoicerebilling_pay_count.py b/finance/migrations/0009_invoicerebilling_pay_count.py new file mode 100644 index 0000000..89e388d --- /dev/null +++ b/finance/migrations/0009_invoicerebilling_pay_count.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.6 on 2018-03-30 15:03 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('finance', '0008_invoicerebilling'), + ] + + operations = [ + migrations.AddField( + model_name='invoicerebilling', + name='pay_count', + field=models.SmallIntegerField(default=2, editable=False, verbose_name='Всего платежей'), + preserve_default=False, + ), + ] diff --git a/finance/models.py b/finance/models.py index e72e348..30310e0 100755 --- a/finance/models.py +++ b/finance/models.py @@ -59,8 +59,6 @@ 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 get_comment(self): return '''Вам выставлен счёт,''' if \ @@ -71,4 +69,13 @@ class Invoice(models.Model): class Meta: verbose_name = 'Платёж' - verbose_name_plural = 'Платежи' \ No newline at end of file + verbose_name_plural = 'Платежи' + + +class InvoiceRebilling(Invoice): + rebilling_on = models.BooleanField(verbose_name='Повторять платеж', default=False, editable=False) + pay_count = models.SmallIntegerField(verbose_name='Всего платежей', editable=False) + + class Meta: + verbose_name = 'Повторный платёж' + verbose_name_plural = 'Повторные платежи' diff --git a/finance/signals.py b/finance/signals.py index 9d62f16..ea0f3cf 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' and not instance.rebilling: + if instance.yandex_pay and instance.method == 'Y' and instance.status == 'P': msg = EmailMessage( 'Вам выставлен новый счёт', """%s для оплаты перейдите по ссылке @@ -27,7 +27,7 @@ def invoice_signal(instance, **kwargs): ) msg.send() - if instance.status == 'F' and not instance.rebilling: + if instance.status == 'F': if instance.is_open: try: Progress.objects.get( diff --git a/finance/views.py b/finance/views.py index 87d9a66..95bd1d9 100644 --- a/finance/views.py +++ b/finance/views.py @@ -19,7 +19,7 @@ from django.utils.html import strip_tags from courses.models import Course from courses.api import CourseParamsApi -from finance.models import Bill, Invoice +from finance.models import Bill, Invoice, InvoiceRebilling from finance.serializers import BillSerializer, InvoiceSerializer from finance.tasks import setup_periodic_billing from lms.global_decorators import transaction_decorator @@ -99,6 +99,8 @@ class InvoiceDetailView(APIView): price = request.JSON.get('price', None) comment = request.JSON.get('comment', None) real_price = request.JSON.get('real_price', None) + rebilling_on = request.JSON.get('is_rebilling', False) + pay_count = request.JSON.get('pay_count', None) if bill_id is None: return Response("Не передан id счёта", status=400) @@ -117,22 +119,32 @@ class InvoiceDetailView(APIView): if bill.check_validate(invoice_id) and is_open: return Response("Уже есть платёж открывающий курс", status=400) - try: - invoice = Invoice.objects.get(id=invoice_id) - except Invoice.DoesNotExist: - if not invoice_id == 0: - return Response("Платёж не найден", status=404) - - if bill.check_pay(): - return Response( - "Нельзя добавить новый платёж, так как один из платежей по счёту уже оплачен", status=400) - invoice = Invoice.objects.create( + if rebilling_on: + invoice = InvoiceRebilling.objects.create( bill=bill, method=method, status=status, is_open=is_open, + pay_count=pay_count, ) + else: + try: + invoice = Invoice.objects.get(id=invoice_id) + except Invoice.DoesNotExist: + if not invoice_id == 0: + return Response("Платёж не найден", status=404) + + if bill.check_pay(): + return Response( + "Нельзя добавить новый платёж, так как один из платежей по счёту уже оплачен", status=400) + invoice = Invoice.objects.create( + bill=bill, + method=method, + status=status, + is_open=is_open, + ) + if invoice.status == "F": return Response(InvoiceSerializer(invoice).data, status=200) @@ -248,6 +260,10 @@ class YandexPay(APIView): def get(request, pk): try: pay = Payment.objects.get(id=pk) + try: + inv = InvoiceRebilling.objects.get(yandex_pay=pay) + except InvoiceRebilling: + inv = None r = requests.post('https://money.yandex.ru/eshop.xml', data={ 'shopId': pay.shop_id, 'scid': pay.scid, @@ -255,7 +271,7 @@ class YandexPay(APIView): 'customerNumber': pay.customer_number, 'orderNumber': pay.order_number, 'cps_email': pay.cps_email, - 'rebillingOn': pay.invoice.rebilling_on, + 'rebillingOn': False if inv is None else inv.rebilling_on, 'shopSuccessURL': settings.YANDEX_MONEY_SUCCESS_URL, 'shopFailURL': settings.YANDEX_MONEY_FAIL_URL, }) diff --git a/template/mail/sales/back_set_bill.html b/template/mail/sales/back_set_bill.html deleted file mode 100644 index f7e5884..0000000 --- a/template/mail/sales/back_set_bill.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - $Title$ - - -$END$ - - \ No newline at end of file diff --git a/template/mail/sales/back_set_bill.txt b/template/mail/sales/back_set_bill.txt deleted file mode 100644 index e69de29..0000000 From 8ae4d09a3d22a83500f9697dfaeee94e78b9cff8 Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 30 Mar 2018 18:21:20 +0300 Subject: [PATCH 7/9] finance email --- finance/signals.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/finance/signals.py b/finance/signals.py index ea0f3cf..da1b573 100644 --- a/finance/signals.py +++ b/finance/signals.py @@ -5,11 +5,27 @@ from django.dispatch import receiver from yandex_money.models import Payment from django.conf import settings -from finance.models import Invoice +from finance.models import Invoice, InvoiceRebilling from courses.models import Course from progress.models import Progress, ProgressLesson +@receiver(pre_save, sender=InvoiceRebilling) +def invoice_signal(instance, **kwargs): + """Отправка сообщения после сохранения рассрочки""" + + if instance.yandex_pay and instance.method == 'Y' and instance.status == 'P': + msg = EmailMessage( + 'Вам выставлен новый счёт', + """%s для оплаты перейдите по ссылке + %s/api/v1/finance/payment/%s/""" % (instance.get_comment(), settings.DOMAIN, instance.yandex_pay.id), + to=[instance.yandex_pay.cps_email], + bcc=[instance.bill.opener.email], + reply_to=[instance.bill.opener.email], + ) + msg.send() + + @receiver(pre_save, sender=Invoice) def invoice_signal(instance, **kwargs): """Отправка сообщения после сохранения платежа""" From d898ab95eef4e4c9a7a1cfd74ecdf60598d8b9f5 Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 30 Mar 2018 18:52:20 +0300 Subject: [PATCH 8/9] finance email --- finance/models.py | 12 ++++++++++++ finance/signals.py | 18 +----------------- finance/views.py | 2 +- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/finance/models.py b/finance/models.py index 30310e0..434e562 100755 --- a/finance/models.py +++ b/finance/models.py @@ -1,5 +1,6 @@ # coding=utf-8 from django.conf import settings +from django.core.mail import EmailMessage from django.db import models from yandex_money.models import Payment @@ -64,6 +65,17 @@ class Invoice(models.Model): return '''Вам выставлен счёт,''' if \ self.comment == "" else self.comment + def send_link(self): + msg = EmailMessage( + 'Вам выставлен новый счёт', + """%s для оплаты перейдите по ссылке + %s/api/v1/finance/payment/%s/""" % (self.get_comment(), settings.DOMAIN, self.yandex_pay.id), + to=[self.yandex_pay.cps_email], + bcc=[self.bill.opener.email], + reply_to=[self.bill.opener.email], + ) + msg.send() + 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 da1b573..ea0f3cf 100644 --- a/finance/signals.py +++ b/finance/signals.py @@ -5,27 +5,11 @@ from django.dispatch import receiver from yandex_money.models import Payment from django.conf import settings -from finance.models import Invoice, InvoiceRebilling +from finance.models import Invoice from courses.models import Course from progress.models import Progress, ProgressLesson -@receiver(pre_save, sender=InvoiceRebilling) -def invoice_signal(instance, **kwargs): - """Отправка сообщения после сохранения рассрочки""" - - if instance.yandex_pay and instance.method == 'Y' and instance.status == 'P': - msg = EmailMessage( - 'Вам выставлен новый счёт', - """%s для оплаты перейдите по ссылке - %s/api/v1/finance/payment/%s/""" % (instance.get_comment(), settings.DOMAIN, instance.yandex_pay.id), - to=[instance.yandex_pay.cps_email], - bcc=[instance.bill.opener.email], - reply_to=[instance.bill.opener.email], - ) - msg.send() - - @receiver(pre_save, sender=Invoice) def invoice_signal(instance, **kwargs): """Отправка сообщения после сохранения платежа""" diff --git a/finance/views.py b/finance/views.py index 95bd1d9..4db8425 100644 --- a/finance/views.py +++ b/finance/views.py @@ -127,7 +127,7 @@ class InvoiceDetailView(APIView): is_open=is_open, pay_count=pay_count, ) - + invoice.send_link() else: try: invoice = Invoice.objects.get(id=invoice_id) From cf07fde91a00035a5c98b8123c9dfb94fe15c007 Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 30 Mar 2018 18:55:32 +0300 Subject: [PATCH 9/9] finance email --- finance/signals.py | 11 ----------- finance/views.py | 3 ++- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/finance/signals.py b/finance/signals.py index ea0f3cf..c7b128f 100644 --- a/finance/signals.py +++ b/finance/signals.py @@ -16,17 +16,6 @@ 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': - msg = EmailMessage( - 'Вам выставлен новый счёт', - """%s для оплаты перейдите по ссылке - %s/api/v1/finance/payment/%s/""" % (instance.get_comment(), settings.DOMAIN, instance.yandex_pay.id), - to=[instance.yandex_pay.cps_email], - bcc=[instance.bill.opener.email], - reply_to=[instance.bill.opener.email], - ) - msg.send() - if instance.status == 'F': if instance.is_open: try: diff --git a/finance/views.py b/finance/views.py index 4db8425..eaa7fac 100644 --- a/finance/views.py +++ b/finance/views.py @@ -127,7 +127,6 @@ class InvoiceDetailView(APIView): is_open=is_open, pay_count=pay_count, ) - invoice.send_link() else: try: invoice = Invoice.objects.get(id=invoice_id) @@ -173,6 +172,8 @@ class InvoiceDetailView(APIView): ) invoice.yandex_pay = yandex_pay + invoice.send_link() + context = { 'user_email': invoice.bill.user.email, 'opener_full_name': invoice.bill.opener.get_full_name(),