Files @ 1b1e2d038c0b
Branch filter:

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

Brett Smith
importers.benevity: Initial version.
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