Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve API (API 1.1) #421

Draft
wants to merge 16 commits into
base: next
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion stregsystem/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def __init__(self, *args, **kwargs):

class QRPaymentForm(forms.Form):
member = forms.CharField(max_length=16)
amount = forms.DecimalField(min_value=50, decimal_places=2, required=False)
amount = forms.DecimalField(min_value=0.01, decimal_places=2, required=False)


class PurchaseForm(forms.Form):
Expand Down
16 changes: 8 additions & 8 deletions stregsystem/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@
re_path(r'^(?P<room_id>\d+)/user/(?P<member_id>\d+)/pay$', views.menu_userpay, name="userpay"),
re_path(r'^(?P<room_id>\d+)/user/(?P<member_id>\d+)/rank$', views.menu_userrank, name="userrank"),
re_path(r'^(?P<room_id>\d+)/send_csv_mail/(?P<member_id>\d+)/$', views.send_userdata, name="send_userdata"),
re_path(r'^api/member/payment/qr$', views.qr_payment, name="payment_qr"),
re_path(r'^api/member/active$', views.check_user_active, name="active_member"),
re_path(r'^api/member/sales$', views.get_user_sales, name="get_user_sales"),
re_path(r'^api/member/get_id$', views.convert_username_to_id, name="get_id"),
re_path(r'^api/member/balance$', views.get_user_balance, name="get_user_balance"),
re_path(r'^api/member$', views.get_user_info, name="get_user_transactions"),
re_path(r'^api/products/named_products$', views.dump_named_items, name="named_products"),
re_path(r'^api/products/active_products$', views.dump_active_items, name="active_products"),
re_path(r'^api/member/payment/qr$', views.get_payment_qr, name="get_payment_qr"),
re_path(r'^api/member/active$', views.get_member_active, name="get_member_active"),
re_path(r'^api/member/sales$', views.get_member_sales, name="get_member_sales"),
re_path(r'^api/member/get_id$', views.get_member_id, name="get_member_id"),
re_path(r'^api/member/balance$', views.get_member_balance, name="get_member_balance"),
re_path(r'^api/member$', views.get_member_info, name="get_member_info"),
re_path(r'^api/products/named_products$', views.dump_named_products, name="dump_named_products"),
re_path(r'^api/products/active_products$', views.dump_active_items, name="dump_active_products"),
re_path(r'^api/products/category_mappings$', views.dump_product_category_mappings, name="product_mappings"),
re_path(r'^api/sale$', views.api_sale, name="sale"),
]
13 changes: 12 additions & 1 deletion stregsystem/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import qrcode
import qrcode.image.svg

import urllib.parse

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -141,14 +143,23 @@ def strip_emoji(text):
).strip()


def qr_code(data):
def qr_code(data) -> HttpResponse:
response = HttpResponse(content_type="image/svg+xml")
qr = qrcode.make(data, image_factory=qrcode.image.svg.SvgPathFillImage)
qr.save(response)

return response


def mobilepay_launch_uri(comment: str, amount: float) -> str:
query = {'phone': '90601', 'comment': comment}

if amount is not None:
query['amount'] = amount

return 'mobilepay://send?{}'.format(urllib.parse.urlencode(query))


class stregsystemTestRunner(DiscoverRunner):
def __init__(self, *args, **kwargs):
settings.TEST_MODE = True
Expand Down
69 changes: 38 additions & 31 deletions stregsystem/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
from django_select2 import forms as s2forms
import urllib.parse


