importers.nbpy2017: Yield entries for the original invoice.

This lets us write up a cleaner separation between the original act of
invoicing and the Stripe payment.
This commit is contained in:
Brett Smith 2017-12-18 10:47:04 -05:00
parent fb0e4f2235
commit 668906b944
2 changed files with 72 additions and 9 deletions

View file

@ -4,6 +4,10 @@ import functools
import bs4
from .. import util
STATUS_INVOICED = 'Invoice'
STATUS_PAID = 'Payment'
STATUS_REFUNDED = 'Refund'
class Invoice2017:
STANDARD_TICKET_RATE = decimal.Decimal('42.50')
DISCOUNT_TICKET_RATE = STANDARD_TICKET_RATE / 2
@ -46,6 +50,7 @@ class Invoice2017:
self.base_data = {
'amount': self.amount,
'currency': self.CURRENCY,
'invoice_date': self.invoice_date,
'invoice_id': self.invoice_id,
'payee': self.payee,
'shirt_rate': self.shirt_rate,
@ -62,6 +67,9 @@ class Invoice2017:
def _read_invoice_header(self, table, first_row_text, rows_text):
self.invoice_id = first_row_text[1]
for key, value in rows_text:
if key == 'Issue date':
self.invoice_date = self._strpdate(value)
recipient_h = table.find('th', text='Recipient')
recipient_cell = recipient_h.find_next_sibling('td')
self.payee = next(recipient_cell.stripped_strings)
@ -83,13 +91,16 @@ class Invoice2017:
self.amount += decimal.Decimal(total.lstrip('$'))
def _read_invoice_activity(self, table, first_row_text, rows_text):
self.actions = []
self.actions = [{
'date': self.invoice_date,
'status': STATUS_INVOICED,
}]
for timestamp, description, amount in rows_text:
if description.startswith('Paid '):
last_stripe_id = util.rslice_words(description, 1, limit=1)
action = {
'multiplier': 1,
'payment_id': last_stripe_id,
'status': STATUS_PAID,
}
else:
# Refund handling could go here, if we need it.
@ -102,9 +113,6 @@ class Invoice2017:
for action in self.actions:
data = self.base_data.copy()
data.update(action)
multiplier = data.pop('multiplier')
for key in ['amount', 'tickets_sold', 'shirts_sold']:
data[key] *= multiplier
yield data
@ -129,13 +137,17 @@ class ImporterBase:
def __iter__(self):
for entry in self.invoice:
if self._should_yield_entry(entry):
if entry['status'] == self.YIELD_STATUS:
yield entry
class Invoice2017Importer(ImporterBase):
TEMPLATE_KEY = 'template nbpy2017 invoice'
INVOICE_CLASS = Invoice2017
YIELD_STATUS = STATUS_INVOICED
class Payment2017Importer(ImporterBase):
TEMPLATE_KEY = 'template nbpy2017 payment'
INVOICE_CLASS = Invoice2017
def _should_yield_entry(self, entry):
return entry['amount'] > 0
YIELD_STATUS = STATUS_PAID

View file

@ -82,6 +82,51 @@
payment_id: ch_hHee9ef1aeyee1ruo7ochee9
description: "Payment for invoice #100"
- source: nbpy2017a.html
importer: nbpy2017.Invoice2017Importer
expect:
- payee: Python Person A
date: !!python/object/apply:datetime.date [2017, 10, 19]
amount: !!python/object/apply:decimal.Decimal ["80.00"]
tickets_sold: !!python/object/apply:decimal.Decimal ["1"]
ticket_rate: !!python/object/apply:decimal.Decimal ["21.25"]
shirts_sold: !!python/object/apply:decimal.Decimal ["1"]
shirt_rate: !!python/object/apply:decimal.Decimal ["25.50"]
currency: USD
status: Invoice
invoice_id: "83"
invoice_date: !!python/object/apply:datetime.date [2017, 10, 19]
- source: nbpy2017b.html
importer: nbpy2017.Invoice2017Importer
expect:
- payee: Python Person B
date: !!python/object/apply:datetime.date [2017, 12, 3]
amount: !!python/object/apply:decimal.Decimal ["50.00"]
tickets_sold: !!python/object/apply:decimal.Decimal ["1"]
ticket_rate: !!python/object/apply:decimal.Decimal ["42.50"]
shirts_sold: !!python/object/apply:decimal.Decimal ["0"]
shirt_rate: !!python/object/apply:decimal.Decimal ["25.50"]
status: Invoice
currency: USD
invoice_date: !!python/object/apply:datetime.date [2017, 12, 3]
invoice_id: "304"
- source: nbpy2017c.html
importer: nbpy2017.Invoice2017Importer
expect:
- payee: Python Person C
date: !!python/object/apply:datetime.date [2017, 10, 5]
amount: !!python/object/apply:decimal.Decimal ["55.00"]
tickets_sold: !!python/object/apply:decimal.Decimal ["1"]
ticket_rate: !!python/object/apply:decimal.Decimal ["21.25"]
shirts_sold: !!python/object/apply:decimal.Decimal ["1"]
shirt_rate: !!python/object/apply:decimal.Decimal ["25.50"]
status: Invoice
currency: USD
invoice_date: !!python/object/apply:datetime.date [2017, 10, 5]
invoice_id: "11"
- source: nbpy2017a.html
importer: nbpy2017.Payment2017Importer
expect:
@ -93,7 +138,9 @@
shirts_sold: !!python/object/apply:decimal.Decimal ["1"]
shirt_rate: !!python/object/apply:decimal.Decimal ["25.50"]
currency: USD
status: Payment
invoice_id: "83"
invoice_date: !!python/object/apply:datetime.date [2017, 10, 19]
payment_id: ch_ahr0ue8lai1ohqu4Gei4Biem
stripe_id: ch_ahr0ue8lai1ohqu4Gei4Biem
@ -107,7 +154,9 @@
ticket_rate: !!python/object/apply:decimal.Decimal ["42.50"]
shirts_sold: !!python/object/apply:decimal.Decimal ["0"]
shirt_rate: !!python/object/apply:decimal.Decimal ["25.50"]
status: Payment
currency: USD
invoice_date: !!python/object/apply:datetime.date [2017, 12, 3]
payment_id: ch_eishei9aiY8aiqu4lieYiu9i
stripe_id: ch_eishei9aiY8aiqu4lieYiu9i
invoice_id: "304"
@ -122,7 +171,9 @@
ticket_rate: !!python/object/apply:decimal.Decimal ["21.25"]
shirts_sold: !!python/object/apply:decimal.Decimal ["1"]
shirt_rate: !!python/object/apply:decimal.Decimal ["25.50"]
status: Payment
currency: USD
invoice_date: !!python/object/apply:datetime.date [2017, 10, 5]
payment_id: ch_daer0ahwoh9oDeiqu2eimoD7
stripe_id: ch_daer0ahwoh9oDeiqu2eimoD7
invoice_id: "11"