You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

235 lines
6.7 KiB

7 years ago
9 years ago
7 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
  1. from django.conf import settings
  2. from django.contrib import messages
  3. from django.contrib.auth.decorators import login_required
  4. from django.http import (HttpResponseBadRequest, HttpResponseForbidden,
  5. JsonResponse, HttpResponse)
  6. from django.shortcuts import redirect, render
  7. from django.views.decorators.http import require_POST
  8. from hc.payments.forms import BillToForm
  9. from hc.payments.invoices import PdfInvoice
  10. from hc.payments.models import Subscription
  11. if settings.USE_PAYMENTS:
  12. import braintree
  13. else:
  14. # hc.payments tests mock this object, so tests should
  15. # still be able to run:
  16. braintree = None
  17. @login_required
  18. def get_client_token(request):
  19. sub = Subscription.objects.for_user(request.user)
  20. client_token = braintree.ClientToken.generate({
  21. "customer_id": sub.customer_id
  22. })
  23. return JsonResponse({"client_token": client_token})
  24. def pricing(request):
  25. if request.user.is_authenticated and request.profile != request.team:
  26. ctx = {"page": "pricing"}
  27. return render(request, "payments/pricing_not_owner.html", ctx)
  28. sub = None
  29. if request.user.is_authenticated:
  30. # Don't use Subscription.objects.for_user method here, so a
  31. # subscription object is not created just by viewing a page.
  32. sub = Subscription.objects.filter(user_id=request.user.id).first()
  33. period = "monthly"
  34. if sub and sub.plan_id.startswith("Y"):
  35. period = "annual"
  36. ctx = {
  37. "page": "pricing",
  38. "sub": sub,
  39. "period": period,
  40. "first_charge": request.session.pop("first_charge", False)
  41. }
  42. return render(request, "payments/pricing.html", ctx)
  43. def log_and_bail(request, result):
  44. logged_deep_error = False
  45. for error in result.errors.deep_errors:
  46. messages.error(request, error.message)
  47. logged_deep_error = True
  48. if not logged_deep_error:
  49. messages.error(request, result.message)
  50. return redirect("hc-pricing")
  51. @login_required
  52. @require_POST
  53. def create_plan(request):
  54. plan_id = request.POST["plan_id"]
  55. if plan_id not in ("P5", "P50", "Y48", "Y480"):
  56. return HttpResponseBadRequest()
  57. sub = Subscription.objects.for_user(request.user)
  58. # Cancel the previous plan
  59. if sub.subscription_id:
  60. braintree.Subscription.cancel(sub.subscription_id)
  61. sub.subscription_id = ""
  62. sub.plan_id = ""
  63. sub.save()
  64. # Create Braintree customer record
  65. if not sub.customer_id:
  66. result = braintree.Customer.create({
  67. "email": request.user.email
  68. })
  69. if not result.is_success:
  70. return log_and_bail(request, result)
  71. sub.customer_id = result.customer.id
  72. sub.save()
  73. # Create Braintree payment method
  74. if "payment_method_nonce" in request.POST:
  75. result = braintree.PaymentMethod.create({
  76. "customer_id": sub.customer_id,
  77. "payment_method_nonce": request.POST["payment_method_nonce"]
  78. })
  79. if not result.is_success:
  80. return log_and_bail(request, result)
  81. sub.payment_method_token = result.payment_method.token
  82. sub.save()
  83. # Create Braintree subscription
  84. result = braintree.Subscription.create({
  85. "payment_method_token": sub.payment_method_token,
  86. "plan_id": plan_id,
  87. })
  88. if not result.is_success:
  89. return log_and_bail(request, result)
  90. sub.subscription_id = result.subscription.id
  91. sub.plan_id = plan_id
  92. sub.save()
  93. # Update user's profile
  94. profile = request.user.profile
  95. if plan_id in ("P5", "Y48"):
  96. profile.ping_log_limit = 1000
  97. profile.check_limit = 500
  98. profile.team_limit = 9
  99. profile.sms_limit = 50
  100. profile.sms_sent = 0
  101. profile.save()
  102. elif plan_id in ("P50", "Y480"):
  103. profile.ping_log_limit = 1000
  104. profile.check_limit = 500
  105. profile.team_limit = 500
  106. profile.sms_limit = 500
  107. profile.sms_sent = 0
  108. profile.save()
  109. request.session["first_charge"] = True
  110. return redirect("hc-pricing")
  111. @login_required
  112. @require_POST
  113. def update_payment_method(request):
  114. sub = Subscription.objects.for_user(request.user)
  115. if not sub.customer_id or not sub.subscription_id:
  116. return HttpResponseBadRequest()
  117. if "payment_method_nonce" not in request.POST:
  118. return HttpResponseBadRequest()
  119. result = braintree.PaymentMethod.create({
  120. "customer_id": sub.customer_id,
  121. "payment_method_nonce": request.POST["payment_method_nonce"]
  122. })
  123. if not result.is_success:
  124. return log_and_bail(request, result)
  125. payment_method_token = result.payment_method.token
  126. result = braintree.Subscription.update(sub.subscription_id, {
  127. "payment_method_token": payment_method_token
  128. })
  129. if not result.is_success:
  130. return log_and_bail(request, result)
  131. sub.payment_method_token = payment_method_token
  132. sub.save()
  133. return redirect("hc-pricing")
  134. @login_required
  135. @require_POST
  136. def cancel_plan(request):
  137. sub = Subscription.objects.get(user=request.user)
  138. sub.cancel()
  139. # Revert to default limits--
  140. profile = request.user.profile
  141. profile.ping_log_limit = 100
  142. profile.check_limit = 20
  143. profile.team_limit = 2
  144. profile.sms_limit = 0
  145. profile.save()
  146. return redirect("hc-pricing")
  147. @login_required
  148. def billing(request):
  149. if request.method == "POST":
  150. form = BillToForm(request.POST)
  151. if form.is_valid():
  152. request.user.profile.bill_to = form.cleaned_data["bill_to"]
  153. request.user.profile.save()
  154. return redirect("hc-billing")
  155. sub = Subscription.objects.get(user=request.user)
  156. transactions = braintree.Transaction.search(
  157. braintree.TransactionSearch.customer_id == sub.customer_id)
  158. ctx = {"transactions": transactions}
  159. return render(request, "payments/billing.html", ctx)
  160. @login_required
  161. def invoice(request, transaction_id):
  162. sub = Subscription.objects.get(user=request.user)
  163. transaction = braintree.Transaction.find(transaction_id)
  164. if transaction.customer_details.id != sub.customer_id:
  165. return HttpResponseForbidden()
  166. ctx = {"tx": transaction}
  167. return render(request, "payments/invoice.html", ctx)
  168. @login_required
  169. def pdf_invoice(request, transaction_id):
  170. sub = Subscription.objects.get(user=request.user)
  171. transaction = braintree.Transaction.find(transaction_id)
  172. if transaction.customer_details.id != sub.customer_id:
  173. return HttpResponseForbidden()
  174. response = HttpResponse(content_type='application/pdf')
  175. filename = "MS-HC-%s.pdf" % transaction.id.upper()
  176. response['Content-Disposition'] = 'attachment; filename="%s"' % filename
  177. bill_to = request.user.profile.bill_to or request.user.email
  178. PdfInvoice(response).render(transaction, bill_to)
  179. return response