import csv import logging import datetime import dicttoxml import requests from django.contrib.auth import get_user_model from django.db.models import Q from django.http import HttpResponse, HttpResponseForbidden from django.shortcuts import redirect from rest_framework.renderers import JSONRenderer from rest_framework.response import Response from rest_framework.views import APIView from yandex_money.models import Payment from django.conf import settings from courses.api import CourseParamsApi from finance.models import Bill, Invoice from finance.serializers import BillSerializer, InvoiceSerializer from lms.global_decorators import transaction_decorator from lms.tools import get_real_name from django.utils import timezone logger_yandex = logging.getLogger('yandex_money') class BillListView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def get(request): if request.user.is_authenticated: return Response( [BillSerializer(i).data for i in Bill.objects.filter(Q(user=request.user) | Q(opener=request.user))], status=200, ) return Response("Permission denied", status=403) @transaction_decorator def post(self, request): if request.user.is_authenticated and (request.user.groups.filter(name__in=['managers','lead_managers']).exists() 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() 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) if i['method'] == 'Y' and invoice.yandex_pay is None: yandex_pay = Payment.objects.create( order_amount=i['price'], shop_amount=0, customer_number=bill_obj.user.id, user=bill_obj.user, cps_email=bill_obj.user.email, ) 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] res = { "bill": BillSerializer(bill_obj).data, "children": [InvoiceSerializer(i).data for i in bill_obj.invoice_set.all()], } return Response(res, status=200) return Response("Bill not set", status=400) return Response("Course detail access only for manager users", status=403) class BillDetailView(APIView): renderer_classes = (JSONRenderer,) status_code = 200 def get(self, request, pk): if request.user.is_authenticated: try: bill = Bill.objects.get(id=pk) except Bill.DoesNotExist: return Response("Bill not found", status=404) res = { "bill": BillSerializer(bill).data, "children": [InvoiceSerializer(i).data for i in bill.invoice_set.all()], } return Response( res, status=self.status_code, ) return Response("Permission denied", status=403) class FindBillView(APIView): renderer_classes = (JSONRenderer,) status_code = 200 @staticmethod def get(request): if request.user.is_authenticated() and \ (request.user.is_superuser or request.user.groups.filter(name__in=['managers', 'lead_managers']).exists()): key = request.GET.get('key', None) count = int(request.GET.get('count', '10')) if key: res = Bill.objects.filter( Q(opener__email__contains=key.lower()) | Q(user__email__contains=key.lower()) ) else: res = Bill.objects.all() res = res[:(count if len(res) > count else len(res))] return Response( [BillSerializer(i).data for i in res], status=200 ) return Response('Permission denied', status=403) class YandexPay(APIView): renderer_classes = (JSONRenderer,) @staticmethod def get(request, pk): try: pay = Payment.objects.get(id=pk) r = requests.post('https://money.yandex.ru/eshop.xml', data={ 'shopId': pay.shop_id, 'scid': pay.scid, 'sum': pay.order_amount, 'customerNumber': pay.customer_number, 'orderNumber': pay.order_number, 'cps_email': pay.cps_email, 'shopSuccessURL': settings.YANDEX_MONEY_SUCCESS_URL, 'shopFailURL': settings.YANDEX_MONEY_FAIL_URL, }) return redirect(r.url) except Payment.DoesNotExist: return Response('Payment not found', status=404) def get_invoices(request): if not request.user.is_authenticated and (request.user.groups.filter(name="finance") or request.user.is_superuser): return HttpResponseForbidden() date_from = request.GET.get('from', None) date_to = request.GET.get('to', None) file_name = "invoices" file_name = file_name + "__from_%s" % date_from if date_from else file_name 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 response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename="%s.csv"' % file_name writer = csv.writer(response) writer.writerow(['date', 'time', 'student_email', 'full_name', 'course', 'price', 'real_price', 'key']) for i in invoices.order_by('-date'): course_api = CourseParamsApi(i.bill.course_token) writer.writerow([ i.date.date(), i.date.time(), i.bill.user.email, i.bill.user.get_full_name(), course_api.get_slug_and_title()['title'], i.price, i.real_price, i.key, ]) return response class YandexCheckView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def post(request): data = dict() for i in request.body.decode('utf-8').split('&'): key = i.split('=')[0] val = i.split('=')[1] data[key] = val logger_yandex.info(data) try: pay = Payment.objects.get(order_number=data['orderNumber']) except Payment.DoesNotExist: logger_yandex.error("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)) return Response(status=204) if not pay.shop_id == int(data['shopId']): logger_yandex.error("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'],)) 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'])) return Response(status=204) # TODO Нужно решение # pay.invoice_id = int(data['invoiceId']) # pay.save() now = timezone.now() pay.performed_datetime = now.isoformat() pay.save() xml_res = """ """ % (pay.performed_datetime, str(data['invoiceId']), str(pay.shop_id)) logger_yandex.info(xml_res) return HttpResponse(xml_res, content_type='application/xml') class YandexAvisoView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def post(request): data = dict() for i in request.body.decode('utf-8').split('&'): key = i.split('=')[0] val = i.split('=')[1] data[key] = val try: pay = Payment.objects.get(order_number=data['orderNumber']) except Payment.DoesNotExist: logger_yandex.error("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) pay.shop_amount = data['shopSumAmount'] pay.status = Payment.STATUS.SUCCESS pay.save() xml_res = """ """ % (pay.performed_datetime, str(data['invoiceId']), str(pay.shop_id)) logger_yandex.info(xml_res) return HttpResponse(xml_res, content_type='application/xml') class YandexFailView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def post(request): data = dict() for i in request.body.decode('utf-8').split('&'): key = i.split('=')[0] val = i.split('=')[1] data[key] = val logger_yandex.error(data) return redirect(to=settings.DOMAIN) class DemoYandexCheckView(YandexCheckView): """для тестирования платежей""" pass class DemoYandexAvisoView(YandexAvisoView): pass