You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
309 lines
10 KiB
309 lines
10 KiB
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
|
|
|
|
logger_yandex = logging.getLogger('yandex_money')
|
|
|
|
|
|
class BillListView(APIView):
|
|
renderer_classes = (JSONRenderer,)
|
|
|
|
@staticmethod
|
|
def get(request):
|
|
"""
|
|
This API endpoint return list of bills.
|
|
---
|
|
Returns a list of accounts for an authorized user or responsible user
|
|
"""
|
|
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':
|
|
yandex_pay, _is_create = Payment.objects.get_or_create(
|
|
order_amount=i['price'],
|
|
order_number=invoice.id,
|
|
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,
|
|
})
|
|
|
|
logger_yandex.info(r)
|
|
|
|
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()
|
|
xml_res = dicttoxml.dicttoxml({
|
|
'code': 0,
|
|
'shopId': int(pay.shop_id),
|
|
'invoiceId': int(data['invoiceId']),
|
|
'orderSumAmount': pay.order_amount,
|
|
'performedDatetime': datetime.datetime.now(),
|
|
})
|
|
logger_yandex.info(xml_res)
|
|
|
|
return Response(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 = dicttoxml.dicttoxml({
|
|
'code': 0,
|
|
'shopId':int(pay.shop_id),
|
|
'invoiceId': int(data['invoiceId']),
|
|
'orderSumAmount': pay.order_amount,
|
|
'performedDatetime': datetime.datetime.now(),
|
|
})
|
|
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) |