From 4bdea41c3f368c3773e3a403a6e212a6984ec8fc 2020-08-30 22:21:59 From: Brett Smith Date: 2020-08-30 22:21:59 Subject: [PATCH] patreon: New importer for new patron report CSV format. --- diff --git a/README.rst b/README.rst index bccc94d0ac5b8a0ea8920030e1ae9fe86daebc6c..70ac3472b88e924a63a16bf9cc5dcb494d781108 100644 --- a/README.rst +++ b/README.rst @@ -287,6 +287,18 @@ Patreon ``patreon income ledger entry`` Imports one transaction per patron per month. Generated from Patreon's monthly patron report CSVs. + This template can use these variables: + + =============== =========================================================== + Name Contents + =============== =========================================================== + email The patron's email address on Patreon + --------------- ----------------------------------------------------------- + tier The name of the tier the patron is supporting at + --------------- ----------------------------------------------------------- + patreon_id The patron's user ID on Patreon + =============== =========================================================== + ``patreon payout ledger entry`` Imports one transaction per month for that month's payout. Generated from Patreon's payout report CSV. diff --git a/import2ledger/importers/patreon.py b/import2ledger/importers/patreon.py index e1ee21002cd98ca68f3c1c18e5f83f7b49b6a1cf..5588a1e65805d4e2d9ca908c30c84b0cc03b9fed 100644 --- a/import2ledger/importers/patreon.py +++ b/import2ledger/importers/patreon.py @@ -5,32 +5,31 @@ from . import _csv from .. import strparse class IncomeImporter(_csv.CSVImporterBase): + AMOUNT_KEY = 'Pledge $' + DATE_KEY = 'Charged On Date' + STATUS_KEY = 'Charge Status' NEEDED_FIELDS = frozenset([ - 'FirstName', - 'LastName', - 'Pledge', - 'Status', + AMOUNT_KEY, + DATE_KEY, + STATUS_KEY, ]) COPIED_FIELDS = { - 'Pledge': 'amount', + 'Name': 'payee', + 'Email': 'email', + 'Tier': 'tier', + 'User ID': 'patreon_id', } ENTRY_SEED = { 'currency': 'USD', } - def __init__(self, input_file): - super().__init__(input_file) - match = re.search(r'(?:\b|_)(\d{4}-\d{2}-\d{2})(?:\b|_)', - pathlib.Path(input_file.name).name) - if match: - self.entry_seed['date'] = strparse.date(match.group(1), '%Y-%m-%d') - def _read_row(self, row): - if row['Status'] != 'Processed': + if row[self.STATUS_KEY] != 'Paid': return None else: return { - 'payee': '{0[FirstName]} {0[LastName]}'.format(row), + 'amount': strparse.currency_decimal(row[self.AMOUNT_KEY]), + 'date': strparse.date(row[self.DATE_KEY], '%Y-%m-%d %H:%M:%S'), } @@ -92,3 +91,33 @@ class VATImporter(FeeImporterBase): 'Country Code': 'country_code', 'Country Name': 'country_name', } + + +class Income2017Importer(_csv.CSVImporterBase): + NEEDED_FIELDS = frozenset([ + 'FirstName', + 'LastName', + 'Pledge', + 'Status', + ]) + COPIED_FIELDS = { + 'Pledge': 'amount', + } + ENTRY_SEED = { + 'currency': 'USD', + } + + def __init__(self, input_file): + super().__init__(input_file) + match = re.search(r'(?:\b|_)(\d{4}-\d{2}-\d{2})(?:\b|_)', + pathlib.Path(input_file.name).name) + if match: + self.entry_seed['date'] = strparse.date(match.group(1), '%Y-%m-%d') + + def _read_row(self, row): + if row['Status'] != 'Processed': + return None + else: + return { + 'payee': '{0[FirstName]} {0[LastName]}'.format(row), + } diff --git a/setup.py b/setup.py index 43bc81a7a76ce2e07bed24873b0aa42c6b592b19..178dbc57538b0eb6fa22e58af83b7e6fbc6ff539 100755 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ REQUIREMENTS['tests_require'] = [ setup( name='import2ledger', description="Import different sources of financial data to Ledger", - version='1.0.0', + version='1.1.0', author='Brett Smith', author_email='brettcsmith@brettcsmith.org', license='GNU AGPLv3+', diff --git a/tests/data/PatreonPatronReport_2020-08-01.csv b/tests/data/PatreonPatronReport_2020-08-01.csv new file mode 100644 index 0000000000000000000000000000000000000000..05f0936f7cd2a11be53075a6df9df3594cf361c5 --- /dev/null +++ b/tests/data/PatreonPatronReport_2020-08-01.csv @@ -0,0 +1,3 @@ +Name,Email,Twitter,Patron Status,Follows You,Lifetime $,Pledge $,Charge Frequency,Tier,Addressee,Street,City,State,Zip,Country,Phone,Patronage Since Date,Max Amount,Charged On Date,Charge Status,Additional Details,User ID,Last Updated +Alex Jones,ajones@example.com,,Active patron,No,$28,$2,monthly,Even tier,,,,,,,,2019-10-30 18:25:15.457830,$2,2020-08-01 18:21:04,Paid,,1234567,2020-08-12 12:34:31.348413 +Breonna,breonna@example.org,patreonb,Active patron,No,$5,$5,monthly,Odd tier,,,,,,,,2020-08-02 11:59:15.365305,$5,2020-08-02 12:00:02,Paid,,234567,2020-08-12 12:43:08.745681 diff --git a/tests/data/imports.yml b/tests/data/imports.yml index c00c289028d1bea0a2c8d6ddfae65fa86d0207a6..276a5e6ff0f3977401c62eec100d19b698248a67 100644 --- a/tests/data/imports.yml +++ b/tests/data/imports.yml @@ -1,5 +1,5 @@ - source: PatreonPatronReport_2017-09-01.csv - importer: patreon.IncomeImporter + importer: patreon.Income2017Importer expect: - payee: Alex Jones date: !!python/object/apply:datetime.date [2017, 9, 1] @@ -10,6 +10,24 @@ amount: !!python/object/apply:decimal.Decimal ["12.00"] currency: USD +- source: PatreonPatronReport_2020-08-01.csv + importer: patreon.IncomeImporter + expect: + - payee: Alex Jones + email: ajones@example.com + tier: Even tier + patreon_id: "1234567" + date: !!python/object/apply:datetime.date [2020, 8, 1] + amount: !!python/object/apply:decimal.Decimal ["2"] + currency: USD + - payee: Breonna + email: breonna@example.org + tier: Odd tier + patreon_id: "234567" + date: !!python/object/apply:datetime.date [2020, 8, 2] + amount: !!python/object/apply:decimal.Decimal ["5.00"] + currency: USD + - source: PatreonEarnings.csv importer: patreon.ServiceFeesImporter expect: