Browse Source

Billing page allows setting up a subscription before a payment method is added.

pull/374/head
Pēteris Caune 5 years ago
parent
commit
95279f6f3f
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
7 changed files with 69 additions and 37 deletions
  1. +5
    -1
      hc/payments/models.py
  2. +2
    -2
      hc/payments/tests/test_payment_method.py
  3. +8
    -4
      hc/payments/views.py
  4. +13
    -0
      static/css/billing.css
  5. +0
    -8
      static/css/pricing.css
  6. +37
    -18
      templates/accounts/billing.html
  7. +4
    -4
      templates/payments/payment_method.html

+ 5
- 1
hc/payments/models.py View File

@ -65,6 +65,9 @@ class Subscription(models.Model):
@property
def payment_method(self):
if not self.subscription_id:
return None
if not hasattr(self, "_pm"):
o = self._get_braintree_subscription()
self._pm = braintree.PaymentMethod.find(o.payment_method_token)
@ -152,7 +155,8 @@ class Subscription(models.Model):
self.save()
return result
if not result.is_success:
return result
def cancel(self):
if self.subscription_id:


+ 2
- 2
hc/payments/tests/test_payment_method.py View File

@ -11,7 +11,7 @@ class UpdatePaymentMethodTestCase(BaseTestCase):
mock.credit_card.CreditCard = list
mock.PaymentMethod.find.return_value = {"email": "[email protected]"}
Subscription.objects.create(user=self.alice)
Subscription.objects.create(user=self.alice, subscription_id="fake-id")
self.client.login(username="[email protected]", password="password")
r = self.client.get("/accounts/profile/billing/payment_method/")
@ -23,7 +23,7 @@ class UpdatePaymentMethodTestCase(BaseTestCase):
mock.credit_card.CreditCard = dict
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="[email protected]", password="password")
r = self.client.get("/accounts/profile/billing/payment_method/")


+ 8
- 4
hc/payments/views.py View File

@ -95,7 +95,11 @@ def update(request):
sub = Subscription.objects.for_user(request.user)
# If plan_id has not changed then just update the payment method:
if plan_id == sub.plan_id:
error = sub.update_payment_method(nonce)
if not sub.subscription_id:
error = sub.setup(plan_id, nonce)
else:
error = sub.update_payment_method(nonce)
if error:
return log_and_bail(request, error)
@ -119,9 +123,9 @@ def update(request):
request.session["set_plan_status"] = "success"
return redirect("hc-billing")
result = sub.setup(plan_id, nonce)
if not result.is_success:
return log_and_bail(request, result)
error = sub.setup(plan_id, nonce)
if error:
return log_and_bail(request, error)
# Update user's profile
profile = request.user.profile


+ 13
- 0
static/css/billing.css View File

@ -37,6 +37,19 @@
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 {
display: none;
}


+ 0
- 8
static/css/pricing.css View File

@ -67,14 +67,6 @@
}
#payment-method-modal .modal-header {
border-bottom: 0;
}
#payment-method-modal .modal-footer {
border-top: 0;
}
.error-message {
font-family: monospace;
}


+ 37
- 18
templates/accounts/billing.html View File

@ -46,7 +46,7 @@
<td>Current Plan</td>
<td>{{ sub.plan_name|default:"Hobbyist" }}</td>
</tr>
{% if sub.plan_id %}
{% if sub.subscription_id %}
<tr>
<td>Next Payment</td>
<td id="next-billing-date">
@ -78,7 +78,7 @@
{% endif %}
</div>
{% if sub.subscription_id %}
{% if sub.plan_id %}
<div class="panel panel-{{ payment_method_status }}">
<div class="panel-body settings-block">
<h2>Payment Method</h2>
@ -288,24 +288,19 @@
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4>Some details are missing…</h4>
<h4>Country not specified.</h4>
</div>
<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
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>
{% endif %}
<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>
@ -317,6 +312,7 @@
<div id="payment-method-modal" class="modal pm-modal">
<div class="modal-dialog">
{% if sub.address_id %}
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
@ -334,6 +330,29 @@
</button>
</div>
</div>
{% else %}
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</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>


+ 4
- 4
templates/payments/payment_method.html View File

@ -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>
{% if pm.expired %}
<span class="text-danger">(expired)</span>
{% endif %}
{% endif %}
{% if sub.pm_is_paypal %}
{% elif sub.pm_is_paypal %}
<img src="{{ pm.image_url }}" height="30" /> {{ pm.email }}
{% endif %}


Loading…
Cancel
Save