|
|
|
|
@ -1,10 +1,9 @@ |
|
|
|
|
import csv |
|
|
|
|
import logging |
|
|
|
|
import datetime |
|
|
|
|
import dicttoxml |
|
|
|
|
|
|
|
|
|
import requests |
|
|
|
|
from django.contrib.auth import get_user_model |
|
|
|
|
from django.core.mail import EmailMessage |
|
|
|
|
from django.db.models import Q |
|
|
|
|
from django.http import HttpResponse, HttpResponseForbidden |
|
|
|
|
from django.shortcuts import redirect |
|
|
|
|
@ -14,6 +13,7 @@ from rest_framework.views import APIView |
|
|
|
|
from yandex_money.models import Payment |
|
|
|
|
from django.conf import settings |
|
|
|
|
|
|
|
|
|
from courses.models import Course |
|
|
|
|
from courses.api import CourseParamsApi |
|
|
|
|
from finance.models import Bill, Invoice |
|
|
|
|
from finance.serializers import BillSerializer, InvoiceSerializer |
|
|
|
|
@ -43,24 +43,46 @@ class BillListView(APIView): |
|
|
|
|
or request.user.is_superuser): |
|
|
|
|
bill = request.JSON.get('bill') |
|
|
|
|
children = request.JSON.get('children', []) |
|
|
|
|
bill_kwarg = dict() |
|
|
|
|
|
|
|
|
|
if bill: |
|
|
|
|
bill_kwarg['user'] = get_user_model().objects.get(email=bill['user']) |
|
|
|
|
bill_kwarg['opener'] = get_user_model().objects.get(email=bill['opener']) |
|
|
|
|
bill_kwarg['description'] = bill['description'] |
|
|
|
|
bill_kwarg['comment'] = bill['comment'] |
|
|
|
|
bill_kwarg['course_token'] = bill['course_token'] |
|
|
|
|
|
|
|
|
|
bill_obj, is_create = Bill.objects.update_or_create(**bill_kwarg) |
|
|
|
|
invoices = bill_obj.invoice_set.all() |
|
|
|
|
user = get_user_model().objects.get(email=bill['user']) |
|
|
|
|
opener = get_user_model().objects.get(email=bill['opener']) |
|
|
|
|
description = bill['description'] |
|
|
|
|
comment = bill['comment'] |
|
|
|
|
course_token = bill['course_token'] |
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
bill_obj = Bill.objects.get(user=user, course_token=course_token) |
|
|
|
|
except Bill.DoesNotExist: |
|
|
|
|
bill_obj = Bill.objects.create(user=user, course_token=course_token) |
|
|
|
|
|
|
|
|
|
bill_obj.opener = opener |
|
|
|
|
bill_obj.description = description |
|
|
|
|
bill_obj.comment = comment |
|
|
|
|
bill_obj.save() |
|
|
|
|
|
|
|
|
|
for i in children: |
|
|
|
|
i['method'] = get_real_name(elem=i['method'], array=Invoice.BILL_METHOD) |
|
|
|
|
i['status'] = get_real_name(elem=i['status'], array=Invoice.BILL_STATUSES) |
|
|
|
|
i['bill'] = bill_obj |
|
|
|
|
i['yandex_pay'] = None |
|
|
|
|
invoice, _is_create = Invoice.objects.update_or_create(**i) |
|
|
|
|
status = get_real_name(elem=i['status'], array=Invoice.BILL_STATUSES) |
|
|
|
|
try: |
|
|
|
|
invoice_id = i['id'] |
|
|
|
|
except KeyError: |
|
|
|
|
invoice_id = None |
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
if not invoice_id is None: |
|
|
|
|
invoice = Invoice.objects.get(id=i['id']) |
|
|
|
|
if invoice.status == "P" or invoice.status == status: |
|
|
|
|
continue |
|
|
|
|
else: |
|
|
|
|
raise Invoice.DoesNotExist |
|
|
|
|
|
|
|
|
|
except Invoice.DoesNotExist: |
|
|
|
|
i['method'] = get_real_name(elem=i['method'], array=Invoice.BILL_METHOD) |
|
|
|
|
i['status'] = status |
|
|
|
|
i['bill'] = bill_obj |
|
|
|
|
i['yandex_pay'] = None |
|
|
|
|
invoice = Invoice.objects.create(**i) |
|
|
|
|
|
|
|
|
|
if i['method'] == 'Y' and invoice.yandex_pay is None: |
|
|
|
|
yandex_pay = Payment.objects.create( |
|
|
|
|
order_amount=i['price'], |
|
|
|
|
@ -72,9 +94,20 @@ class BillListView(APIView): |
|
|
|
|
invoice.yandex_pay = yandex_pay |
|
|
|
|
invoice.save() |
|
|
|
|
|
|
|
|
|
invoices = [j for j in invoices if not j.id == invoice.id] |
|
|
|
|
|
|
|
|
|
[i.delete() for i in invoices] |
|
|
|
|
msg = EmailMessage( |
|
|
|
|
'Выставлен новый счёт.', |
|
|
|
|
'''Менеджер %s выставил счёт пользователю %s на курс "%s".''' |
|
|
|
|
% ( |
|
|
|
|
invoice.bill.opener.get_full_name(), |
|
|
|
|
invoice.bill.user.email, |
|
|
|
|
Course.objects.get(token=invoice.bill.course_token).title, |
|
|
|
|
), |
|
|
|
|
'robo@skillbox.ru', |
|
|
|
|
[invoice.bill.opener.email], |
|
|
|
|
bcc=['dmitry.dolya@skillbox.ru'], |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
msg.send() |
|
|
|
|
|
|
|
|
|
res = { |
|
|
|
|
"bill": BillSerializer(bill_obj).data, |
|
|
|
|
@ -161,6 +194,17 @@ class YandexPay(APIView): |
|
|
|
|
'shopFailURL': settings.YANDEX_MONEY_FAIL_URL, |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
msg = EmailMessage( |
|
|
|
|
'Пользователь перешёл на страницу оплаты.', |
|
|
|
|
'''Пользователь "%s" перешёл на страницу оплаты курса "%s".''' |
|
|
|
|
% (pay.invoice.bill.user.email, Course.objects.get(token=pay.invoice.bill.course_token).title), |
|
|
|
|
'robo@skillbox.ru', |
|
|
|
|
[pay.invoice.bill.opener.email], |
|
|
|
|
bcc=['dmitry.dolya@skillbox.ru'], |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
msg.send() |
|
|
|
|
|
|
|
|
|
return redirect(r.url) |
|
|
|
|
|
|
|
|
|
except Payment.DoesNotExist: |
|
|
|
|
@ -179,8 +223,8 @@ def get_invoices(request): |
|
|
|
|
file_name = file_name + "__to_%s" % date_to if date_to else file_name |
|
|
|
|
|
|
|
|
|
invoices = Invoice.objects.filter(method="Y", status="F") |
|
|
|
|
invoices = invoices.filter(date__lt=date_to) if date_to else invoices |
|
|
|
|
invoices = invoices.filter(date__gte=date_from) if date_from else invoices |
|
|
|
|
invoices = invoices.filter(yandex_pay__performed_datetime__lt=date_to) if date_to else invoices |
|
|
|
|
invoices = invoices.filter(yandex_pay__performed_datetime__gte=date_from) if date_from else invoices |
|
|
|
|
|
|
|
|
|
response = HttpResponse(content_type='text/csv') |
|
|
|
|
response['Content-Disposition'] = 'attachment; filename="%s.csv"' % file_name |
|
|
|
|
@ -191,8 +235,8 @@ def get_invoices(request): |
|
|
|
|
for i in invoices.order_by('-date'): |
|
|
|
|
course_api = CourseParamsApi(i.bill.course_token) |
|
|
|
|
writer.writerow([ |
|
|
|
|
i.date.date(), |
|
|
|
|
i.date.time(), |
|
|
|
|
i.yandex_pay.performed_datetime.date(), |
|
|
|
|
i.yandex_pay.performed_datetime.time(), |
|
|
|
|
i.bill.user.email, |
|
|
|
|
i.bill.user.get_full_name(), |
|
|
|
|
course_api.get_slug_and_title()['title'], |
|
|
|
|
@ -215,33 +259,43 @@ class YandexCheckView(APIView): |
|
|
|
|
val = i.split('=')[1] |
|
|
|
|
data[key] = val |
|
|
|
|
|
|
|
|
|
logger_yandex.info(data) |
|
|
|
|
logger_yandex.info('Проверка платежа запрос', exc_info=True, extra={ |
|
|
|
|
'request': data, |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
pay = Payment.objects.get(order_number=data['orderNumber']) |
|
|
|
|
except Payment.DoesNotExist: |
|
|
|
|
logger_yandex.error("Payment with id=%s not found" % data['orderNumber']) |
|
|
|
|
logger_yandex.error('Ошибка проверки платежа', exc_info=True, extra={ |
|
|
|
|
'request': "Payment with id=%s not found" % data['orderNumber'], |
|
|
|
|
}) |
|
|
|
|
return Response(status=204) |
|
|
|
|
|
|
|
|
|
if not pay.status == Payment.STATUS.PROCESSED: |
|
|
|
|
logger_yandex.error("Payment with id=%s have status %s" % (data['orderNumber'], pay.status)) |
|
|
|
|
logger_yandex.error('Ошибка проверки платежа', exc_info=True, extra={ |
|
|
|
|
'request': "Payment with id=%s have status %s" % (data['orderNumber'], pay.status), |
|
|
|
|
}) |
|
|
|
|
return Response(status=204) |
|
|
|
|
|
|
|
|
|
if not pay.shop_id == int(data['shopId']): |
|
|
|
|
logger_yandex.error("ShopId=%s not match" % (data['shopId'],)) |
|
|
|
|
logger_yandex.error('Ошибка проверки платежа', exc_info=True, extra={ |
|
|
|
|
'request': "ShopId=%s not match" % (data['shopId'],), |
|
|
|
|
}) |
|
|
|
|
return Response(status=204) |
|
|
|
|
|
|
|
|
|
if not pay.scid == int(data['scid']): |
|
|
|
|
logger_yandex.error("scid=%s not match" % (data['scid'],)) |
|
|
|
|
logger_yandex.error('Ошибка проверки платежа', exc_info=True, extra={ |
|
|
|
|
'request': "scid=%s not match" % (data['scid'],) |
|
|
|
|
}) |
|
|
|
|
return Response(status=204) |
|
|
|
|
|
|
|
|
|
if not pay.order_amount == float(data['orderSumAmount']): |
|
|
|
|
logger_yandex.error("Expected amount is %s received amount is %s" |
|
|
|
|
% (pay.order_amount, data['orderSumAmount'])) |
|
|
|
|
logger_yandex.error('Ошибка проверки платежа', exc_info=True, extra={ |
|
|
|
|
'request': "Expected amount is %s received amount is %s" |
|
|
|
|
% (pay.order_amount, data['orderSumAmount']), |
|
|
|
|
}) |
|
|
|
|
return Response(status=204) |
|
|
|
|
|
|
|
|
|
# TODO Нужно решение |
|
|
|
|
# pay.invoice_id = int(data['invoiceId']) |
|
|
|
|
# pay.save() |
|
|
|
|
now = timezone.now() |
|
|
|
|
pay.performed_datetime = now.isoformat() |
|
|
|
|
pay.save() |
|
|
|
|
@ -249,7 +303,9 @@ class YandexCheckView(APIView): |
|
|
|
|
xml_res = """<checkOrderResponse performedDatetime="%s" code="0" invoiceId="%s" shopId="%s"/> |
|
|
|
|
""" % (pay.performed_datetime, str(data['invoiceId']), str(pay.shop_id)) |
|
|
|
|
|
|
|
|
|
logger_yandex.info(xml_res) |
|
|
|
|
logger_yandex.info('Проверка платежа ответ', exc_info=True, extra={ |
|
|
|
|
'response': xml_res, |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
return HttpResponse(xml_res, content_type='application/xml') |
|
|
|
|
|
|
|
|
|
@ -268,19 +324,39 @@ class YandexAvisoView(APIView): |
|
|
|
|
try: |
|
|
|
|
pay = Payment.objects.get(order_number=data['orderNumber']) |
|
|
|
|
except Payment.DoesNotExist: |
|
|
|
|
logger_yandex.error("Payment with invoice_id=%s not found" % data['orderNumber']) |
|
|
|
|
logger_yandex.error('Ошибка подтверждения платежа', exc_info=True, extra={ |
|
|
|
|
'request': "Payment with invoice_id=%s not found" % data['orderNumber'], |
|
|
|
|
}) |
|
|
|
|
return Response(status=204) |
|
|
|
|
|
|
|
|
|
logger_yandex.info('Get success pay with invoice_id(yandex) %s' % pay.invoice_id) |
|
|
|
|
logger_yandex.info('Подтверждение платежа запрос', exc_info=True, extra={ |
|
|
|
|
'request': 'Get success pay with invoice_id(yandex) %s' % str(data['invoiceId']), |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
pay.shop_amount = data['shopSumAmount'] |
|
|
|
|
pay.status = Payment.STATUS.SUCCESS |
|
|
|
|
pay.invoice_id = data['invoiceId'] |
|
|
|
|
now = timezone.now() |
|
|
|
|
pay.performed_datetime = now.isoformat() |
|
|
|
|
pay.save() |
|
|
|
|
xml_res = """<paymentAvisoResponse performedDatetime="%s" code="0" invoiceId="%s" shopId="%s"/> |
|
|
|
|
""" % (pay.performed_datetime, str(data['invoiceId']), str(pay.shop_id)) |
|
|
|
|
|
|
|
|
|
logger_yandex.info(xml_res) |
|
|
|
|
logger_yandex.info('Подтверждение платежа ответ', exc_info=True, extra={ |
|
|
|
|
'response': xml_res, |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
msg = EmailMessage( |
|
|
|
|
'Успешная оплата.', |
|
|
|
|
'''Пользователь "%s", перевёл %s рублей. Номер платежа в яндекс кассе %s''' |
|
|
|
|
% (pay.invoice.bill.user.email, str(pay.invoice.price), str(data['invoiceId'])), |
|
|
|
|
'robo@skillbox.ru', |
|
|
|
|
[pay.invoice.bill.opener.email], |
|
|
|
|
bcc=['dmitry.dolya@skillbox.ru', 'vera.procenko@skillbox.ru'], |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
msg.send() |
|
|
|
|
|
|
|
|
|
if pay.invoice.rebilling_on: |
|
|
|
|
setup_periodic_billing(pay.order_number) |
|
|
|
|
|