works but cannot change address
This commit is contained in:
@@ -183,7 +183,7 @@ def make_payment(rower,data):
|
|||||||
return False,0
|
return False,0
|
||||||
|
|
||||||
amount = data['amount']
|
amount = data['amount']
|
||||||
amount = '{amount:.f2}'.format(amount=amount)
|
amount = '{amount}'.format(amount=amount)
|
||||||
|
|
||||||
result = gateway.transaction.sale({
|
result = gateway.transaction.sale({
|
||||||
"amount": amount,
|
"amount": amount,
|
||||||
@@ -200,13 +200,18 @@ def make_payment(rower,data):
|
|||||||
l = rower.user.last_name,
|
l = rower.user.last_name,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fakturoid_contact_id = fakturoid.get_contacts(rower)
|
||||||
|
if not fakturoid_contact_id:
|
||||||
|
fakturoid_contact_id = fakturoid.create_contact(rower)
|
||||||
|
id = fakturoid.create_invoice(rower,amount,transaction.id,dosend=True,contact_id=fakturoid_contact_id,
|
||||||
|
name='Rowsandall Purchase')
|
||||||
|
|
||||||
job = myqueue(queuehigh,handle_send_email_transaction,
|
job = myqueue(queuehigh,handle_send_email_transaction,
|
||||||
name, rower.user.email, amount)
|
name, rower.user.email, amount)
|
||||||
|
|
||||||
return amount,''
|
return amount,True
|
||||||
else:
|
else:
|
||||||
return 0,''
|
return 0,False
|
||||||
|
|
||||||
def update_subscription(rower,data,method='up'):
|
def update_subscription(rower,data,method='up'):
|
||||||
planid = data['plan']
|
planid = data['plan']
|
||||||
|
|||||||
@@ -83,11 +83,14 @@ def create_contact(rower):
|
|||||||
|
|
||||||
# this should be triggered by a Braintree webhook
|
# this should be triggered by a Braintree webhook
|
||||||
def create_invoice(rower,amount,braintreeid,dosend=True,
|
def create_invoice(rower,amount,braintreeid,dosend=True,
|
||||||
contact_id=None):
|
contact_id=None,name=None):
|
||||||
|
|
||||||
if not contact_id:
|
if not contact_id:
|
||||||
contact_id = get_contacts(rower)
|
contact_id = get_contacts(rower)
|
||||||
|
|
||||||
|
if not name:
|
||||||
|
name = 'Rowsandall Subscription'
|
||||||
|
|
||||||
|
|
||||||
with open('braintreewebhooks.log','a') as f:
|
with open('braintreewebhooks.log','a') as f:
|
||||||
f.write('Creating invoice for contact iD '+str(contact_id)+'\n')
|
f.write('Creating invoice for contact iD '+str(contact_id)+'\n')
|
||||||
@@ -104,7 +107,7 @@ def create_invoice(rower,amount,braintreeid,dosend=True,
|
|||||||
'paid_amount': str(amount),
|
'paid_amount': str(amount),
|
||||||
'status': 'paid',
|
'status': 'paid',
|
||||||
'lines': [{
|
'lines': [{
|
||||||
'name': 'Rowsandall Subscription',
|
'name': name,
|
||||||
'quantity': '1',
|
'quantity': '1',
|
||||||
'unit_price': str(amount),
|
'unit_price': str(amount),
|
||||||
'vat_rate': 0,
|
'vat_rate': 0,
|
||||||
|
|||||||
@@ -101,6 +101,19 @@ class BillingForm(forms.Form):
|
|||||||
paymenttype = forms.CharField(max_length=255,required=True)
|
paymenttype = forms.CharField(max_length=255,required=True)
|
||||||
tac= forms.BooleanField(required=True,initial=False)
|
tac= forms.BooleanField(required=True,initial=False)
|
||||||
|
|
||||||
|
# TrainingPlanBillingForm form
|
||||||
|
class TrainingPlanBillingForm(forms.Form):
|
||||||
|
amount = FlexibleDecimalField(required=True,decimal_places=2,
|
||||||
|
max_digits=8)
|
||||||
|
plan = forms.IntegerField(widget=forms.HiddenInput())
|
||||||
|
payment_method_nonce = forms.CharField(max_length=255,required=True)
|
||||||
|
paymenttype = forms.CharField(max_length=255,required=True)
|
||||||
|
enddate = forms.DateField(widget=forms.HiddenInput)
|
||||||
|
name = forms.CharField(max_length=255,required=False)
|
||||||
|
notes = forms.CharField(max_length=255,required=True)
|
||||||
|
status = forms.CharField(max_length=255,required=True)
|
||||||
|
tac= forms.BooleanField(required=True,initial=False)
|
||||||
|
|
||||||
|
|
||||||
# login form
|
# login form
|
||||||
class LoginForm(forms.Form):
|
class LoginForm(forms.Form):
|
||||||
|
|||||||
@@ -1612,7 +1612,7 @@ class TrainingPlan(models.Model):
|
|||||||
rowers = models.ManyToManyField(Rower,related_name='planathletes',
|
rowers = models.ManyToManyField(Rower,related_name='planathletes',
|
||||||
verbose_name='Athletes')
|
verbose_name='Athletes')
|
||||||
manager = models.ForeignKey(Rower,related_name='planmanager',null=True,on_delete=models.SET_NULL)
|
manager = models.ForeignKey(Rower,related_name='planmanager',null=True,on_delete=models.SET_NULL)
|
||||||
name = models.CharField(max_length=150,blank=True)
|
name = models.CharField(max_length=150,blank=True, verbose_name="Plan Name")
|
||||||
status = models.BooleanField(default=True,verbose_name='Active')
|
status = models.BooleanField(default=True,verbose_name='Active')
|
||||||
target = models.ForeignKey(TrainingTarget,blank=True,null=True,on_delete=models.SET_NULL)
|
target = models.ForeignKey(TrainingTarget,blank=True,null=True,on_delete=models.SET_NULL)
|
||||||
startdate = models.DateField(default=current_day)
|
startdate = models.DateField(default=current_day)
|
||||||
|
|||||||
43
rowers/templates/buy_trainingplan.html
Normal file
43
rowers/templates/buy_trainingplan.html
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{% extends "newbase.html" %}
|
||||||
|
{% block title %}Rowsandall Purchase Training Plan{% endblock title %}
|
||||||
|
{% load rowerfilters %}
|
||||||
|
{% block main %}
|
||||||
|
|
||||||
|
<h1>Purchase Training Plan</h1>
|
||||||
|
|
||||||
|
<form action="" method="post">
|
||||||
|
<ul class="main-content">
|
||||||
|
<li class="grid_3">
|
||||||
|
<h2>Billing Details</h2>
|
||||||
|
<p>For tax reasons, we need your country of residence. You should
|
||||||
|
update this when it is incorrect.</p>
|
||||||
|
<table>
|
||||||
|
{{ form.as_table }}
|
||||||
|
{{ billingaddressform.as_table }}
|
||||||
|
</table>
|
||||||
|
</li>
|
||||||
|
<li class="grid_3">
|
||||||
|
<h2>Your Purchase</h2>
|
||||||
|
|
||||||
|
<p>Plan: {{ plan.name }}</p>
|
||||||
|
<p>Price: {{ plan.price }}€</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Your purchase will be effective immediately. You will be charged
|
||||||
|
for the price of the plan.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li class="grid_3">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="submit" value="Proceed">
|
||||||
|
You will be able to review your order before finalizing your purchase.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block sidebar %}
|
||||||
|
{% include 'menu_payments.html' %}
|
||||||
|
{% endblock %}
|
||||||
114
rowers/templates/confirm_trainingplan.html
Normal file
114
rowers/templates/confirm_trainingplan.html
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
{% extends "newbase.html" %}
|
||||||
|
{% block title %}Rowsandall Purchase Training Plan{% endblock title %}
|
||||||
|
{% load rowerfilters %}
|
||||||
|
{% block main %}
|
||||||
|
|
||||||
|
<div id="paymenterror">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1>Confirm Your Payment</h1>
|
||||||
|
|
||||||
|
<h2>Order Overview</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Please refer to our <a href="/rowers/legal/">terms and conditions</a> for our
|
||||||
|
payments and refunds policy. Accepted payment methods are the payment methods offered
|
||||||
|
by
|
||||||
|
<a href="https://www.braintreegateway.com/merchants/jytq7yxsm66qqdzb/verified">Braintree</a>
|
||||||
|
through us. If you have any questions about our payments and refunds policy, please contact
|
||||||
|
us by email at support@rowsandall.com.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Payments will be processed by Braintree (A PayPal service):
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://www.braintreegateway.com/merchants/{{ BRAINTREE_MERCHANT_ID }}/verified" target="_blank">
|
||||||
|
<img src="https://s3.amazonaws.com/braintree-badges/braintree-badge-light.png" width="164px" height ="44px" border="0"/>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul class="main-content">
|
||||||
|
<li class="grid_2">
|
||||||
|
<p>
|
||||||
|
<table class="plantable shortpadded" width="80%">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Plan</th><td>{{ plan.name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Total</th><td>€ {{ plan.price|currency }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<table class="plantable shortpadded" width="80%">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Street Address</th><td>{{ user.rower.street_address }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>City</th><td>{{ user.rower.city }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Postal Code</th><td>{{ user.rower.postal_code }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Country</th><td>{{ user.rower.country }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li class="grid_4">
|
||||||
|
<form id="payment-form" method="post" action="/rowers/purchasecheckouts/"
|
||||||
|
autocomplete="off">
|
||||||
|
<section>
|
||||||
|
<label for="amount">
|
||||||
|
<div class="input-wrapper amount-wrapper">
|
||||||
|
<input id="amount" name="amount" type="hidden" min="1" placeholder="Amount"
|
||||||
|
value="{{ plan.price }}" readonly>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<div class="bt-drop-in-wrapper">
|
||||||
|
<div id="bt-dropin"></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<div id="paymenterror2"> </div>
|
||||||
|
<input type="hidden" id="nonce" name="payment_method_nonce" />
|
||||||
|
<input type="hidden" id="paymenttype" name="paymenttype" />
|
||||||
|
<input type="hidden" id="plan" name="plan" value="{{ plan.id }}">
|
||||||
|
<input type="hidden" id="status" name="status" value="{{ status }}">
|
||||||
|
<input type="hidden" id="notes" name="notes" value="{{ notes }}">
|
||||||
|
<input type="hidden" id="name" name="name" value="{{ name }}">
|
||||||
|
<input type="hidden" id="enddate" name="enddate" value="{{ enddate }}">
|
||||||
|
<p>
|
||||||
|
<input id="tac" type="checkbox" name="tac" value="tac">I have taken note of the
|
||||||
|
<a href="/rowers/legal/#refunds" target="_blank">Refund and Cancellation</a>
|
||||||
|
Policy and agree with the <a href="/rowers/legal/" target="_blank">Terms of Service</a>.
|
||||||
|
</p>
|
||||||
|
{% csrf_token %}
|
||||||
|
<button type="submit" id="submit-button"><span>Purchase for € {{ plan.price|currency }}</span></button>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
<li class="grid_4">
|
||||||
|
<p>
|
||||||
|
After you hit the Purchase button, the transaction will be launched.
|
||||||
|
Please wait until the transaction completes. Do not click the
|
||||||
|
button twice. Do not close your browser window.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{% include 'braintreedropin.html' %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block sidebar %}
|
||||||
|
{% include 'menu_payments.html' %}
|
||||||
|
{% endblock %}
|
||||||
@@ -27,6 +27,11 @@
|
|||||||
<p>What the plan will achieve: {{ plan.target }}</p>
|
<p>What the plan will achieve: {{ plan.target }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<p>Weekly volume: {{ plan.hoursperweek }} hours per week over {{ plan.sessionsperweek }} sessions.</p>
|
<p>Weekly volume: {{ plan.hoursperweek }} hours per week over {{ plan.sessionsperweek }} sessions.</p>
|
||||||
|
{% if plan.price == 0 %}
|
||||||
|
<p>Price: Free</p>
|
||||||
|
{% else %}
|
||||||
|
<p>Price: {{ plan.price }}€</p>
|
||||||
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<p>
|
<p>
|
||||||
@@ -37,12 +42,20 @@
|
|||||||
You can select the end date manually or use the training target (if you have any), and the plan will start at
|
You can select the end date manually or use the training target (if you have any), and the plan will start at
|
||||||
the date it needs to complete in time.
|
the date it needs to complete in time.
|
||||||
</p>
|
</p>
|
||||||
|
{% if plan.price == 0 %}
|
||||||
<form enctype="multipart/form-data" action="" method="post">
|
<form enctype="multipart/form-data" action="" method="post">
|
||||||
|
{% else %}
|
||||||
|
<form enctype="multipart/form-data" action="/rowers/buyplan/{{ plan.id }}/" method="post">
|
||||||
|
{% endif %}
|
||||||
<table>
|
<table>
|
||||||
{{ form.as_table }}
|
{{ form.as_table }}
|
||||||
</table>
|
</table>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
{% if plan.price == 0 %}
|
||||||
<p><input class="button" type="submit" value="Create Plan and Add Sessions"></p>
|
<p><input class="button" type="submit" value="Create Plan and Add Sessions"></p>
|
||||||
|
{% else %}
|
||||||
|
<p><input class="button" type="submit" action="/rowers/buyplan/{{ plan.id }}/" value="BUY NOW and Add Sessions"></p>
|
||||||
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
|
|||||||
@@ -22,6 +22,11 @@
|
|||||||
<p>Goal: {{ plan.goal }}</p>
|
<p>Goal: {{ plan.goal }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<p>{{ plan.hoursperweek }} hours per week over {{ plan.sessionsperweek }} sessions</p>
|
<p>{{ plan.hoursperweek }} hours per week over {{ plan.sessionsperweek }} sessions</p>
|
||||||
|
{% if plan.price == 0 %}
|
||||||
|
<p>Price: Free</p>
|
||||||
|
{% else %}
|
||||||
|
<p>Price: {{ plan.price }}€</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -719,7 +719,8 @@ urlpatterns = [
|
|||||||
re_path(r'^me/cancelsubscription/(?P<id>[\w\ ]+.*)/$',views.plan_tobasic_view,name='plan_tobasic_view'),
|
re_path(r'^me/cancelsubscription/(?P<id>[\w\ ]+.*)/$',views.plan_tobasic_view,name='plan_tobasic_view'),
|
||||||
re_path(r'^checkouts/$',views.checkouts_view,name='checkouts'),
|
re_path(r'^checkouts/$',views.checkouts_view,name='checkouts'),
|
||||||
re_path(r'^upgradecheckouts/$',views.upgrade_checkouts_view,name='upgrade_checkouts'),
|
re_path(r'^upgradecheckouts/$',views.upgrade_checkouts_view,name='upgrade_checkouts'),
|
||||||
re_path(r'^downgradecheckouts/$',views.downgrade_checkouts_view,name='downgrade_checkouts'),
|
re_path(r'^upgradecheckouts/$',views.upgrade_checkouts_view,name='upgrade_checkouts'),
|
||||||
|
re_path(r'^purchasecheckouts/$',views.purchase_checkouts_view,name='purchase_checkouts_view'),
|
||||||
re_path(r'^planrequired/',views.planrequired_view,name='planrequired_view'),
|
re_path(r'^planrequired/',views.planrequired_view,name='planrequired_view'),
|
||||||
re_path(r'^starttrial/$',views.start_trial_view,name='start_trial_view'),
|
re_path(r'^starttrial/$',views.start_trial_view,name='start_trial_view'),
|
||||||
re_path(r'^startplantrial/$',views.start_plantrial_view,name='start_plantrial_view'),
|
re_path(r'^startplantrial/$',views.start_plantrial_view,name='start_plantrial_view'),
|
||||||
@@ -744,6 +745,8 @@ urlpatterns = [
|
|||||||
re_path(r'^plans/$', views.rower_select_instantplan, name='rower_select_instantplan'),
|
re_path(r'^plans/$', views.rower_select_instantplan, name='rower_select_instantplan'),
|
||||||
re_path(r'^plans/(?P<id>[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12})/$',
|
re_path(r'^plans/(?P<id>[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12})/$',
|
||||||
views.rower_view_instantplan, name='rower_view_instantplan'),
|
views.rower_view_instantplan, name='rower_view_instantplan'),
|
||||||
|
re_path(r'^buyplan/(?P<id>\d+)/$',views.buy_trainingplan_view,name='buy_trainingplan_view'),
|
||||||
|
re_path(r'^confirmpurchaseplan/(?P<id>\d+)/$',views.confirm_trainingplan_purchase_view,name='confirm_trainingplan_purchase_view'),
|
||||||
re_path(r'^addinstantplan/$', views.add_instantplan_view, name='add_instantplan_view'),
|
re_path(r'^addinstantplan/$', views.add_instantplan_view, name='add_instantplan_view'),
|
||||||
re_path(r'^deleteplan/(?P<pk>\d+)/$',login_required(
|
re_path(r'^deleteplan/(?P<pk>\d+)/$',login_required(
|
||||||
views.TrainingPlanDelete.as_view()),name='trainingplan_delete_view'),
|
views.TrainingPlanDelete.as_view()),name='trainingplan_delete_view'),
|
||||||
|
|||||||
@@ -84,6 +84,212 @@ def billing_view(request):
|
|||||||
'planselectform':planselectform,
|
'planselectform':planselectform,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@login_required()
|
||||||
|
def buy_trainingplan_view(request,id=0):
|
||||||
|
if not PAYMENT_PROCESSING_ON:
|
||||||
|
url = reverse('promembership')
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
r = request.user.rower
|
||||||
|
|
||||||
|
plan = get_object_or_404(InstantPlan,pk=id)
|
||||||
|
|
||||||
|
if r.paymentprocessor != 'braintree':
|
||||||
|
messages.error(request,"This purchase is currently only available through BrainTree (by PayPal)")
|
||||||
|
|
||||||
|
if id == 0 or id is None:
|
||||||
|
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 = TrainingPlanForm(request.POST,user=request.user)
|
||||||
|
if billingaddressform.is_valid():
|
||||||
|
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']
|
||||||
|
rowers = cd['rowers']
|
||||||
|
notes = cd['notes']
|
||||||
|
status = cd['status']
|
||||||
|
|
||||||
|
# get target and set enddate
|
||||||
|
try:
|
||||||
|
target = cd['target']
|
||||||
|
except KeyError:
|
||||||
|
try:
|
||||||
|
targetid = request.POST['target']
|
||||||
|
|
||||||
|
if targetid != '':
|
||||||
|
target = TrainingTarget.objects.get(id=int(targetid))
|
||||||
|
else:
|
||||||
|
target = None
|
||||||
|
except KeyError:
|
||||||
|
target = None
|
||||||
|
|
||||||
|
if target:
|
||||||
|
enddate = target.date
|
||||||
|
|
||||||
|
pars = {
|
||||||
|
'name':cd['name'],
|
||||||
|
'enddate':enddate,
|
||||||
|
'notes':notes,
|
||||||
|
'status':status,
|
||||||
|
'rower':rowers[0].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 = TrainingPlanForm(user=request.user)
|
||||||
|
billingaddressform = RowerBillingAddressForm(instance=r)
|
||||||
|
|
||||||
|
return render(request,
|
||||||
|
'buy_trainingplan.html',
|
||||||
|
{
|
||||||
|
'rower':r,
|
||||||
|
'plan':plan,
|
||||||
|
'billingaddressform':billingaddressform,
|
||||||
|
'form':form,
|
||||||
|
})
|
||||||
|
|
||||||
|
@login_required()
|
||||||
|
def purchase_checkouts_view(request):
|
||||||
|
if not PAYMENT_PROCESSING_ON:
|
||||||
|
url = reverse('promembership')
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
r = request.user.rower
|
||||||
|
|
||||||
|
if request.method != 'POST':
|
||||||
|
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:
|
||||||
|
messages.error(request,"Could not connect to the training plan server")
|
||||||
|
return HttpResponseRedirect(reverse('rower_select_instantplan'))
|
||||||
|
|
||||||
|
amount, success = braintreestuff.make_payment(r,data)
|
||||||
|
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
|
||||||
|
url = reverse('plannedsessions_view')
|
||||||
|
timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d')
|
||||||
|
url = url+'?when='+timeperiod
|
||||||
|
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
else:
|
||||||
|
messages.error(request,"There was a problem with your payment")
|
||||||
|
url = reverse('rower_view_instantplan',kwargs={
|
||||||
|
'id':plan.uuid,
|
||||||
|
})
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
elif 'tac' not in request.POST:
|
||||||
|
try:
|
||||||
|
planid=int(request.POST['plan'])
|
||||||
|
enddate = request.POST['enddate']
|
||||||
|
rower = r.id
|
||||||
|
# incomplete
|
||||||
|
except IndexError:
|
||||||
|
messages.error(request,"There was an error in the payment form")
|
||||||
|
url = reverse("purchase_checkouts_view")
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
url = reverse('rower_view_instantplan',kwargs={
|
||||||
|
'id':plan.uuid,
|
||||||
|
})
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
@login_required()
|
||||||
|
def confirm_trainingplan_purchase_view(request,id = 0):
|
||||||
|
if not PAYMENT_PROCESSING_ON:
|
||||||
|
url = reverse('promembership')
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
r = request.user.rower
|
||||||
|
|
||||||
|
plan = get_object_or_404(InstantPlan,pk=id)
|
||||||
|
|
||||||
|
if r.paymentprocessor != 'braintree':
|
||||||
|
messages.error(request,"This purchase is currently only available through BrainTree (by PayPal)")
|
||||||
|
|
||||||
|
if id == 0 or id is None:
|
||||||
|
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:
|
||||||
|
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()
|
@login_required()
|
||||||
def upgrade_view(request):
|
def upgrade_view(request):
|
||||||
if not PAYMENT_PROCESSING_ON:
|
if not PAYMENT_PROCESSING_ON:
|
||||||
|
|||||||
@@ -2473,9 +2473,6 @@ class PlannedSessionDelete(DeleteView):
|
|||||||
|
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
@user_passes_test(can_plan,login_url="/rowers/paidplans",
|
|
||||||
message="This functionality requires a Coach or Self-Coach plan",
|
|
||||||
redirect_field_name=None)
|
|
||||||
def rower_view_instantplan(request,id='',userid=0):
|
def rower_view_instantplan(request,id='',userid=0):
|
||||||
r = getrequestrower(request,userid=userid)
|
r = getrequestrower(request,userid=userid)
|
||||||
if not id:
|
if not id:
|
||||||
@@ -2521,6 +2518,12 @@ def rower_view_instantplan(request,id='',userid=0):
|
|||||||
).order_by("-date")
|
).order_by("-date")
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
if not can_plan(request.user):
|
||||||
|
messages.error(request,'You must be on a <a href="/rowers/paidplans">paid plan</a> to use this functionality')
|
||||||
|
url = reverse('rower_view_instantplan',kwargs={
|
||||||
|
'id':id,
|
||||||
|
})
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
form = TrainingPlanForm(request.POST,user=request.user)
|
form = TrainingPlanForm(request.POST,user=request.user)
|
||||||
|
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ from rowers.forms import (
|
|||||||
VideoAnalysisCreateForm,WorkoutSingleSelectForm,
|
VideoAnalysisCreateForm,WorkoutSingleSelectForm,
|
||||||
VideoAnalysisMetricsForm,SurveyForm,HistorySelectForm,
|
VideoAnalysisMetricsForm,SurveyForm,HistorySelectForm,
|
||||||
StravaChartForm,FitnessFitForm,PerformanceManagerForm,
|
StravaChartForm,FitnessFitForm,PerformanceManagerForm,
|
||||||
|
TrainingPlanBillingForm,
|
||||||
)
|
)
|
||||||
|
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
|
|||||||
Reference in New Issue
Block a user