1094 lines
40 KiB
Python
1094 lines
40 KiB
Python
from django.utils.encoding import force_bytes, force_str
|
|
from rowers.tokens import account_activation_token
|
|
from django.contrib.sites.shortcuts import get_current_site
|
|
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
|
|
from django.contrib.auth.backends import ModelBackend
|
|
from rowers.views.statements import *
|
|
from django.core.mail import EmailMessage
|
|
|
|
from rowers import credits
|
|
|
|
@login_required()
|
|
def rower_idoklad_authorize(request):
|
|
state=str(uuid4())
|
|
|
|
params = {
|
|
"client_id":IDOKLAD_CLIENT_ID,
|
|
"response_type": "code",
|
|
"redirect_uri": IDOKLAD_REDIRECT_URI,
|
|
"scope": "idoklad_api offline_access",
|
|
}
|
|
|
|
url = "https://identity.idoklad.cz/server/connect/authorize?"+urllib.parse.urlencode(params)
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
@login_required()
|
|
def process_idokladcallback(request):
|
|
dologging('idoklad.log',' /rowers/idokladcallback/')
|
|
|
|
try:
|
|
code = request.GET['code']
|
|
except KeyError:
|
|
error = request.GET['error']
|
|
messages.error(request,error)
|
|
return HttpResponseRedirect(reverse('workouts_view'))
|
|
|
|
post_data = {
|
|
'grant_type': "authorization_code",
|
|
'client_id': IDOKLAD_CLIENT_ID,
|
|
'client_secret': IDOKLAD_CLIENT_SECRET,
|
|
'scope': 'idoklad_api offline_access',
|
|
'code': code,
|
|
'redirect_uri': IDOKLAD_REDIRECT_URI,
|
|
}
|
|
|
|
headers = {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
}
|
|
|
|
base_url = 'https://identity.idoklad.cz/server/connect/token'
|
|
|
|
response = requests.post(base_url, data=post_data, headers=headers)
|
|
|
|
if response.status_code == 200:
|
|
result = response.json()
|
|
try:
|
|
t = iDokladToken.objects.get(id=1)
|
|
t.acces_token = result['access_token'],
|
|
t.refresh_token = result['refresh_token']
|
|
t.expires_in = result['expires_in']
|
|
t.id_token = result['id_token']
|
|
t.save()
|
|
except iDokladToken.DoesNotExist:
|
|
t = iDokladToken(
|
|
access_token = result['access_token'],
|
|
refresh_token = result['refresh_token'],
|
|
expires_in = result['expires_in'],
|
|
)
|
|
t.save()
|
|
messages.info(request,"Token refreshed and stored")
|
|
else:
|
|
messages.error(request,"Error")
|
|
|
|
url = reverse('rower_exportsettings_view')
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
@csrf_exempt
|
|
def braintree_webhook_view(request):
|
|
dologging('braintreewebhooks.log',' /rowers/braintree/')
|
|
if request.method == 'POST':
|
|
result = braintreestuff.webhook(request)
|
|
if result == 4: # pragma: no cover
|
|
raise PermissionDenied("Not allowed")
|
|
|
|
return HttpResponse('')
|
|
|
|
|
|
def paidplans_view(request):
|
|
if not request.user.is_anonymous:
|
|
r = request.user.rower
|
|
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
|
|
messages.error(request, 'Automated payment processing is currently only available through" \
|
|
" BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal." \
|
|
" Contact the site administrator at support@rowsandall.com before you proceed')
|
|
else:
|
|
r = None
|
|
|
|
return render(request,
|
|
'paidplans.html',
|
|
{'rower': r})
|
|
|
|
|
|
@login_required()
|
|
def billing_view(request):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
r = request.user.rower
|
|
|
|
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
|
|
messages.error(request, 'Automated payment processing is currently only available through" \
|
|
" BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal." \
|
|
" Contact the site administrator at support@rowsandall.com before you proceed')
|
|
|
|
if payments.is_existing_customer(r): # pragma: no cover
|
|
url = reverse(upgrade_view)
|
|
return HttpResponseRedirect(url)
|
|
|
|
if request.method == 'POST':
|
|
billingaddressform = RowerBillingAddressForm(request.POST)
|
|
planselectform = PlanSelectForm(
|
|
request.POST, paymentprocessor='braintree')
|
|
if billingaddressform.is_valid():
|
|
cd = billingaddressform.cleaned_data
|
|
for attr, value in cd.items():
|
|
setattr(r, attr, value)
|
|
r.save()
|
|
|
|
if billingaddressform.is_valid():
|
|
if planselectform.is_valid():
|
|
plan = planselectform.cleaned_data['plan']
|
|
try:
|
|
_ = braintreestuff.create_customer(r)
|
|
except ProcessorCustomerError: # pragma: no cover
|
|
messages.error(
|
|
request, "Something went wrong registering you as a customer.")
|
|
url = reverse(billing_view)
|
|
return HttpResponseRedirect(url)
|
|
url = reverse(payment_confirm_view,
|
|
kwargs={
|
|
'planid': plan.id
|
|
})
|
|
return HttpResponseRedirect(url)
|
|
|
|
else:
|
|
billingaddressform = RowerBillingAddressForm(instance=r)
|
|
planselectform = PlanSelectForm(paymentprocessor='braintree')
|
|
|
|
return render(request,
|
|
'billing.html',
|
|
{'rower': r,
|
|
'billingaddressform': billingaddressform,
|
|
'planselectform': planselectform,
|
|
})
|
|
|
|
|
|
def buy_trainingplan_view(request, id=0):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
r = request.user.rower
|
|
|
|
targets = TrainingTarget.objects.filter(
|
|
rowers=r,
|
|
date__gte=timezone.now(),
|
|
).order_by("-date")
|
|
|
|
plan = get_object_or_404(InstantPlan, pk=id)
|
|
|
|
if r.paymentprocessor != 'braintree': # pragma: no cover
|
|
messages.error(
|
|
request, "This purchase is currently only available through BrainTree (by PayPal)")
|
|
|
|
if id == 0 or id is None: # pragma: no cover
|
|
messages.error(request, "There was an error accessing this plan")
|
|
url = reverse('rower_view_instantplan', kwargs={
|
|
'id': plan.uuid,
|
|
})
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
if request.method == 'POST':
|
|
billingaddressform = RowerBillingAddressForm(instance=r)
|
|
form = InstantPlanSelectForm(request.POST, targets=targets)
|
|
if billingaddressform.is_valid(): # pragma: no cover
|
|
cd = billingaddressform.cleaned_data
|
|
for attr, value in cd.items():
|
|
setattr(r, attr, value)
|
|
r.save()
|
|
|
|
# redirect to payment confirmation view
|
|
if form.is_valid():
|
|
cd = form.cleaned_data
|
|
|
|
enddate = cd['enddate']
|
|
startdate = cd['startdate']
|
|
notes = cd['notes']
|
|
datechoice = form.cleaned_data['datechoice']
|
|
status = True
|
|
|
|
# get target and set enddate
|
|
try: # pragma: no cover
|
|
targetid = cd['target']
|
|
target = TrainingTarget.objects.get(id=int(targetid))
|
|
except (KeyError, ValueError):
|
|
try:
|
|
targetid = request.POST['target']
|
|
|
|
if targetid != '': # pragma: no cover
|
|
target = TrainingTarget.objects.get(id=int(targetid))
|
|
else: # pragma: no cover
|
|
target = None
|
|
except KeyError:
|
|
target = None
|
|
|
|
if target and datechoice == 'target': # pragma: no cover
|
|
enddate = target.date
|
|
elif datechoice == 'startdate': # pragma: no cover
|
|
enddate = startdate+datetime.timedelta(days=plan.duration)
|
|
else:
|
|
startdate = enddate-datetime.timedelta(days=plan.duration)
|
|
|
|
pars = {
|
|
'name': cd['name'],
|
|
'enddate': enddate,
|
|
'notes': notes,
|
|
'status': status,
|
|
'rower': r.id,
|
|
}
|
|
params = urllib.parse.urlencode(pars)
|
|
url = reverse('confirm_trainingplan_purchase_view',
|
|
kwargs={'id': plan.id})
|
|
url = url + "?%s" % params
|
|
return HttpResponseRedirect(url)
|
|
|
|
else:
|
|
form = InstantPlanForm()
|
|
billingaddressform = RowerBillingAddressForm(instance=r)
|
|
|
|
return render(request,
|
|
'buy_trainingplan.html',
|
|
{
|
|
'rower': r,
|
|
'plan': plan,
|
|
'billingaddressform': billingaddressform,
|
|
'form': form,
|
|
})
|
|
|
|
|
|
def purchase_checkouts_view(request):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
r = request.user.rower
|
|
|
|
if request.method != 'POST': # pragma: no cover
|
|
url = reverse('rower_view_instantplan', kwargs={
|
|
'id': plan.uuid,
|
|
})
|
|
return HttpResponseRedirect(url)
|
|
|
|
if r.rowerplan == 'freecoach': # pragma: no cover
|
|
messages.error(
|
|
request, 'You cannot purchase this training plan as a free coach member')
|
|
url = reverse('rower_view_instantplan', kwargs={
|
|
'id': plan.uuid,
|
|
})
|
|
return HttpResponseRedirect(url)
|
|
|
|
form = TrainingPlanBillingForm(request.POST)
|
|
if form.is_valid():
|
|
|
|
data = form.cleaned_data
|
|
|
|
plan = InstantPlan.objects.get(id=data['plan'])
|
|
authorizationstring = 'Bearer '+settings.WORKOUTS_FIT_TOKEN
|
|
url = settings.WORKOUTS_FIT_URL+"/trainingplan/"+str(plan.uuid)
|
|
headers = {'Authorization': authorizationstring}
|
|
response = requests.get(url=url, headers=headers)
|
|
if response.status_code != 200: # pragma: no cover
|
|
messages.error(
|
|
request, "Could not connect to the training plan server")
|
|
return HttpResponseRedirect(reverse('rower_select_instantplan'))
|
|
|
|
amount, success = braintreestuff.make_payment(r, data)
|
|
diff = plan.price - int(amount)
|
|
|
|
_ = credits.withdraw(diff, r)
|
|
|
|
if success:
|
|
messages.info(
|
|
request, "Your payment was completed and the sessions are copied to your calendar")
|
|
plansteps = response.json()
|
|
name = data['name']
|
|
enddate = data['enddate']
|
|
notes = data['notes']
|
|
status = data['status']
|
|
startdate = enddate-datetime.timedelta(days=plan.duration)
|
|
|
|
# upgrade rower
|
|
if r.rowerplan == 'basic': # pragma: no cover
|
|
messages.info(
|
|
request, 'You have been upgraded to the Self-Coach plan for the duration of the plan')
|
|
r.rowerplan = 'plan'
|
|
r.planexpires = enddate
|
|
r.save()
|
|
|
|
p = TrainingPlan(
|
|
name=name,
|
|
# target=target,
|
|
manager=r,
|
|
startdate=startdate,
|
|
enddate=enddate, status=status,
|
|
notes=notes,
|
|
)
|
|
|
|
p.save()
|
|
|
|
p.rowers.add(r)
|
|
|
|
create_sessions_from_json(plansteps, r, startdate, r.user)
|
|
|
|
_ = myqueue(queuehigh, handle_send_email_instantplan_notification,
|
|
r.user.username,
|
|
r.user.email,
|
|
plan.price,
|
|
plan.name,
|
|
startdate,
|
|
enddate)
|
|
|
|
url = reverse('plannedsessions_view')
|
|
timeperiod = startdate.strftime(
|
|
'%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d')
|
|
url = url+'?when='+timeperiod
|
|
|
|
return HttpResponseRedirect(url)
|
|
else: # pragma: no cover
|
|
messages.error(request, "There was a problem processing your payment. If the problem persists, please contact me through the <a href='/rowers/email/'>contact form</a>.")
|
|
url = reverse('rower_view_instantplan', kwargs={
|
|
'id': plan.uuid,
|
|
})
|
|
return HttpResponseRedirect(url)
|
|
elif 'tac' not in request.POST: # pragma: no cover
|
|
try:
|
|
enddate = request.POST['enddate']
|
|
# incomplete
|
|
except IndexError:
|
|
messages.error(request, "There was an error in the payment form")
|
|
url = reverse("purchase_checkouts_view")
|
|
return HttpResponseRedirect(url)
|
|
else: # pragma: no cover
|
|
messages.error(request, "There was an error in the payment form")
|
|
|
|
url = reverse('rower_select_instantplan') # pragma: no cover
|
|
if 'plan' in request.POST: # pragma: no cover
|
|
plan = plan = InstantPlan.objects.get(id=request.POST['plan'])
|
|
url = reverse('rower_view_instantplan', kwargs={
|
|
'id': plan.uuid,
|
|
})
|
|
return HttpResponseRedirect(url) # pragma: no cover
|
|
|
|
|
|
def confirm_trainingplan_purchase_view(request, id=0):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
if not can_plan(request.user):
|
|
url = reverse('paidplans_view')
|
|
messages.info(request,'You need to upgrade to Self-Coach or Coach first. On your training plan purchases you will get a discount.')
|
|
return HttpResponseRedirect(url)
|
|
|
|
r = request.user.rower
|
|
|
|
plan = get_object_or_404(InstantPlan, pk=id)
|
|
|
|
if r.paymentprocessor != 'braintree': # pragma: no cover
|
|
messages.error(
|
|
request, "This purchase is currently only available through BrainTree (by PayPal)")
|
|
|
|
if id == 0 or id is None: # pragma: no cover
|
|
messages.error(request, "There was an error accessing this plan")
|
|
url = reverse('rower_view_instantplan', kwargs={
|
|
'id': plan.uuid,
|
|
})
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
client_token = braintreestuff.get_client_token(r)
|
|
|
|
enddate = request.GET.get('enddate', None)
|
|
name = request.GET.get('name', '')
|
|
status = request.GET.get('status', True)
|
|
notes = request.GET.get('notes', '')
|
|
if enddate is None: # pragma: no cover
|
|
messages.error(request, "There was an error accessing this plan")
|
|
url = reverse('rower_view_instantplan', kwargs={
|
|
'id': plan.uuid,
|
|
})
|
|
|
|
return render(request,
|
|
'confirm_trainingplan.html',
|
|
{
|
|
'plan': plan,
|
|
'client_token': client_token,
|
|
'rower': r,
|
|
'enddate': enddate,
|
|
'status': status,
|
|
'name': name,
|
|
'notes': notes,
|
|
})
|
|
|
|
|
|
@login_required()
|
|
def upgrade_view(request):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
r = request.user.rower
|
|
|
|
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
|
|
messages.error(request, 'Automated payment processing is currently only available through" \
|
|
" BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal." \
|
|
" Contact the site administrator at support@rowsandall.com before you proceed')
|
|
|
|
if r.subscription_id is None or r.subscription_id == '': # pragma: no cover
|
|
url = reverse(billing_view)
|
|
return HttpResponseRedirect(url)
|
|
|
|
if request.method == 'POST':
|
|
billingaddressform = RowerBillingAddressForm(request.POST)
|
|
planselectform = PlanSelectForm(
|
|
request.POST, paymentprocessor='braintree')
|
|
if billingaddressform.is_valid():
|
|
cd = billingaddressform.cleaned_data
|
|
for attr, value in cd.items():
|
|
setattr(r, attr, value)
|
|
r.save()
|
|
|
|
if planselectform.is_valid():
|
|
plan = planselectform.cleaned_data['plan']
|
|
if billingaddressform.is_valid():
|
|
url = reverse(upgrade_confirm_view,
|
|
kwargs={
|
|
'planid': plan.id
|
|
})
|
|
return HttpResponseRedirect(url)
|
|
|
|
else:
|
|
billingaddressform = RowerBillingAddressForm(instance=r)
|
|
planselectform = PlanSelectForm(paymentprocessor='braintree',
|
|
rower=r)
|
|
|
|
return render(request,
|
|
'upgrade.html',
|
|
{'rower': r,
|
|
'billingaddressform': billingaddressform,
|
|
'planselectform': planselectform,
|
|
})
|
|
|
|
|
|
@login_required()
|
|
def downgrade_view(request):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
r = request.user.rower
|
|
|
|
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
|
|
messages.error(request, 'Automated payment processing is currently only available through" \
|
|
" BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal." \
|
|
" Contact the site administrator at support@rowsandall.com before you proceed')
|
|
|
|
if r.subscription_id is None or r.subscription_id == '': # pragma: no cover
|
|
url = reverse(billing_view)
|
|
return HttpResponseRedirect(url)
|
|
|
|
if request.method == 'POST':
|
|
billingaddressform = RowerBillingAddressForm(request.POST)
|
|
planselectform = PlanSelectForm(
|
|
request.POST, paymentprocessor='braintree')
|
|
if billingaddressform.is_valid():
|
|
cd = billingaddressform.cleaned_data
|
|
for attr, value in cd.items():
|
|
setattr(r, attr, value)
|
|
r.save()
|
|
|
|
if planselectform.is_valid():
|
|
plan = planselectform.cleaned_data['plan']
|
|
|
|
if plan.price > r.paidplan.price: # pragma: no cover
|
|
nextview = upgrade_confirm_view
|
|
elif plan.price == r.paidplan.price: # pragma: no cover
|
|
messages.info(request, 'You did not select a new plan')
|
|
url = reverse(downgrade_view)
|
|
return HttpResponseRedirect(url)
|
|
else:
|
|
nextview = downgrade_confirm_view
|
|
|
|
if billingaddressform.is_valid():
|
|
url = reverse(nextview,
|
|
kwargs={
|
|
'planid': plan.id
|
|
})
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
else:
|
|
billingaddressform = RowerBillingAddressForm(instance=r)
|
|
planselectform = PlanSelectForm(paymentprocessor='braintree',
|
|
rower=r, includeall=True, initial={'plan': r.paidplan})
|
|
|
|
return render(request,
|
|
'downgrade.html',
|
|
{'rower': r,
|
|
'billingaddressform': billingaddressform,
|
|
'planselectform': planselectform,
|
|
})
|
|
|
|
|
|
@login_required()
|
|
def plan_stop_view(request):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
r = request.user.rower
|
|
|
|
subscriptions = []
|
|
|
|
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
|
|
messages.error(request, 'Automated payment processing is currently only available through" \
|
|
" BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal." \
|
|
" Contact the site administrator at support@rowsandall.com before you proceed')
|
|
|
|
if r.paidplan is not None and r.paidplan.paymentprocessor == 'braintree':
|
|
try:
|
|
subscriptions = braintreestuff.find_subscriptions(r)
|
|
except ProcessorCustomerError: # pragma: no cover
|
|
r.paymentprocessor = None
|
|
r.save()
|
|
|
|
return render(request,
|
|
'subscriptions_cancel.html',
|
|
{'rower': r,
|
|
'subscriptions': subscriptions
|
|
})
|
|
|
|
|
|
@login_required()
|
|
def plan_tobasic_view(request, id=0):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
r = request.user.rower
|
|
|
|
if r.paidplan.paymentprocessor == 'braintree': # pragma: no cover
|
|
success, themessages, errormessages = braintreestuff.cancel_subscription(
|
|
r, id)
|
|
for message in themessages:
|
|
messages.info(request, message)
|
|
|
|
for message in errormessages:
|
|
messages.error(request, message)
|
|
|
|
url = reverse(plan_stop_view)
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
|
|
@login_required()
|
|
def upgrade_confirm_view(request, planid=0):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
try:
|
|
plan = PaidPlan.objects.get(id=planid)
|
|
except PaidPlan.DoesNotExist: # pragma: no cover
|
|
messages.error(request, "Something went wrong. Please try again.")
|
|
url = reverse(billing_view)
|
|
return HttpResponseRedirect(url)
|
|
|
|
r = request.user.rower
|
|
|
|
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
|
|
messages.error(request, 'Automated payment processing is currently only available through" \
|
|
" BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal." \
|
|
" Contact the site administrator at support@rowsandall.com before you proceed')
|
|
|
|
client_token = braintreestuff.get_client_token(r)
|
|
|
|
return render(request,
|
|
"upgradeconfirm.html",
|
|
{
|
|
'plan': plan,
|
|
'client_token': client_token,
|
|
'rower': r,
|
|
})
|
|
|
|
|
|
@login_required()
|
|
def downgrade_confirm_view(request, planid=0):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
try:
|
|
plan = PaidPlan.objects.get(id=planid)
|
|
except PaidPlan.DoesNotExist: # pragma: no cover
|
|
messages.error(request, "Something went wrong. Please try again.")
|
|
url = reverse(billing_view)
|
|
return HttpResponseRedirect(url)
|
|
|
|
r = request.user.rower
|
|
|
|
client_token = braintreestuff.get_client_token(r)
|
|
|
|
return render(request,
|
|
"downgradeconfirm.html",
|
|
{
|
|
'plan': plan,
|
|
'client_token': client_token,
|
|
'rower': r,
|
|
})
|
|
|
|
|
|
@login_required()
|
|
def payment_confirm_view(request, planid=0):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
try:
|
|
plan = PaidPlan.objects.get(id=planid)
|
|
except PaidPlan.DoesNotExist: # pragma: no cover
|
|
messages.error(request, "Something went wrong. Please try again.")
|
|
url = reverse(billing_view)
|
|
return HttpResponseRedirect(url)
|
|
|
|
r = request.user.rower
|
|
|
|
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
|
|
messages.error(request, 'Automated payment processing is currently only available through" \
|
|
" BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal." \
|
|
" Contact the site administrator at support@rowsandall.com before you proceed')
|
|
|
|
client_token = braintreestuff.get_client_token(r)
|
|
|
|
return render(request,
|
|
"paymentconfirm.html",
|
|
{
|
|
'plan': plan,
|
|
'client_token': client_token,
|
|
'rower': r,
|
|
})
|
|
|
|
|
|
@login_required()
|
|
def checkouts_view(request):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
r = request.user.rower
|
|
|
|
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
|
|
messages.error(request, 'Automated payment processing is currently only" \
|
|
" available through BrainTree (by PayPal). " \
|
|
"You are currently on a recurring payment plan with PayPal." \
|
|
" Contact the site administrator at support@rowsandall.com before you proceed')
|
|
|
|
if request.method != 'POST': # pragma: no cover
|
|
url = reverse(paidplans_view)
|
|
return HttpResponseRedirect(url)
|
|
|
|
form = BillingForm(request.POST)
|
|
if form.is_valid():
|
|
data = form.cleaned_data
|
|
success, amount = braintreestuff.create_subscription(r, data)
|
|
if success:
|
|
messages.info(
|
|
request, "Your payment has succeeded and your plan has been updated")
|
|
url = "{baseurl}?amount={amount:.2f}".format(
|
|
baseurl=reverse(payment_completed_view),
|
|
amount=amount)
|
|
return HttpResponseRedirect(url)
|
|
else: # pragma: no cover
|
|
messages.error(request, "There was a problem with your payment")
|
|
url = reverse(billing_view)
|
|
return HttpResponseRedirect(url)
|
|
elif 'tac' not in request.POST: # pragma: no cover
|
|
try:
|
|
planid = int(request.POST['plan'])
|
|
url = reverse('payment_confirm_view', kwargs={'planid': planid})
|
|
messages.error(
|
|
request, "You must review and acknowledge the terms and conditions")
|
|
return HttpResponseRedirect(url)
|
|
except IndexError:
|
|
messages.error(request, "There was an error in the payment form")
|
|
url = reverse('billing_view')
|
|
return HttpResponseRedirect(url)
|
|
else: # pragma: no cover
|
|
messages.error(request, "There was an error in the payment form")
|
|
url = reverse(billing_view)
|
|
return HttpResponseRedirect(url)
|
|
|
|
url = reverse(paidplans_view) # pragma: no cover
|
|
return HttpResponseRedirect(url) # pragma: no cover
|
|
|
|
|
|
@login_required()
|
|
def upgrade_checkouts_view(request):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
r = request.user.rower
|
|
|
|
if request.method != 'POST': # pragma: no cover
|
|
url = reverse(paidplans_view)
|
|
return HttpResponseRedirect(url)
|
|
|
|
form = BillingForm(request.POST)
|
|
if form.is_valid():
|
|
data = form.cleaned_data
|
|
success, amount = braintreestuff.update_subscription(r, data)
|
|
if success:
|
|
messages.info(
|
|
request, "Your payment has succeeded and your plan has been updated")
|
|
url = "{baseurl}?amount={amount:.2f}".format(
|
|
baseurl=reverse(payment_completed_view),
|
|
amount=amount)
|
|
return HttpResponseRedirect(url)
|
|
else: # pragma: no cover
|
|
messages.error(request, "There was a problem with your payment")
|
|
url = reverse(upgrade_view)
|
|
return HttpResponseRedirect(url)
|
|
|
|
elif 'tac' not in request.POST: # pragma: no cover
|
|
try:
|
|
planid = int(request.POST['plan'])
|
|
url = reverse('upgrade_confirm_view', kwargs={'planid': planid})
|
|
messages.error(
|
|
request, "You must review and acknowledge the terms and conditions")
|
|
return HttpResponseRedirect(url)
|
|
except IndexError:
|
|
messages.error(request, "There was an error in the payment form")
|
|
url = reverse('billing_view')
|
|
return HttpResponseRedirect(url)
|
|
else: # pragma: no cover
|
|
messages.error(request, "There was an error in the payment form")
|
|
url = reverse(upgrade_view)
|
|
return HttpResponseRedirect(url)
|
|
|
|
url = reverse(paidplans_view) # pragma: no cover
|
|
return HttpResponseRedirect(url) # pragma: no cover
|
|
|
|
|
|
@login_required()
|
|
def downgrade_checkouts_view(request):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
r = request.user.rower
|
|
|
|
if request.method != 'POST': # pragma: no cover
|
|
url = reverse(paidplans_view)
|
|
return HttpResponseRedirect(url)
|
|
|
|
form = BillingForm(request.POST)
|
|
if form.is_valid():
|
|
data = form.cleaned_data
|
|
success = braintreestuff.update_subscription(r, data, method='down')
|
|
if success:
|
|
messages.info(request, "Your plan has been updated")
|
|
url = reverse(downgrade_completed_view)
|
|
return HttpResponseRedirect(url)
|
|
else: # pragma: no cover
|
|
messages.error(
|
|
request, "There was a problem with your transaction")
|
|
url = reverse(upgrade_view)
|
|
return HttpResponseRedirect(url)
|
|
elif 'tac' not in request.POST: # pragma: no cover
|
|
try:
|
|
planid = int(request.POST['plan'])
|
|
url = reverse('downgrade_confirm_view', kwargs={'planid': planid})
|
|
messages.error(
|
|
request, "You must review and acknowledge the terms and conditions")
|
|
return HttpResponseRedirect(url)
|
|
except IndexError:
|
|
messages.error(request, "There was an error in the payment form")
|
|
url = reverse('billing_view')
|
|
return HttpResponseRedirect(url)
|
|
|
|
else: # pragma: no cover
|
|
messages.error(request, "There was an error in the payment form")
|
|
url = reverse(upgrade_view)
|
|
return HttpResponseRedirect(url)
|
|
|
|
url = reverse(paidplans_view) # pragma: no cover
|
|
return HttpResponseRedirect(url) # pragma: no cover
|
|
|
|
|
|
@login_required()
|
|
def payment_completed_view(request):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
amount = request.GET.get('amount', 0)
|
|
|
|
r = request.user.rower
|
|
|
|
return render(request,
|
|
"payment_completed.html",
|
|
{
|
|
'rower': r,
|
|
'amount': amount,
|
|
})
|
|
|
|
|
|
@login_required()
|
|
def downgrade_completed_view(request):
|
|
if not PAYMENT_PROCESSING_ON: # pragma: no cover
|
|
url = reverse('promembership')
|
|
return HttpResponseRedirect(url)
|
|
|
|
r = request.user.rower
|
|
|
|
return render(request,
|
|
"downgrade_completed.html",
|
|
{
|
|
'rower': r
|
|
})
|
|
|
|
|
|
# Email activation
|
|
|
|
|
|
def useractivate(request, uidb64, token): # pragma: no cover
|
|
try:
|
|
uid = force_str(urlsafe_base64_decode(uidb64))
|
|
user = User.objects.get(id=uid)
|
|
except(TypeError, ValueError, OverflowError, User.DoesNotExist):
|
|
user = None
|
|
if user is not None and account_activation_token.check_token(user, token):
|
|
user.is_active = True
|
|
user.save()
|
|
# below is old
|
|
fullemail = user.first_name + " " + user.last_name + " " + "<" + user.email + ">"
|
|
subject = "Thank you for registering on rowsandall.com"
|
|
from_address = 'Sander Roosendaal <info@rowsandall.com>'
|
|
|
|
d = {'first_name': user.first_name}
|
|
|
|
template = 'registeremail.html'
|
|
if user.rower.rowerplan == 'freecoach':
|
|
template = 'coachregisteremail.html'
|
|
|
|
send_template_email(from_address, [fullemail],
|
|
subject, template, d)
|
|
|
|
subject2 = "New User"
|
|
message2 = "New user registered.\n"
|
|
message2 += fullemail + "\n"
|
|
message2 += "User name: "+user.username
|
|
|
|
if user.rower.rowerplan == 'freecoach':
|
|
subject2 = "New Free Coach User"
|
|
|
|
send_mail(subject2, message2,
|
|
'Rowsandall Server <info@rowsandall.com>',
|
|
['roosendaalsander@gmail.com'])
|
|
|
|
messages.info(
|
|
request, 'Thank you for your email confirmation. You are now signed in to your account.')
|
|
login(request, user, backend='django.contrib.auth.backends.ModelBackend')
|
|
url = reverse('workouts_view')
|
|
# if user.rower.rowerplan == 'freecoach':
|
|
# url+='?next=/rowers/me/teams'
|
|
return HttpResponseRedirect(url)
|
|
else:
|
|
return render(request,
|
|
"invalid_activation.html",
|
|
{})
|
|
|
|
|
|
# User registration
|
|
def rower_register_view(request):
|
|
|
|
nextpage = request.GET.get('next', '/rowers/list-workouts/')
|
|
if nextpage == '': # pragma: no cover
|
|
nextpage = '/rowers/list-workouts/'
|
|
|
|
if request.method == 'POST':
|
|
form = RegistrationFormSex(request.POST)
|
|
if form.is_valid():
|
|
first_name = form.cleaned_data['first_name']
|
|
last_name = form.cleaned_data['last_name']
|
|
email = form.cleaned_data['email']
|
|
password = form.cleaned_data['password1']
|
|
username = form.cleaned_data['username']
|
|
sex = form.cleaned_data['sex']
|
|
birthdate = form.cleaned_data['birthdate']
|
|
weightcategory = form.cleaned_data['weightcategory']
|
|
adaptiveclass = form.cleaned_data['adaptiveclass']
|
|
nextpage = request.POST['next']
|
|
try:
|
|
theuser = User.objects.create_user(username, password=password)
|
|
except:
|
|
messages.error(request, "This user name already exists, choose another one")
|
|
url = reverse('rower_register_view')
|
|
return HttpResponseRedirect(url)
|
|
theuser.first_name = first_name
|
|
theuser.last_name = last_name
|
|
theuser.email = email
|
|
theuser.is_active = False
|
|
theuser.save()
|
|
|
|
birthdate = birthdate.replace(tzinfo=None)
|
|
|
|
therower = Rower(user=theuser, sex=sex, birthdate=birthdate,
|
|
weightcategory=weightcategory,
|
|
adaptiveclass=adaptiveclass)
|
|
|
|
therower.save()
|
|
|
|
# create default favorite charts
|
|
add_defaultfavorites(therower)
|
|
|
|
# Create Sample workout
|
|
f = 'media/testdata.csv.gz'
|
|
timestr = strftime("%Y%m%d-%H%M%S")
|
|
f2 = f[:-7]+timestr+'.csv.gz'
|
|
copyfile(f, f2)
|
|
|
|
response = dataprep.new_workout_from_file(therower, f2,
|
|
title='New User Sample Data',
|
|
notes='This is an example workout to get you started')
|
|
newworkoutid = response[0]
|
|
if newworkoutid:
|
|
w = Workout.objects.get(id=newworkoutid)
|
|
w.startdatetime = timezone.now()
|
|
w.date = timezone.now().date()
|
|
w.save()
|
|
|
|
# Create and send email
|
|
current_site = get_current_site(request)
|
|
mail_subject = 'Activate your account.'
|
|
to_email = form.cleaned_data.get('email')
|
|
message = render_to_string('acc_activate_email.html', {
|
|
'user': theuser,
|
|
'domain': current_site.domain,
|
|
'uid': urlsafe_base64_encode(force_bytes(theuser.id)),
|
|
'token': account_activation_token.make_token(theuser),
|
|
})
|
|
to_email = form.cleaned_data.get('email')
|
|
email = EmailMessage(
|
|
mail_subject, message, to=[to_email]
|
|
)
|
|
email.send()
|
|
return render(request, 'confirmemailpage.html', {'address': to_email})
|
|
|
|
# login(request,theuser)
|
|
|
|
# return HttpResponseRedirect(nextpage)
|
|
# '/rowers/register/thankyou/')
|
|
|
|
else: # pragma: no cover
|
|
return render(request,
|
|
"registration_form.html",
|
|
{'form': form,
|
|
'next': nextpage, })
|
|
else:
|
|
form = RegistrationFormSex()
|
|
return render(request,
|
|
"registration_form.html",
|
|
{'form': form,
|
|
'next': nextpage, })
|
|
|
|
# User registration
|
|
|
|
|
|
def freecoach_register_view(request): # pragma: no cover
|
|
|
|
nextpage = request.GET.get('next', '/rowers/me/teams/')
|
|
if nextpage == '': # pragma: no cover
|
|
nextpage = '/rowers/me/teams/'
|
|
|
|
if request.method == 'POST':
|
|
form = RegistrationFormSex(request.POST)
|
|
if form.is_valid():
|
|
first_name = form.cleaned_data['first_name']
|
|
last_name = form.cleaned_data['last_name']
|
|
email = form.cleaned_data['email']
|
|
password = form.cleaned_data['password1']
|
|
username = form.cleaned_data['username']
|
|
sex = form.cleaned_data['sex']
|
|
birthdate = form.cleaned_data['birthdate']
|
|
weightcategory = form.cleaned_data['weightcategory']
|
|
adaptiveclass = form.cleaned_data['adaptiveclass']
|
|
nextpage = request.POST['next']
|
|
theuser = User.objects.create_user(username, password=password)
|
|
theuser.first_name = first_name
|
|
theuser.last_name = last_name
|
|
theuser.email = email
|
|
theuser.save()
|
|
|
|
birthdate = birthdate.replace(tzinfo=None)
|
|
|
|
therower = Rower(user=theuser, sex=sex, birthdate=birthdate,
|
|
weightcategory=weightcategory,
|
|
adaptiveclass=adaptiveclass,
|
|
rowerplan='freecoach', clubsize=10)
|
|
|
|
therower.save()
|
|
|
|
# create default favorite charts
|
|
add_defaultfavorites(therower)
|
|
|
|
# Create and send email
|
|
current_site = get_current_site(request)
|
|
mail_subject = 'Activate your account.'
|
|
to_email = form.cleaned_data.get('email')
|
|
message = render_to_string('acc_activate_email.html', {
|
|
'user': theuser,
|
|
'domain': current_site.domain,
|
|
'uid': urlsafe_base64_encode(force_bytes(theuser.id)),
|
|
'token': account_activation_token.make_token(theuser),
|
|
})
|
|
to_email = form.cleaned_data.get('email')
|
|
email = EmailMessage(
|
|
mail_subject, message, to=[to_email]
|
|
)
|
|
email.send()
|
|
return HttpResponse('Please confirm your email address to complete the registration')
|
|
|
|
return HttpResponseRedirect(nextpage)
|
|
|
|
else: # pragma: no cover
|
|
return render(request,
|
|
"freecoach_registration_form.html",
|
|
{'form': form,
|
|
'next': nextpage, })
|
|
else:
|
|
form = RegistrationFormSex()
|
|
form.fields.pop('sex')
|
|
form.fields.pop('weightcategory')
|
|
form.fields.pop('adaptiveclass')
|
|
return render(request,
|
|
"freecoach_registration_form.html",
|
|
{'form': form,
|
|
'next': nextpage, })
|
|
|
|
|
|
@login_required()
|
|
@permission_required('rower.is_staff', fn=get_user_by_userid, raise_exception=True)
|
|
def transactions_view(request): # pragma: no cover
|
|
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
|
|
})
|