from stregsystem import parser
Expand All @@ -43,6 +42,7 @@
from stregsystem.utils import (
make_active_productlist_query,
qr_code,
mobilepay_launch_uri,
make_room_specific_query,
make_unprocessed_mobilepayment_query,
parse_csv_and_create_mobile_payments,
Expand Down Expand Up @@ -499,92 +499,99 @@ def mobilepaytool(request):
return render(request, "admin/stregsystem/mobilepaytool.html", data)


def qr_payment(request):
# API views


def get_payment_qr(request):
form = QRPaymentForm(request.GET)
if not form.is_valid():
return HttpResponseBadRequest("Invalid input for MobilePay QR code generation")

query = {'phone': '90601', 'comment': form.cleaned_data.get('member')}

if form.cleaned_data.get("amount") is not None:
query['amount'] = form.cleaned_data.get("amount")
username = form.cleaned_data.get('member')
amount = form.cleaned_data.get('amount')

data = 'mobilepay://send?{}'.format(urllib.parse.urlencode(query))
return qr_code(data)


# API views
return qr_code(mobilepay_launch_uri(username, amount))


def dump_active_items(request):
room_id = request.GET.get('room_id') or None
if room_id is None:
return HttpResponseBadRequest("Missing room_id")
return HttpResponseBadRequest("Parameter missing: room_id")
elif not room_id.isdigit():
return HttpResponseBadRequest("Invalid room_id")
return HttpResponseBadRequest("Parameter invalid: room_id")
# TODO: Check whether room exists
items = __get_productlist(room_id)
items_dict = {item.id: (item.name, item.price) for item in items}
items_dict = {item.id: {'name': item.name, 'price': item.price} for item in items}
return JsonResponse(items_dict, json_dumps_params={'ensure_ascii': False})


def check_user_active(request):
def get_member_active(request):
member_id = request.GET.get('member_id') or None
if member_id is None:
return HttpResponseBadRequest("Missing member_id")
return HttpResponseBadRequest("Parameter missing: member_id")
elif not member_id.isdigit():
return HttpResponseBadRequest("Invalid member_id")
return HttpResponseBadRequest("Parameter invalid: member_id")
try:
member = Member.objects.get(pk=member_id)
except Member.DoesNotExist:
return HttpResponseBadRequest("Member not found")
return JsonResponse({'active': member.active})


def convert_username_to_id(request):
def get_member_id(request):
username = request.GET.get('username') or None
if username is None:
return HttpResponseBadRequest("Missing username")
return HttpResponseBadRequest("Parameter missing: username")

try:
member = Member.objects.get(username=username)
except Member.DoesNotExist:
return HttpResponseBadRequest("Invalid username")
return HttpResponseBadRequest("Member not found")

return JsonResponse({'member_id': member.id})


def dump_product_category_mappings(request):
return JsonResponse({p.id: [(cat.id, cat.name) for cat in p.categories.all()] for p in Product.objects.all()})
return JsonResponse(
{
p.id: [{'category_id': cat.id, 'category_name': cat.name} for cat in p.categories.all()]
for p in Product.objects.all()
}
)


def get_user_sales(request):
def get_member_sales(request):
member_id = request.GET.get('member_id') or None
if member_id is None:
return HttpResponseBadRequest("Missing member_id")
return HttpResponseBadRequest("Parameter missing: member_id")
elif not member_id.isdigit():
return HttpResponseBadRequest("Invalid member_id")
return HttpResponseBadRequest("Parameter invalid: member_id")
count = 10 if request.GET.get('count') is None else int(request.GET.get('count') or 10)
sales = Sale.objects.filter(member=member_id).order_by('-timestamp')[:count]
return JsonResponse(
{'sales': [{'timestamp': s.timestamp, 'product': s.product.name, 'price': s.product.price} for s in sales]}
)


def get_user_balance(request):
def get_member_balance(request):
member_id = request.GET.get('member_id') or None
if member_id is None:
return HttpResponseBadRequest("Missing member_id")
return HttpResponseBadRequest("Parameter missing: member_id")
elif not member_id.isdigit():
return HttpResponseBadRequest("Invalid member_id")
return HttpResponseBadRequest("Parameter invalid: member_id")
try:
member = Member.objects.get(pk=member_id)
except Member.DoesNotExist:
return HttpResponseBadRequest("Member not found")
return JsonResponse({'balance': member.balance})


def get_user_info(request):
def get_member_info(request):
member_id = str(request.GET.get('member_id')) or None
if member_id is None or not member_id.isdigit():
return HttpResponseBadRequest("Missing or invalid member_id")
if member_id is None:
return HttpResponseBadRequest("Parameter missing: member_id")
elif not member_id.isdigit():
return HttpResponseBadRequest("Parameter invalid: member_id")

member = find_user_from_id(int(member_id))
if member is None:
Expand All @@ -606,7 +613,7 @@ def find_user_from_id(user_id: int):
return None


def dump_named_items(request):
def dump_named_products(request):
items = NamedProduct.objects.all()
items_dict = {item.name: item.product.id for item in items}
return JsonResponse(items_dict, json_dumps_params={'ensure_ascii': False})
Expand Down
Loading