Changeset - 4bdea41c3f36
[Not reviewed]
0 4 1
Brett Smith - 4 years ago 2020-08-30 22:21:59
brettcsmith@brettcsmith.org
patreon: New importer for new patron report CSV format.
5 files changed with 78 insertions and 16 deletions:
0 comments (0 inline, 0 general)
README.rst
Show inline comments
...
 
@@ -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.
 

	
import2ledger/importers/patreon.py
Show inline comments
...
 
@@ -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),
 
            }
setup.py
Show inline comments
...
 
@@ -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+',
tests/data/PatreonPatronReport_2020-08-01.csv
Show inline comments
 
new file 100644
 
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
tests/data/imports.yml
Show inline comments
 
- 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:
0 comments (0 inline, 0 general)