forked from GithubBackups/healthchecks
Billing page allows setting up a subscription before a payment method is added.
This commit is contained in:
parent
9617be6e1b
commit
95279f6f3f
@ -65,6 +65,9 @@ class Subscription(models.Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def payment_method(self):
|
def payment_method(self):
|
||||||
|
if not self.subscription_id:
|
||||||
|
return None
|
||||||
|
|
||||||
if not hasattr(self, "_pm"):
|
if not hasattr(self, "_pm"):
|
||||||
o = self._get_braintree_subscription()
|
o = self._get_braintree_subscription()
|
||||||
self._pm = braintree.PaymentMethod.find(o.payment_method_token)
|
self._pm = braintree.PaymentMethod.find(o.payment_method_token)
|
||||||
@ -152,6 +155,7 @@ class Subscription(models.Model):
|
|||||||
|
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
|
if not result.is_success:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def cancel(self):
|
def cancel(self):
|
||||||
|
@ -11,7 +11,7 @@ class UpdatePaymentMethodTestCase(BaseTestCase):
|
|||||||
mock.credit_card.CreditCard = list
|
mock.credit_card.CreditCard = list
|
||||||
mock.PaymentMethod.find.return_value = {"email": "foo@example.org"}
|
mock.PaymentMethod.find.return_value = {"email": "foo@example.org"}
|
||||||
|
|
||||||
Subscription.objects.create(user=self.alice)
|
Subscription.objects.create(user=self.alice, subscription_id="fake-id")
|
||||||
|
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.get("/accounts/profile/billing/payment_method/")
|
r = self.client.get("/accounts/profile/billing/payment_method/")
|
||||||
@ -23,7 +23,7 @@ class UpdatePaymentMethodTestCase(BaseTestCase):
|
|||||||
mock.credit_card.CreditCard = dict
|
mock.credit_card.CreditCard = dict
|
||||||
mock.PaymentMethod.find.return_value = {"masked_number": "1***2"}
|
mock.PaymentMethod.find.return_value = {"masked_number": "1***2"}
|
||||||
|
|
||||||
Subscription.objects.create(user=self.alice)
|
Subscription.objects.create(user=self.alice, subscription_id="fake-id")
|
||||||
|
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.get("/accounts/profile/billing/payment_method/")
|
r = self.client.get("/accounts/profile/billing/payment_method/")
|
||||||
|
@ -95,7 +95,11 @@ def update(request):
|
|||||||
sub = Subscription.objects.for_user(request.user)
|
sub = Subscription.objects.for_user(request.user)
|
||||||
# If plan_id has not changed then just update the payment method:
|
# If plan_id has not changed then just update the payment method:
|
||||||
if plan_id == sub.plan_id:
|
if plan_id == sub.plan_id:
|
||||||
|
if not sub.subscription_id:
|
||||||
|
error = sub.setup(plan_id, nonce)
|
||||||
|
else:
|
||||||
error = sub.update_payment_method(nonce)
|
error = sub.update_payment_method(nonce)
|
||||||
|
|
||||||
if error:
|
if error:
|
||||||
return log_and_bail(request, error)
|
return log_and_bail(request, error)
|
||||||
|
|
||||||
@ -119,9 +123,9 @@ def update(request):
|
|||||||
request.session["set_plan_status"] = "success"
|
request.session["set_plan_status"] = "success"
|
||||||
return redirect("hc-billing")
|
return redirect("hc-billing")
|
||||||
|
|
||||||
result = sub.setup(plan_id, nonce)
|
error = sub.setup(plan_id, nonce)
|
||||||
if not result.is_success:
|
if error:
|
||||||
return log_and_bail(request, result)
|
return log_and_bail(request, error)
|
||||||
|
|
||||||
# Update user's profile
|
# Update user's profile
|
||||||
profile = request.user.profile
|
profile = request.user.profile
|
||||||
|
@ -37,6 +37,19 @@
|
|||||||
border-color: #0091EA;
|
border-color: #0091EA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#payment-method-modal .modal-header {
|
||||||
|
border-bottom: 0;
|
||||||
|
padding: 30px 30px 0 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#payment-method-modal .modal-body {
|
||||||
|
padding: 15px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#payment-method-modal .modal-footer {
|
||||||
|
border-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.plan .marker {
|
.plan .marker {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -67,14 +67,6 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#payment-method-modal .modal-header {
|
|
||||||
border-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#payment-method-modal .modal-footer {
|
|
||||||
border-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-message {
|
.error-message {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
<td>Current Plan</td>
|
<td>Current Plan</td>
|
||||||
<td>{{ sub.plan_name|default:"Hobbyist" }}</td>
|
<td>{{ sub.plan_name|default:"Hobbyist" }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% if sub.plan_id %}
|
{% if sub.subscription_id %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>Next Payment</td>
|
<td>Next Payment</td>
|
||||||
<td id="next-billing-date">
|
<td id="next-billing-date">
|
||||||
@ -78,7 +78,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if sub.subscription_id %}
|
{% if sub.plan_id %}
|
||||||
<div class="panel panel-{{ payment_method_status }}">
|
<div class="panel panel-{{ payment_method_status }}">
|
||||||
<div class="panel-body settings-block">
|
<div class="panel-body settings-block">
|
||||||
<h2>Payment Method</h2>
|
<h2>Payment Method</h2>
|
||||||
@ -288,12 +288,9 @@
|
|||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||||
<h4>Some details are missing…</h4>
|
<h4>Country not specified.</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
{% if not sub.address_id %}
|
|
||||||
<div id="no-billing-address">
|
|
||||||
<h4>Country not specified.</h4>
|
|
||||||
<p>For tax accounting purposes, please specify
|
<p>For tax accounting purposes, please specify
|
||||||
your <strong>Country</strong> in the "Billing Details"
|
your <strong>Country</strong> in the "Billing Details"
|
||||||
section.
|
section.
|
||||||
@ -305,8 +302,6 @@
|
|||||||
to have them displayed on invoices.
|
to have them displayed on invoices.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">OK</button>
|
<button type="button" class="btn btn-default" data-dismiss="modal">OK</button>
|
||||||
</div>
|
</div>
|
||||||
@ -317,6 +312,7 @@
|
|||||||
|
|
||||||
<div id="payment-method-modal" class="modal pm-modal">
|
<div id="payment-method-modal" class="modal pm-modal">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
|
{% if sub.address_id %}
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||||
@ -334,6 +330,29 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||||
|
<h4>Country not specified.</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>For tax accounting purposes, please specify
|
||||||
|
your <strong>Country</strong> in the "Billing Details"
|
||||||
|
section.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Optionally, add your
|
||||||
|
<strong>company name</strong>, <strong>address</strong>
|
||||||
|
and <strong>VAT ID</strong>
|
||||||
|
to have them displayed on invoices.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">OK</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
{% if sub.pm_is_card %}
|
{% if not sub.subscription_id %}
|
||||||
|
<span class="billing-empty">No payment method added</span>
|
||||||
|
{% elif sub.pm_is_card %}
|
||||||
<img src="{{ pm.image_url }}" height="30" /> <span class="masked_number">{{ pm.masked_number }}</span>
|
<img src="{{ pm.image_url }}" height="30" /> <span class="masked_number">{{ pm.masked_number }}</span>
|
||||||
{% if pm.expired %}
|
{% if pm.expired %}
|
||||||
<span class="text-danger">(expired)</span>
|
<span class="text-danger">(expired)</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% elif sub.pm_is_paypal %}
|
||||||
|
|
||||||
{% if sub.pm_is_paypal %}
|
|
||||||
<img src="{{ pm.image_url }}" height="30" /> {{ pm.email }}
|
<img src="{{ pm.image_url }}" height="30" /> {{ pm.email }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user