Browse Source

Remove PDF invoice generation bits - these are unlikely to ever be useful in the open source version.

pull/291/head
Pēteris Caune 5 years ago
parent
commit
accdfb637b
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
9 changed files with 2 additions and 311 deletions
  1. +0
    -98
      hc/payments/invoices.py
  2. +0
    -7
      hc/payments/models.py
  3. +1
    -1
      hc/payments/tests/test_billing_history.py
  4. +0
    -74
      hc/payments/tests/test_charge_webhook.py
  5. +0
    -65
      hc/payments/tests/test_pdf_invoice.py
  6. +0
    -4
      hc/payments/urls.py
  7. +1
    -47
      hc/payments/views.py
  8. +0
    -8
      templates/payments/address_plain.html
  9. +0
    -7
      templates/payments/billing_history.html

+ 0
- 98
hc/payments/invoices.py View File

@ -1,98 +0,0 @@
# coding: utf-8
try:
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import inch
from reportlab.pdfgen.canvas import Canvas
W, H = A4
except ImportError:
# Don't crash if reportlab is not installed.
Canvas = object
def f(dt):
return dt.strftime("%b. %-d, %Y")
class PdfInvoice(Canvas):
def __init__(self, fileobj):
Canvas.__init__(self, fileobj, pagesize=A4, pageCompression=0)
self.head_y = H - inch * 0.5
def linefeed(self):
self.head_y -= inch / 8
def text(self, s, align="left", size=10, bold=False):
self.head_y -= inch / 24
self.linefeed()
self.setFont("Helvetica-Bold" if bold else "Helvetica", size)
if align == "left":
self.drawString(inch * 0.5, self.head_y, s)
elif align == "right":
self.drawRightString(W - inch * 0.5, self.head_y, s)
elif align == "center":
self.drawCentredString(W / 2, self.head_y, s)
self.head_y -= inch / 24
def hr(self):
self.setLineWidth(inch / 72 / 8)
self.line(inch * 0.5, self.head_y, W - inch * 0.5, self.head_y)
def row(self, items, align="left", bold=False, size=10):
self.head_y -= inch / 8
self.linefeed()
self.setFont("Helvetica-Bold" if bold else "Helvetica", size)
self.drawString(inch * 0.5, self.head_y, items[0])
self.drawString(inch * 3.5, self.head_y, items[1])
self.drawString(inch * 5.5, self.head_y, items[2])
self.drawRightString(W - inch * 0.5, self.head_y, items[3])
self.head_y -= inch / 8
def render(self, tx, bill_to):
invoice_id = "MS-HC-%s" % tx.id.upper()
self.setTitle(invoice_id)
self.text("SIA Monkey See Monkey Do", size=16)
self.linefeed()
self.text("Gaujas iela 4-2")
self.text("Valmiera, LV-4201, Latvia")
self.text("VAT: LV44103100701")
self.linefeed()
created = f(tx.created_at)
self.text("Date Issued: %s" % created, align="right")
self.text("Invoice Id: %s" % invoice_id, align="right")
self.linefeed()
self.hr()
self.row(["Description", "Start", "End", tx.currency_iso_code], bold=True)
self.hr()
start = f(tx.subscription_details.billing_period_start_date)
end = f(tx.subscription_details.billing_period_end_date)
if tx.currency_iso_code == "USD":
amount = "$%s" % tx.amount
elif tx.currency_iso_code == "EUR":
amount = "%s" % tx.amount
else:
amount = "%s %s" % (tx.currency_iso_code, tx.amount)
self.row(["healthchecks.io paid plan", start, end, amount])
self.hr()
self.row(["", "", "", "Total: %s" % amount], bold=True)
self.linefeed()
self.text("Bill to:", bold=True)
for s in bill_to.split("\n"):
self.text(s.strip())
self.linefeed()
self.showPage()
self.save()

+ 0
- 7
hc/payments/models.py View File

@ -173,13 +173,6 @@ class Subscription(models.Model):
return self._address return self._address
def flattened_address(self):
if self.address_id:
ctx = {"a": self.address, "email": self.user.email}
return render_to_string("payments/address_plain.html", ctx)
else:
return self.user.email
@property @property
def transactions(self): def transactions(self):
if not hasattr(self, "_tx"): if not hasattr(self, "_tx"):


+ 1
- 1
hc/payments/tests/test_billing_history.py View File

@ -23,4 +23,4 @@ class BillingHistoryTestCase(BaseTestCase):
self.client.login(username="[email protected]", password="password") self.client.login(username="[email protected]", password="password")
r = self.client.get("/accounts/profile/billing/history/") r = self.client.get("/accounts/profile/billing/history/")
self.assertContains(r, "123") self.assertContains(r, "123")
self.assertContains(r, "def456")
self.assertContains(r, "456")

