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.

229 lines
7.2 KiB

7 years ago
9 years ago
7 years ago
9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. from django.contrib import messages
  2. from django.contrib.auth.decorators import login_required
  3. from django.http import (HttpResponseBadRequest, HttpResponseForbidden,
  4. JsonResponse, HttpResponse)
  5. from django.shortcuts import get_object_or_404, redirect, render
  6. from django.views.decorators.csrf import csrf_exempt
  7. from django.views.decorators.http import require_POST
  8. import six
  9. from hc.api.models import Check
  10. from hc.lib import emails
  11. from hc.payments.invoices import PdfInvoice
  12. from hc.payments.models import Subscription
  13. @login_required
  14. def get_client_token(request):
  15. sub = Subscription.objects.for_user(request.user)
  16. return JsonResponse({"client_token": sub.get_client_token()})
  17. def pricing(request):
  18. if request.user.is_authenticated and request.profile != request.team:
  19. ctx = {"page": "pricing"}
  20. return render(request, "payments/pricing_not_owner.html", ctx)
  21. # Don't use Subscription.objects.for_user method here, so a
  22. # subscription object is not created just by viewing a page.
  23. sub = Subscription.objects.filter(user_id=request.user.id).first()
  24. ctx = {"page": "pricing", "sub": sub}
  25. return render(request, "payments/pricing.html", ctx)
  26. @login_required
  27. def billing(request):
  28. if request.team != request.profile:
  29. request.team = request.profile
  30. request.profile.current_team = request.profile
  31. request.profile.save()
  32. # Don't use Subscription.objects.for_user method here, so a
  33. # subscription object is not created just by viewing a page.
  34. sub = Subscription.objects.filter(user_id=request.user.id).first()
  35. send_invoices_status = "default"
  36. if request.method == "POST":
  37. if "save_send_invoices" in request.POST:
  38. sub = Subscription.objects.for_user(request.user)
  39. sub.send_invoices = "send_invoices" in request.POST
  40. sub.save()
  41. send_invoices_status = "success"
  42. ctx = {
  43. "page": "billing",
  44. "profile": request.profile,
  45. "sub": sub,
  46. "num_checks": Check.objects.filter(user=request.user).count(),
  47. "team_size": request.profile.member_set.count() + 1,
  48. "team_max": request.profile.team_limit + 1,
  49. "send_invoices_status": send_invoices_status,
  50. "set_plan_status": "default",
  51. "address_status": "default",
  52. "payment_method_status": "default"
  53. }
  54. if "set_plan_status" in request.session:
  55. ctx["set_plan_status"] = request.session.pop("set_plan_status")
  56. if "address_status" in request.session:
  57. ctx["address_status"] = request.session.pop("address_status")
  58. if "payment_method_status" in request.session:
  59. ctx["payment_method_status"] = \
  60. request.session.pop("payment_method_status")
  61. return render(request, "accounts/billing.html", ctx)
  62. def log_and_bail(request, result):
  63. logged_deep_error = False
  64. for error in result.errors.deep_errors:
  65. messages.error(request, error.message)
  66. logged_deep_error = True
  67. if not logged_deep_error:
  68. messages.error(request, result.message)
  69. return redirect("hc-billing")
  70. @login_required
  71. @require_POST
  72. def set_plan(request):
  73. plan_id = request.POST["plan_id"]
  74. if plan_id not in ("", "P5", "P50", "Y48", "Y480", "T144"):
  75. return HttpResponseBadRequest()
  76. sub = Subscription.objects.for_user(request.user)
  77. if sub.plan_id == plan_id:
  78. return redirect("hc-billing")
  79. # Cancel the previous plan
  80. sub.cancel()
  81. if plan_id == "":
  82. profile = request.user.profile
  83. profile.ping_log_limit = 100
  84. profile.check_limit = 20
  85. profile.team_limit = 2
  86. profile.sms_limit = 0
  87. profile.save()
  88. return redirect("hc-billing")
  89. result = sub.setup(plan_id)
  90. if not result.is_success:
  91. return log_and_bail(request, result)
  92. # Update user's profile
  93. profile = request.user.profile
  94. if plan_id in ("P5", "Y48", "T144"):
  95. profile.ping_log_limit = 1000
  96. profile.check_limit = 500
  97. profile.team_limit = 9
  98. profile.sms_limit = 50
  99. profile.sms_sent = 0
  100. profile.save()
  101. elif plan_id in ("P50", "Y480"):
  102. profile.ping_log_limit = 1000
  103. profile.check_limit = 500
  104. profile.team_limit = 500
  105. profile.sms_limit = 500
  106. profile.sms_sent = 0
  107. profile.save()
  108. request.session["set_plan_status"] = "success"
  109. return redirect("hc-billing")
  110. @login_required
  111. def address(request):
  112. sub = Subscription.objects.for_user(request.user)
  113. if request.method == "POST":
  114. error = sub.update_address(request.POST)
  115. if error:
  116. return log_and_bail(request, error)
  117. request.session["address_status"] = "success"
  118. return redirect("hc-billing")
  119. ctx = {"a": sub.address}
  120. return render(request, "payments/address.html", ctx)
  121. @login_required
  122. def payment_method(request):
  123. sub = get_object_or_404(Subscription, user=request.user)
  124. if request.method == "POST":
  125. if "payment_method_nonce" not in request.POST:
  126. return HttpResponseBadRequest()
  127. nonce = request.POST["payment_method_nonce"]
  128. error = sub.update_payment_method(nonce)
  129. if error:
  130. return log_and_bail(request, error)
  131. request.session["payment_method_status"] = "success"
  132. return redirect("hc-billing")
  133. ctx = {
  134. "sub": sub,
  135. "pm": sub.payment_method
  136. }
  137. return render(request, "payments/payment_method.html", ctx)
  138. @login_required
  139. def billing_history(request):
  140. try:
  141. sub = Subscription.objects.get(user=request.user)
  142. transactions = sub.transactions
  143. except Subscription.DoesNotExist:
  144. transactions = []
  145. ctx = {"transactions": transactions}
  146. return render(request, "payments/billing_history.html", ctx)
  147. @login_required
  148. def pdf_invoice(request, transaction_id):
  149. sub, tx = Subscription.objects.by_transaction(transaction_id)
  150. # Does this transaction belong to a customer we know about?
  151. if sub is None or tx is None:
  152. return HttpResponseForbidden()
  153. # Does the transaction's customer match the currently logged in user?
  154. if sub.user != request.user and not request.user.is_superuser:
  155. return HttpResponseForbidden()
  156. response = HttpResponse(content_type='application/pdf')
  157. filename = "MS-HC-%s.pdf" % tx.id.upper()
  158. response['Content-Disposition'] = 'attachment; filename="%s"' % filename
  159. PdfInvoice(response).render(tx, sub.flattened_address())
  160. return response
  161. @csrf_exempt
  162. @require_POST
  163. def charge_webhook(request):
  164. sig = str(request.POST["bt_signature"])
  165. payload = str(request.POST["bt_payload"])
  166. import braintree
  167. doc = braintree.WebhookNotification.parse(sig, payload)
  168. if doc.kind != "subscription_charged_successfully":
  169. return HttpResponseBadRequest()
  170. sub = Subscription.objects.get(subscription_id=doc.subscription.id)
  171. if sub.send_invoices:
  172. transaction = doc.subscription.transactions[0]
  173. filename = "MS-HC-%s.pdf" % transaction.id.upper()
  174. sink = six.BytesIO()
  175. PdfInvoice(sink).render(transaction, sub.flattened_address())
  176. ctx = {"tx": transaction}
  177. emails.invoice(sub.user.email, ctx, filename, sink.getvalue())
  178. return HttpResponse()