commit
64442b7ca4
10 changed files with 258 additions and 35 deletions
@ -1,7 +1,13 @@ |
|||||||
# coding=utf-8 |
# coding=utf-8 |
||||||
from django.contrib import admin |
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',) |
||||||
|
|
||||||
|
|
||||||
admin.site.register(Bill) |
admin.site.register(Bill) |
||||||
admin.site.register(Invoice) |
admin.site.register(Invoice) |
||||||
|
admin.site.register(InvoiceRebilling, InvoiceAdmin) |
||||||
|
|||||||
@ -0,0 +1,37 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
# Generated by Django 1.11.6 on 2018-03-30 11:21 |
||||||
|
from __future__ import unicode_literals |
||||||
|
|
||||||
|
from django.db import migrations, models |
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration): |
||||||
|
|
||||||
|
dependencies = [ |
||||||
|
('finance', '0005_auto_20180329_1346'), |
||||||
|
] |
||||||
|
|
||||||
|
operations = [ |
||||||
|
migrations.RemoveField( |
||||||
|
model_name='installmentplan', |
||||||
|
name='bill', |
||||||
|
), |
||||||
|
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='Повторять платеж'), |
||||||
|
), |
||||||
|
migrations.AlterField( |
||||||
|
model_name='invoice', |
||||||
|
name='date', |
||||||
|
field=models.DateTimeField(auto_now_add=True), |
||||||
|
), |
||||||
|
migrations.DeleteModel( |
||||||
|
name='InstallmentPlan', |
||||||
|
), |
||||||
|
] |
||||||
@ -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', |
||||||
|
), |
||||||
|
] |
||||||
@ -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',), |
||||||
|
), |
||||||
|
] |
||||||
@ -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, |
||||||
|
), |
||||||
|
] |
||||||
@ -0,0 +1,86 @@ |
|||||||
|
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(order_number): |
||||||
|
# TODO: настроить периодичность и срок окончания |
||||||
|
# 12:00 первого числа каждого месяца |
||||||
|
schedule, _ = CrontabSchedule.objects.get_or_create( |
||||||
|
minute='0', |
||||||
|
hour='12', |
||||||
|
day_of_week='*', |
||||||
|
day_of_month='1', |
||||||
|
month_of_year='*' |
||||||
|
) |
||||||
|
PeriodicTask.objects.create( |
||||||
|
crontab=schedule, |
||||||
|
name='Periodic billing (order_number={})'.format(order_number), |
||||||
|
task='finance.tasks.periodic_billing', |
||||||
|
kwargs=json.dumps({ |
||||||
|
'order_number': order_number |
||||||
|
}), |
||||||
|
expires=datetime.utcnow() + timedelta(days=180) # в течение полугода |
||||||
|
) |
||||||
|
|
||||||
|
|
||||||
|
@celery_app.task |
||||||
|
def periodic_billing(order_number): |
||||||
|
try: |
||||||
|
sample = Invoice.objects.get(yandex_pay__order_number=order_number) |
||||||
|
except Invoice.DoesNotExist: |
||||||
|
raise ValueError('Номер заказа {} не найден'.format(order_number)) |
||||||
|
|
||||||
|
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() |
||||||
|
|
||||||
|
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) |
||||||
Loading…
Reference in new issue