@ -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() |
@ -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") |
@ -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]"]) |
@ -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) |
@ -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 %} |