diff --git a/import2ledger/importers/benevity.py b/import2ledger/importers/benevity.py new file mode 100644 index 0000000..4e5a34d --- /dev/null +++ b/import2ledger/importers/benevity.py @@ -0,0 +1,78 @@ +import csv + +from . import _csv +from .. import strparse + +class PaymentImporter(_csv.CSVImporterBase): + DATE_FIELD = 'Date of Donation' + NAME_FIELDS = ['Donor First Name', 'Donor Last Name'] + DECIMAL_FIELDS = { + 'Donation Amount': 'donation_amount', + 'Matched Amount': 'match_amount', + 'Total': 'amount', + } + NEEDED_FIELDS = frozenset([ + DATE_FIELD, + *NAME_FIELDS, + *DECIMAL_FIELDS, + ]) + COPIED_FIELDS = { + 'Participating Corporation': 'corporation', + 'Project': 'project', + 'Comment': 'comment', + 'Transaction ID': 'transaction_id', + 'Donation Frequency': 'frequency', + } + TEMPLATE_KEY = 'template benevity payments' + DATE_FMT = '%Y-%m-%d' + NOT_SHARED = 'Not shared by donor' + + @classmethod + def _read_header(cls, source): + needed_keys = cls.NEEDED_FIELDS.union(cls.COPIED_FIELDS) + header = {} + for row in csv.reader(source): + row_len = len(row) + if row_len < 2: + pass + elif row_len == 2: + header[row[0]] = row[1] + elif needed_keys.issubset(row): + return header, csv.DictReader(source, row) + else: + break + raise ValueError("source is not a Benevity CSV") + + @classmethod + def can_import(cls, input_file): + try: + header, _ = cls._read_header(input_file) + except ValueError: + return False + else: + return bool(header) + + def __init__(self, input_file): + header, self.in_csv = self._read_header(input_file) + self.entry_seed = { + 'currency': header['Currency'], + 'disbursement_id': header['Disbursement ID'], + 'reference': header['Payment Reference'], + } + + def _read_row(self, row): + try: + date = strparse.date(row[self.DATE_FIELD], self.DATE_FMT) + except ValueError: + return None + if all(row[key] == self.NOT_SHARED for key in self.NAME_FIELDS): + payee = 'Anonymous' + else: + payee = ' '.join(row[key] for key in self.NAME_FIELDS) + retval = { + 'date': date, + 'payee': payee, + } + retval.update((retkey, strparse.currency_decimal(row[rowkey])) + for rowkey, retkey in self.DECIMAL_FIELDS.items()) + return retval