Files @ 1e24bfe30455
Branch filter:

Location: NPO-Accounting/import2ledger/import2ledger/importers/patreon.py

Brett Smith
github: Turn PRIVATE handle into Anonymous.
import pathlib
import re

from . import _csv
from .. import strparse

class EarningsImporter(_csv.CSVImporterBase):
    AMOUNT_FIELDS = {
        'Creator Share': 'net_amount',
        'Creator Platform Fee': 'platform_fee',
        'Creator Payment Processing Fee': 'processing_fee',
        'Creator Currency Conversion Fee': 'currency_fee',
        'Creator Equivalent of Patron Tax': 'tax_amount',
    }
    DATE_KEY = 'Date'
    TYPE_KEY = 'Event Type'
    NEEDED_FIELDS = frozenset([*AMOUNT_FIELDS, DATE_KEY, TYPE_KEY])
    COPIED_FIELDS = {
        'Creator Currency': 'currency',
        'Event ID': 'event_id',
        'Patron Email': 'email',
        'Patron Name': 'payee',
        'Patron User ID': 'user_id',
    }
    DATE_FMT = '%Y-%m-%d %H:%M:%S'

    def _read_row(self, row):
        if row[self.TYPE_KEY] != 'Payment':
            return None
        retval = {
            ret_key: strparse.currency_decimal(row[src_key] or 0)
            for src_key, ret_key in self.AMOUNT_FIELDS.items()
        }
        retval['amount'] = sum(retval.values()) - retval['tax_amount']
        retval['date'] = strparse.date(row[self.DATE_KEY], self.DATE_FMT)
        return retval


class IncomeImporter(_csv.CSVImporterBase):
    AMOUNT_KEY = 'Pledge Amount'
    DATE_KEY = 'Last Charge Date'
    STATUS_KEY = 'Last Charge Status'
    NEEDED_FIELDS = frozenset([
        AMOUNT_KEY,
        DATE_KEY,
        STATUS_KEY,
    ])
    COPIED_FIELDS = {
        'Name': 'payee',
        'Email': 'email',
        'Tier': 'tier',
        'User ID': 'patreon_id',
    }
    ENTRY_SEED = {
        'currency': 'USD',
    }

    def __init_subclass__(cls):
        cls.NEEDED_FIELDS = frozenset([
            cls.AMOUNT_KEY,
            cls.DATE_KEY,
            cls.STATUS_KEY,
        ])

    def _read_row(self, row):
        if row[self.STATUS_KEY] != 'Paid':
            return None
        else:
            return {
                'amount': strparse.currency_decimal(row[self.AMOUNT_KEY]),
                'date': strparse.date(row[self.DATE_KEY], '%Y-%m-%d %H:%M:%S'),
            }


class PayoutImporter(_csv.CSVImporterBase):
    AMOUNT_KEY = 'Total funds deducted from creator balance'
    PLEDGE_KEY = 'Funds used for pledges to other creators'
    TRANSFER_KEY = 'Funds transferred to you'
    NEEDED_FIELDS = frozenset([
        'Month',
        TRANSFER_KEY,
        PLEDGE_KEY,
        AMOUNT_KEY,
    ])
    ENTRY_SEED = {
        'currency': 'USD',
        'payee': 'Patreon',
    }

    def _read_row(self, row):
        amount = strparse.currency_decimal(row[self.AMOUNT_KEY])
        if not amount:
            return None
        else:
            return {
                'amount': amount,
                'date': strparse.date(row['Month'], '%Y-%m'),
                'pledges_amount': strparse.currency_decimal(row[self.PLEDGE_KEY]),
                'transfer_amount': strparse.currency_decimal(row[self.TRANSFER_KEY]),
            }


class FeeImporterBase(_csv.CSVImporterBase):
    ENTRY_SEED = {
        'currency': 'USD',
        'payee': "Patreon",
    }

    def _read_row(self, row):
        return {
            'amount': row[self.AMOUNT_FIELD],
            'date': strparse.date(row['Month'], '%Y-%m'),
        }


class ServiceFeesImporter(FeeImporterBase):
    AMOUNT_FIELD = 'Patreon Fee'
    NEEDED_FIELDS = frozenset(['Month', AMOUNT_FIELD])


class CardFeesImporter(FeeImporterBase):
    AMOUNT_FIELD = 'Processing Fees'
    NEEDED_FIELDS = frozenset(['Month', AMOUNT_FIELD])


class VATImporter(FeeImporterBase):
    AMOUNT_FIELD = 'Vat Charged'
    NEEDED_FIELDS = frozenset(['Month', AMOUNT_FIELD])
    COPIED_FIELDS = {
        'Country Code': 'country_code',
        'Country Name': 'country_name',
    }



class Income2020OctoberImporter(IncomeImporter):
    AMOUNT_KEY = 'Pledge $'


class Income2020AugustImporter(Income2020OctoberImporter):
    DATE_KEY = 'Charged On Date'
    STATUS_KEY = 'Charge Status'


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),
            }