From 73d8d555d1f39e93571652ec1589f8dc298b170e Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Fri, 21 Dec 2018 09:46:23 +0100 Subject: [PATCH] adding transactions download --- rowers/braintreestuff.py | 74 ++++++++++++++++++++++++++- rowers/payments.py | 27 ++++++---- rowers/templates/menu_profile.html | 8 +++ rowers/templates/transactions.html | 24 +++++++++ rowers/urls.py | 1 + rowers/views.py | 82 +++++++++++++++++++++++++++++- rowsandall_app/settings.py | 5 ++ 7 files changed, 208 insertions(+), 13 deletions(-) create mode 100644 rowers/templates/transactions.html diff --git a/rowers/braintreestuff.py b/rowers/braintreestuff.py index 01fda581..7477ddbe 100644 --- a/rowers/braintreestuff.py +++ b/rowers/braintreestuff.py @@ -15,6 +15,7 @@ from rowers.tasks import ( handle_send_email_failed_cancel, ) +import pandas as pd from rowsandall_app.settings import ( BRAINTREE_MERCHANT_ID,BRAINTREE_PUBLIC_KEY,BRAINTREE_PRIVATE_KEY @@ -314,5 +315,76 @@ def find_subscriptions(rower): result.append(thedict) return result - + +def get_transactions(start_date,end_date): + results = gateway.transaction.search( + braintree.TransactionSearch.created_at.between( + start_date, + end_date, + ) + ) + + amounts = [] + countries = [] + card_countries = [] + names = [] + emails = [] + dates = [] + currencies = [] + statuses = [] + ids = [] + usernames = [] + + for transaction in results: + try: + r = Rower.objects.filter( + customer_id=transaction.customer['id'], + paymentprocessor='braintree')[0] + countries.append(r.country) + names.append('{f} {l}'.format( + f = r.user.first_name, + l = r.user.last_name, + ) + ) + emails.append(r.user.email) + ids.append(r.id) + usernames.append(r.user.username) + + except KeyError: + countries.append( + transaction.credit_card_details.country_of_issuance) + names.append('{f} {l}'.format( + f = transaction.customer['first_name'], + l = transaction.customer['last_name'] + ) + ) + emails.append(transaction.customer.email) + ids.append(transaction.customer['id']) + usernames.append('unknown') + + + amounts.append(transaction.amount) + dates.append(transaction.created_at) + currencies.append(transaction.currency_iso_code) + card_countries.append( + transaction.credit_card_details.country_of_issuance) + statuses.append(transaction.status) + + + df = pd.DataFrame({ + 'name':names, + 'email':emails, + 'date':dates, + 'amount':amounts, + 'currency':currencies, + 'country':countries, + 'card_country':card_countries, + 'status':statuses, + 'username':usernames, + 'user_id':ids, + } + ) + + return df + diff --git a/rowers/payments.py b/rowers/payments.py index 488191c1..7e71aad5 100644 --- a/rowers/payments.py +++ b/rowers/payments.py @@ -10,22 +10,27 @@ def planstopaypal(): plan.external_id = None plan.save() +def initiaterowerplans(): + rowers = Rower.objects.filter(paymenttype = 'recurring',paidplan = None) + for r in rowers: + r.paymentprocessor = 'paypal' + r.save() + def setrowerplans(): rowers = Rower.objects.all() for r in rowers: - if r.rowerplan != 'basic': - paidplans = PaidPlan.objects.filter( - shortname = r.rowerplan, - paymenttype = r.paymenttype, - clubsize = r.clubsize) + paidplans = PaidPlan.objects.filter( + shortname = r.rowerplan, + paymenttype = r.paymenttype, + clubsize = r.clubsize, + paymentprocessor=r.paymentprocessor) - if paidplans: - r.paidplan = paidplans[0] - r.paymentprocessor = 'paypal' - r.save() - else: - print 'Could not set plan for ',r + if paidplans: + r.paidplan = paidplans[0] + r.save() + else: + print 'Could not set plan for ',r def is_existing_customer(rower): if rower.country is not None and rower.customer_id is not None and rower.country != '': diff --git a/rowers/templates/menu_profile.html b/rowers/templates/menu_profile.html index d3dd90b0..90bd73b9 100644 --- a/rowers/templates/menu_profile.html +++ b/rowers/templates/menu_profile.html @@ -27,8 +27,16 @@  Manage Workflow + {% if user.is_authenticated and user.is_staff %} +
  • + +  Transactions + +
  • + {% endif %} + {% if user.is_authenticated and user|is_manager %}

     

    {% if user|team_members %} diff --git a/rowers/templates/transactions.html b/rowers/templates/transactions.html new file mode 100644 index 00000000..08cd6a0a --- /dev/null +++ b/rowers/templates/transactions.html @@ -0,0 +1,24 @@ +{% extends "newbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block main %} +

    Download Transactions

    + +
    + + {{ dateform.as_table }} +
    + {% csrf_token %} + +
    + +{% endblock %} + +{% block sideheader %} +

    Profile

    +{% endblock %} + +{% block sidebar %} +{% include 'menu_profile.html' %} +{% endblock %} diff --git a/rowers/urls.py b/rowers/urls.py index 474946e3..f37951da 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -404,6 +404,7 @@ urlpatterns = [ url(r'^me/edit/$',views.rower_edit_view), url(r'^me/edit/user/(?P\d+)$',views.rower_edit_view), url(r'^me/preferences/$',views.rower_prefs_view), + url(r'^me/transactions/$',views.transactions_view), url(r'^me/preferences/user/(?P\d+)$',views.rower_prefs_view), url(r'^me/edit/(.+.*)/$',views.rower_edit_view), url(r'^me/c2authorize/$',views.rower_c2_authorize), diff --git a/rowers/views.py b/rowers/views.py index d44d47de..1b46512f 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -141,7 +141,8 @@ from rowsandall_app.settings import ( UNDERARMOUR_CLIENT_SECRET,UNDERARMOUR_CLIENT_KEY, RUNKEEPER_CLIENT_ID,RUNKEEPER_REDIRECT_URI,RUNKEEPER_CLIENT_SECRET, TP_CLIENT_ID,TP_REDIRECT_URI,TP_CLIENT_KEY,TP_CLIENT_SECRET, - BRAINTREE_MERCHANT_ID,BRAINTREE_PUBLIC_KEY,BRAINTREE_PRIVATE_KEY + BRAINTREE_MERCHANT_ID,BRAINTREE_PUBLIC_KEY,BRAINTREE_PRIVATE_KEY, + PAYMENT_PROCESSING_ON ) from rowers.tasks_standalone import addcomment2 @@ -1073,6 +1074,10 @@ def paidplans_view(request): @login_required() def billing_view(request): + if not PAYMENT_PROCESSING_ON: + url = reverse('promembership') + return HttpResponseRedirect(url) + r = getrequestrower(request) if payments.is_existing_customer(r): @@ -1116,6 +1121,10 @@ def billing_view(request): @login_required() def upgrade_view(request): + if not PAYMENT_PROCESSING_ON: + url = reverse('promembership') + return HttpResponseRedirect(url) + r = getrequestrower(request) if r.subscription_id is None or r.subscription_id == '': @@ -1154,6 +1163,10 @@ def upgrade_view(request): @login_required() def downgrade_view(request): + if not PAYMENT_PROCESSING_ON: + url = reverse('promembership') + return HttpResponseRedirect(url) + r = getrequestrower(request) if r.subscription_id is None or r.subscription_id == '': @@ -1202,6 +1215,10 @@ def downgrade_view(request): @login_required() def plan_stop_view(request): + if not PAYMENT_PROCESSING_ON: + url = reverse('promembership') + return HttpResponseRedirect(url) + r = getrequestrower(request) subscriptions = [] @@ -1223,6 +1240,10 @@ def plan_stop_view(request): @login_required() def plan_tobasic_view(request,id=0): + if not PAYMENT_PROCESSING_ON: + url = reverse('promembership') + return HttpResponseRedirect(url) + r = getrequestrower(request) if r.paidplan.paymentprocessor == 'braintree': @@ -1241,6 +1262,10 @@ def plan_tobasic_view(request,id=0): @login_required() def upgrade_confirm_view(request,planid = 0): + if not PAYMENT_PROCESSING_ON: + url = reverse('promembership') + return HttpResponseRedirect(url) + try: plan = PaidPlan.objects.get(id=planid) except PaidPlan.DoesNotExist: @@ -1262,6 +1287,10 @@ def upgrade_confirm_view(request,planid = 0): @login_required() def downgrade_confirm_view(request,planid = 0): + if not PAYMENT_PROCESSING_ON: + url = reverse('promembership') + return HttpResponseRedirect(url) + try: plan = PaidPlan.objects.get(id=planid) except PaidPlan.DoesNotExist: @@ -1284,6 +1313,10 @@ def downgrade_confirm_view(request,planid = 0): @login_required() def payment_confirm_view(request,planid = 0): + if not PAYMENT_PROCESSING_ON: + url = reverse('promembership') + return HttpResponseRedirect(url) + try: plan = PaidPlan.objects.get(id=planid) except PaidPlan.DoesNotExist: @@ -1306,6 +1339,10 @@ def payment_confirm_view(request,planid = 0): @login_required() def checkouts_view(request): + if not PAYMENT_PROCESSING_ON: + url = reverse('promembership') + return HttpResponseRedirect(url) + r = getrequestrower(request) @@ -1336,6 +1373,10 @@ def checkouts_view(request): @login_required() def upgrade_checkouts_view(request): + if not PAYMENT_PROCESSING_ON: + url = reverse('promembership') + return HttpResponseRedirect(url) + r = getrequestrower(request) @@ -1366,6 +1407,10 @@ def upgrade_checkouts_view(request): @login_required() def downgrade_checkouts_view(request): + if not PAYMENT_PROCESSING_ON: + url = reverse('promembership') + return HttpResponseRedirect(url) + r = getrequestrower(request) @@ -1397,6 +1442,10 @@ def downgrade_checkouts_view(request): @login_required() def payment_completed_view(request): + if not PAYMENT_PROCESSING_ON: + url = reverse('promembership') + return HttpResponseRedirect(url) + r = getrequestrower(request) return render(request, @@ -1407,6 +1456,10 @@ def payment_completed_view(request): @login_required() def downgrade_completed_view(request): + if not PAYMENT_PROCESSING_ON: + url = reverse('promembership') + return HttpResponseRedirect(url) + r = getrequestrower(request) return render(request, @@ -1864,6 +1917,33 @@ def plannedsessions_icsemail_view(request,userid=0): return response +@login_required() +def transactions_view(request): + if not request.user.is_staff: + raise PermissionDenied("Not Allowed") + + if request.method == 'POST': + dateform = DateRangeForm(request.POST) + if dateform.is_valid(): + startdate = dateform.cleaned_data['startdate'] + enddate = dateform.cleaned_data['enddate'] + + df = braintreestuff.get_transactions(startdate,enddate) + filename="transactions_{s}_{e}.csv".format(s = startdate, e = enddate) + response = HttpResponse(df.to_csv()) + response['Content-Disposition'] = 'attachment; filename="%s"' % filename + response['Content-Type'] = 'application/octet-stream' + + return response + + else: + dateform = DateRangeForm() + + return render(request, + 'transactions.html', + { + 'dateform':dateform + }) @login_required() def course_kmlemail_view(request,id=0): diff --git a/rowsandall_app/settings.py b/rowsandall_app/settings.py index 7aedf773..b96c3f66 100644 --- a/rowsandall_app/settings.py +++ b/rowsandall_app/settings.py @@ -439,3 +439,8 @@ try: BRAINTREE_PRIVATE_KEY = CFG['braintree_private_key'] except KeyError: BRAINTREE_PRIVATE_KEY = '' + +try: + PAYMENT_PROCESSING_ON = CFG['payment_processing_on'] +except KeyError: + PAYMENT_PROCESSING_ON = False