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
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
def transactions(self):
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")
r = self.client.get("/accounts/profile/billing/history/")
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,
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/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.contrib import messages
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.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from hc.api.models import Check
from hc.lib import emails
from hc.payments.forms import InvoiceEmailingForm
from hc.payments.invoices import PdfInvoice
from hc.payments.models import Subscription
@ -184,39 +174,3 @@ def billing_history(request):
ctx = {"transactions": transactions}
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>Type</th>
<th>Status</th>
<th></th>
</tr>
{% for tx in transactions %}
<tr {% if tx.type == "credit" %}class="text-muted"{% endif %}>
@ -29,12 +28,6 @@
</td>
<td>{{ tx.type|capfirst }}</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>
{% endfor%}
</table>


Loading…
Cancel
Save