+ 0
- 74
hc/payments/tests/test_charge_webhook.py View File

@ -1,74 +0,0 @@
from mock import Mock, patch
from unittest import skipIf
from django.core import mail
from django.utils.timezone import now
from hc.payments.models import Subscription
from hc.test import BaseTestCase
try:
import reportlab
except ImportError:
reportlab = None
class ChargeWebhookTestCase(BaseTestCase):
def setUp(self):
super(ChargeWebhookTestCase, self).setUp()
self.sub = Subscription(user=self.alice)
self.sub.subscription_id = "test-id"
self.sub.customer_id = "test-customer-id"
self.sub.send_invoices = True
self.sub.save()
self.tx = Mock()
self.tx.id = "abc123"
self.tx.customer_details.id = "test-customer-id"
self.tx.created_at = now()
self.tx.currency_iso_code = "USD"
self.tx.amount = 5
self.tx.subscription_details.billing_period_start_date = now()
self.tx.subscription_details.billing_period_end_date = now()
@skipIf(reportlab is None, "reportlab not installed")
@patch("hc.payments.views.Subscription.objects.by_braintree_webhook")
def test_it_works(self, mock_getter):
mock_getter.return_value = self.sub, self.tx
r = self.client.post("/pricing/charge/")
self.assertEqual(r.status_code, 200)
# See if email was sent
self.assertEqual(len(mail.outbox), 1)
msg = mail.outbox[0]
self.assertEqual(msg.subject, "Invoice from Mychecks")
self.assertEqual(msg.to, ["[email protected]"])
self.assertEqual(msg.attachments[0][0], "MS-HC-ABC123.pdf")
@patch("hc.payments.views.Subscription.objects.by_braintree_webhook")
def test_it_obeys_send_invoices_flag(self, mock_getter):
mock_getter.return_value = self.sub, self.tx
self.sub.send_invoices = False
self.sub.save()
r = self.client.post("/pricing/charge/")
self.assertEqual(r.status_code, 200)
# It should not send the email
self.assertEqual(len(mail.outbox), 0)
@skipIf(reportlab is None, "reportlab not installed")
@patch("hc.payments.views.Subscription.objects.by_braintree_webhook")
def test_it_uses_invoice_email(self, mock_getter):
mock_getter.return_value = self.sub, self.tx
self.sub.invoice_email = "[email protected]"
self.sub.save()
r = self.client.post("/pricing/charge/")
self.assertEqual(r.status_code, 200)
# See if the email was sent to Alice's accountant:
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].to, ["[email protected]"])

+ 0
- 65
hc/payments/tests/test_pdf_invoice.py View File

@ -1,65 +0,0 @@
from mock import Mock, patch
from unittest import skipIf
from django.utils.timezone import now
from hc.payments.models import Subscription
from hc.test import BaseTestCase
try:
import reportlab
except ImportError:
reportlab = None
class PdfInvoiceTestCase(BaseTestCase):
def setUp(self):
super(PdfInvoiceTestCase, self).setUp()
self.sub = Subscription(user=self.alice)
self.sub.subscription_id = "test-id"
self.sub.customer_id = "test-customer-id"
self.sub.save()
self.tx = Mock()
self.tx.id = "abc123"
self.tx.customer_details.id = "test-customer-id"
self.tx.created_at = now()
self.tx.currency_iso_code = "USD"
self.tx.amount = 5
self.tx.subscription_details.billing_period_start_date = now()
self.tx.subscription_details.billing_period_end_date = now()
@skipIf(reportlab is None, "reportlab not installed")
@patch("hc.payments.models.braintree")
def test_it_works(self, mock_braintree):
mock_braintree.Transaction.find.return_value = self.tx
self.client.login(username="[email protected]", password="password")
r = self.client.get("/invoice/pdf/abc123/")
self.assertTrue(b"ABC123" in r.content)
self.assertTrue(b"[email protected]" in r.content)
@patch("hc.payments.models.braintree")
def test_it_checks_customer_id(self, mock_braintree):
tx = Mock()
tx.id = "abc123"
tx.customer_details.id = "test-another-customer-id"
tx.created_at = None
mock_braintree.Transaction.find.return_value = tx
self.client.login(username="[email protected]", password="password")
r = self.client.get("/invoice/pdf/abc123/")
self.assertEqual(r.status_code, 403)
@skipIf(reportlab is None, "reportlab not installed")
@patch("hc.payments.models.braintree")
def test_it_shows_company_data(self, mock):
self.sub.address_id = "aa"
self.sub.save()
mock.Transaction.find.return_value = self.tx
mock.Address.find.return_value = {"company": "Alice and Partners"}
self.client.login(username="[email protected]", password="password")
r = self.client.get("/invoice/pdf/abc123/")
self.assertTrue(b"Alice and Partners" in r.content)

+ 0
- 4
hc/payments/urls.py View File

@ -16,10 +16,6 @@ urlpatterns = [
views.payment_method, views.payment_method,
name="hc-payment-method", name="hc-payment-method",
), ),
path(
"invoice/pdf/<slug:transaction_id>/", views.pdf_invoice, name="hc-invoice-pdf"
),
path("pricing/update/", views.update, name="hc-update-subscription"), path("pricing/update/", views.update, name="hc-update-subscription"),
path("pricing/token/", views.token, name="hc-get-client-token"), path("pricing/token/", views.token, name="hc-get-client-token"),
path("pricing/charge/", views.charge_webhook),
] ]

+ 1
- 47
hc/payments/views.py View File

@ -1,21 +1,11 @@
from io import BytesIO
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.http import (
HttpResponseBadRequest,
HttpResponseForbidden,
JsonResponse,
HttpResponse,
)
from django.http import HttpResponseBadRequest, JsonResponse
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST from django.views.decorators.http import require_POST
from hc.api.models import Check from hc.api.models import Check
from hc.lib import emails
from hc.payments.forms import InvoiceEmailingForm from hc.payments.forms import InvoiceEmailingForm
from hc.payments.invoices import PdfInvoice
from hc.payments.models import Subscription from hc.payments.models import Subscription
@ -184,39 +174,3 @@ def billing_history(request):
ctx = {"transactions": transactions} ctx = {"transactions": transactions}
return render(request, "payments/billing_history.html", ctx) return render(request, "payments/billing_history.html", ctx)
@login_required
def pdf_invoice(request, transaction_id):
sub, tx = Subscription.objects.by_transaction(transaction_id)
# Does this transaction belong to a customer we know about?
if sub is None or tx is None:
return HttpResponseForbidden()
# Does the transaction's customer match the currently logged in user?
if sub.user != request.user and not request.user.is_superuser:
return HttpResponseForbidden()
response = HttpResponse(content_type="application/pdf")
filename = "MS-HC-%s.pdf" % tx.id.upper()
response["Content-Disposition"] = 'attachment; filename="%s"' % filename
PdfInvoice(response).render(tx, sub.flattened_address())
return response
@csrf_exempt
@require_POST
def charge_webhook(request):
sub, tx = Subscription.objects.by_braintree_webhook(request)
if sub.send_invoices:
filename = "MS-HC-%s.pdf" % tx.id.upper()
sink = BytesIO()
PdfInvoice(sink).render(tx, sub.flattened_address())
ctx = {"tx": tx}
recipient = sub.invoice_email or sub.user.email
emails.invoice(recipient, ctx, filename, sink.getvalue())
return HttpResponse()

+ 0
- 8
templates/payments/address_plain.html View File

@ -1,8 +0,0 @@
{% if a.company %}{{ a.company }}
{% else %}{{ email }}
{% endif %}{% if a.extended_address %}VAT: {{ a.extended_address }}
{% endif %}{% if a.street_address %}{{ a.street_address }}
{% endif %}{% if a.locality %}{{ a.locality }}
{% endif %}{% if a.region %}{{ a.region }}
{% endif %}{% if a.country_name %}{{ a.country_name }}
{% endif %}{% if a.postal_code %}{{ a.postal_code }}{% endif %}

+ 0
- 7
templates/payments/billing_history.html View File

@ -6,7 +6,6 @@
<th>Amount</th> <th>Amount</th>
<th>Type</th> <th>Type</th>
<th>Status</th> <th>Status</th>
<th></th>
</tr> </tr>
{% for tx in transactions %} {% for tx in transactions %}
<tr {% if tx.type == "credit" %}class="text-muted"{% endif %}> <tr {% if tx.type == "credit" %}class="text-muted"{% endif %}>
@ -29,12 +28,6 @@
</td> </td>
<td>{{ tx.type|capfirst }}</td> <td>{{ tx.type|capfirst }}</td>
<td><code>{{ tx.status }}</code></td> <td><code>{{ tx.status }}</code></td>
<td>
{% if tx.type == "credit" %}
{% else %}
<a href="{% url 'hc-invoice-pdf' tx.id %}">PDF Invoice</a>
{% endif %}
</td>
</tr> </tr>
{% endfor%} {% endfor%}
</table> </table>


Loading…
Cancel
Save