patreon: New importer for new patron report CSV format.
This commit is contained in:
parent
e5b600dae6
commit
4bdea41c3f
5 changed files with 78 additions and 16 deletions
12
README.rst
12
README.rst
|
@ -287,6 +287,18 @@ Patreon
|
||||||
``patreon income ledger entry``
|
``patreon income ledger entry``
|
||||||
Imports one transaction per patron per month. Generated from Patreon's monthly patron report CSVs.
|
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``
|
``patreon payout ledger entry``
|
||||||
Imports one transaction per month for that month's payout. Generated from Patreon's payout report CSV.
|
Imports one transaction per month for that month's payout. Generated from Patreon's payout report CSV.
|
||||||
|
|
||||||
|
|
|
@ -5,32 +5,31 @@ from . import _csv
|
||||||
from .. import strparse
|
from .. import strparse
|
||||||
|
|
||||||
class IncomeImporter(_csv.CSVImporterBase):
|
class IncomeImporter(_csv.CSVImporterBase):
|
||||||
|
AMOUNT_KEY = 'Pledge $'
|
||||||
|
DATE_KEY = 'Charged On Date'
|
||||||
|
STATUS_KEY = 'Charge Status'
|
||||||
NEEDED_FIELDS = frozenset([
|
NEEDED_FIELDS = frozenset([
|
||||||
'FirstName',
|
AMOUNT_KEY,
|
||||||
'LastName',
|
DATE_KEY,
|
||||||
'Pledge',
|
STATUS_KEY,
|
||||||
'Status',
|
|
||||||
])
|
])
|
||||||
COPIED_FIELDS = {
|
COPIED_FIELDS = {
|
||||||
'Pledge': 'amount',
|
'Name': 'payee',
|
||||||
|
'Email': 'email',
|
||||||
|
'Tier': 'tier',
|
||||||
|
'User ID': 'patreon_id',
|
||||||
}
|
}
|
||||||
ENTRY_SEED = {
|
ENTRY_SEED = {
|
||||||
'currency': 'USD',
|
'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):
|
def _read_row(self, row):
|
||||||
if row['Status'] != 'Processed':
|
if row[self.STATUS_KEY] != 'Paid':
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return {
|
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 Code': 'country_code',
|
||||||
'Country Name': 'country_name',
|
'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),
|
||||||
|
}
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -30,7 +30,7 @@ REQUIREMENTS['tests_require'] = [
|
||||||
setup(
|
setup(
|
||||||
name='import2ledger',
|
name='import2ledger',
|
||||||
description="Import different sources of financial data to Ledger",
|
description="Import different sources of financial data to Ledger",
|
||||||
version='1.0.0',
|
version='1.1.0',
|
||||||
author='Brett Smith',
|
author='Brett Smith',
|
||||||
author_email='brettcsmith@brettcsmith.org',
|
author_email='brettcsmith@brettcsmith.org',
|
||||||
license='GNU AGPLv3+',
|
license='GNU AGPLv3+',
|
||||||
|
|
3
tests/data/PatreonPatronReport_2020-08-01.csv
Normal file
3
tests/data/PatreonPatronReport_2020-08-01.csv
Normal file
|
@ -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
|
|
|
@ -1,5 +1,5 @@
|
||||||
- source: PatreonPatronReport_2017-09-01.csv
|
- source: PatreonPatronReport_2017-09-01.csv
|
||||||
importer: patreon.IncomeImporter
|
importer: patreon.Income2017Importer
|
||||||
expect:
|
expect:
|
||||||
- payee: Alex Jones
|
- payee: Alex Jones
|
||||||
date: !!python/object/apply:datetime.date [2017, 9, 1]
|
date: !!python/object/apply:datetime.date [2017, 9, 1]
|
||||||
|
@ -10,6 +10,24 @@
|
||||||
amount: !!python/object/apply:decimal.Decimal ["12.00"]
|
amount: !!python/object/apply:decimal.Decimal ["12.00"]
|
||||||
currency: USD
|
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
|
- source: PatreonEarnings.csv
|
||||||
importer: patreon.ServiceFeesImporter
|
importer: patreon.ServiceFeesImporter
|
||||||
expect:
|
expect:
|
||||||
|
|
Loading…
Reference in a new issue