From 44762555d5ebc608e43df51a12c25c438cda570d Mon Sep 17 00:00:00 2001 From: Brett Smith Date: Mon, 25 Feb 2019 12:39:19 -0500 Subject: [PATCH] yourcause: New importer. --- README.rst | 41 ++++++++++++++ import2ledger/importers/yourcause.py | 79 ++++++++++++++++++++++++++ setup.py | 2 +- tests/data/YourCause.csv | 6 ++ tests/data/imports.yml | 84 ++++++++++++++++++++++++++++ 5 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 import2ledger/importers/yourcause.py create mode 100644 tests/data/YourCause.csv diff --git a/README.rst b/README.rst index cc6a39e..9c6c7c2 100644 --- a/README.rst +++ b/README.rst @@ -344,6 +344,47 @@ Stripe retried_payout_net Decimal from the corresponding CSV column ========================== ============================================== +YourCause +^^^^^^^^^ + +``yourcause donations ledger entry`` + Imports one transaction per row in YourCause's donations report CSV. + + This template can use these variables: + + ================= ========================================================== + Name Contents + ================= ========================================================== + comment The comment from the donor + ----------------- ---------------------------------------------------------- + corporation The name of the participating corporation + ----------------- ---------------------------------------------------------- + dedication Text from the corresponding CSV column + ----------------- ---------------------------------------------------------- + dedication_type Text from the corresponding CSV column + ----------------- ---------------------------------------------------------- + designation Text from the corresponding CSV column + ----------------- ---------------------------------------------------------- + donor Name of the individual who donated + ----------------- ---------------------------------------------------------- + donor_amount The amount donated by the individual donor named + ----------------- ---------------------------------------------------------- + match_amount The amount of the donation match by the participating + corporation + ----------------- ---------------------------------------------------------- + original_amount The amount of the original donation in the original + currency + ----------------- ---------------------------------------------------------- + original_currency The local currency the original donation was made in + ----------------- ---------------------------------------------------------- + payment_id The ID of the payment from YourCause that includes this + donation + ----------------- ---------------------------------------------------------- + received_amount Decimal from the corresponding CSV column + ----------------- ---------------------------------------------------------- + transaction_id The ID of this donation from YourCause + ================= ========================================================== + Other output options ~~~~~~~~~~~~~~~~~~~~ diff --git a/import2ledger/importers/yourcause.py b/import2ledger/importers/yourcause.py new file mode 100644 index 0000000..d7446ee --- /dev/null +++ b/import2ledger/importers/yourcause.py @@ -0,0 +1,79 @@ +import decimal + +try: + import enum +except ImportError: + import enum34 as enum + +from . import _csv +from .. import strparse + +ZERO_DECIMAL = decimal.Decimal(0) + +class _DonorType(enum.Enum): + Individual = 1 + Company = 2 + + @classmethod + def from_donation_type(cls, donation_type): + if donation_type.startswith('Individual-'): + return cls.Individual + elif donation_type.startswith('Employer Match-'): + return cls.Company + else: + raise ValueError("unknown donation type {!r}".format(donation_type)) + + +class DonationsImporter(_csv.CSVImporterBase): + ANONYMOUS = "Anonymous" + DATE_FMT = '%m/%d/%Y %I:%M:%S %p' + DONATION_TYPE_FIELD = 'Donation Type' + ENTRY_SEED = { + 'currency': 'USD', + 'donor_amount': ZERO_DECIMAL, + 'match_amount': ZERO_DECIMAL, + } + DECIMAL_FIELDS = { + 'Local Currency Receipt Amount': 'original_amount', + 'Received Amount': 'received_amount', + 'Transaction Amount': 'amount', + } + NEEDED_FIELDS = frozenset([ + DONATION_TYPE_FIELD, + 'Donor First Name', + 'Donor Last Name', + 'Match Donor First Name', + 'Match Donor Last Name', + *DECIMAL_FIELDS, + ]) + COPIED_FIELDS = { + 'Company_Name': 'corporation', + 'Dedication Type': 'dedication_type', + 'Dedication': 'dedication', + 'Designation': 'designation', + 'Local Currency Type': 'original_currency', + 'Payment ID': 'payment_id', + 'Transaction_ID': 'transaction_id', + } + + def _donor_name(self, row, *keys): + names = [row[key] for key in keys] + if any(s and s != self.ANONYMOUS for s in names): + return ' '.join(names).strip() + else: + return self.ANONYMOUS + + def _read_row(self, row): + donor_type = _DonorType.from_donation_type(row[self.DONATION_TYPE_FIELD]) + retval = {retkey: strparse.currency_decimal(row[rowkey]) + for rowkey, retkey in self.DECIMAL_FIELDS.items()} + retval['date'] = strparse.date(row['Donation_Date'], self.DATE_FMT) + if donor_type is _DonorType.Individual: + retval['donor'] = self._donor_name(row, 'Donor First Name', 'Donor Last Name') + retval['donor_amount'] = retval['amount'] + retval['payee'] = retval['donor'] + else: + retval['donor'] = self._donor_name(row, 'Match Donor First Name', 'Match Donor Last Name') + retval['match_amount'] = retval['amount'] + retval['payee'] = row['Company_Name'] + return retval diff --git a/setup.py b/setup.py index 04749f2..b1bc649 100755 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ REQUIREMENTS['tests_require'] = [ setup( name='import2ledger', description="Import different sources of financial data to Ledger", - version='0.7.0', + version='0.8.0', author='Brett Smith', author_email='brettcsmith@brettcsmith.org', license='GNU AGPLv3+', diff --git a/tests/data/YourCause.csv b/tests/data/YourCause.csv new file mode 100644 index 0000000..839b096 --- /dev/null +++ b/tests/data/YourCause.csv @@ -0,0 +1,6 @@ +Donation_Date,Company_Name,Transaction_ID,Donation Type,Transaction Amount,Received Amount,Is Disbursed?,Payment ID,Payment Create Date,Payment Status Date,Payment Status,Donor Type,Donor ID,Donor First Name,Donor Last Name,Donor Full Name,Donor Email Address,Donor Address,Donor Address2,Donor City,Donor State/Province/Region,Donor Postal Code,Donor Country,Match Donor ID,Match Donor First Name,Match Donor Last Name,Dedication Type,Dedication,Designation,Registration ID,Designated Charity Name,Donation Status,Alternate Recognition Name,Segment Name,Local Currency Receipt Amount,Local Currency Type +12/20/2018 1:13:00 PM,Company A,2-34567891,Individual-Credit Card,12,12,TRUE,10006789,01/22/2019 5:46:00 PM,,Outstanding,Individual,E1,Dakota,Smith,Dakota Smith,ds@example.com,123 Any Street,,Anytown,Maine,01234,US,,,,,,Note,410123456,Test Charity,Disbursed,,US Segment,12,USD +12/31/2018 10:17:00 PM,Company B,2-34567893,Individual-Credit Card,14,14,TRUE,10006789,01/22/2019 5:46:00 PM,,Outstanding,Individual,E2,,,,,,,,,,,,,,,,,410123456,Test Charity,Disbursed,,US Segment,14,USD +12/20/2018 1:13:00 PM,Company A,2-34567895,Employer Match-Credit Card Match,12,12,TRUE,10006789,01/22/2019 5:46:00 PM,,Outstanding,Company,C1,,,Company A,,,,,,,,E1,Dakota,Smith,,,Note,410123456,Test Charity,Disbursed,,US Segment,12,USD +12/31/2018 10:17:00 PM,Company B,2-34567897,Employer Match-Credit Card,14,14,TRUE,10006789,01/22/2019 5:46:00 PM,,Outstanding,Individual,E2,,,,,,,,,,,,,,,,,410123456,Test Charity,Disbursed,,US Segment,14,USD +12/15/2018 10:17:00 AM,Company C,2-34567899,Individual-Credit Card,12.50000,12.50000,TRUE,10006789,01/22/2019 5:46:00 PM,,Outstanding,Individual,E3,Alex,Jones,Alex Jones,,,,,,,,,,,,,,410123456,Test Charity,Disbursed,,US Segment,10,GBP diff --git a/tests/data/imports.yml b/tests/data/imports.yml index 901bc39..6f89039 100644 --- a/tests/data/imports.yml +++ b/tests/data/imports.yml @@ -594,3 +594,87 @@ currency: USD amount: !!python/object/apply:decimal.Decimal ["73.85"] payee: "O'Reilly Media, Inc." + +- source: YourCause.csv + importer: yourcause.DonationsImporter + expect: + - date: !!python/object/apply:datetime.date [2018, 12, 20] + currency: USD + original_currency: USD + payment_id: "10006789" + transaction_id: 2-34567891 + amount: !!python/object/apply:decimal.Decimal [12] + original_amount: !!python/object/apply:decimal.Decimal [12] + received_amount: !!python/object/apply:decimal.Decimal [12] + donor_amount: !!python/object/apply:decimal.Decimal [12] + match_amount: !!python/object/apply:decimal.Decimal [0] + dedication_type: "" + dedication: "" + designation: Note + payee: Dakota Smith + donor: Dakota Smith + corporation: Company A + - date: !!python/object/apply:datetime.date [2018, 12, 31] + currency: USD + original_currency: USD + payment_id: "10006789" + transaction_id: 2-34567893 + amount: !!python/object/apply:decimal.Decimal [14] + original_amount: !!python/object/apply:decimal.Decimal [14] + received_amount: !!python/object/apply:decimal.Decimal [14] + donor_amount: !!python/object/apply:decimal.Decimal [14] + match_amount: !!python/object/apply:decimal.Decimal [0] + dedication_type: "" + dedication: "" + designation: "" + payee: Anonymous + donor: Anonymous + corporation: Company B + - date: !!python/object/apply:datetime.date [2018, 12, 20] + currency: USD + original_currency: USD + payment_id: "10006789" + transaction_id: 2-34567895 + amount: !!python/object/apply:decimal.Decimal [12] + original_amount: !!python/object/apply:decimal.Decimal [12] + received_amount: !!python/object/apply:decimal.Decimal [12] + donor_amount: !!python/object/apply:decimal.Decimal [0] + match_amount: !!python/object/apply:decimal.Decimal [12] + dedication_type: "" + dedication: "" + designation: Note + payee: Company A + donor: Dakota Smith + corporation: Company A + - date: !!python/object/apply:datetime.date [2018, 12, 31] + currency: USD + original_currency: USD + payment_id: "10006789" + transaction_id: 2-34567897 + amount: !!python/object/apply:decimal.Decimal [14] + original_amount: !!python/object/apply:decimal.Decimal [14] + received_amount: !!python/object/apply:decimal.Decimal [14] + donor_amount: !!python/object/apply:decimal.Decimal [0] + match_amount: !!python/object/apply:decimal.Decimal [14] + dedication_type: "" + dedication: "" + designation: "" + payee: Company B + donor: Anonymous + corporation: Company B + - date: !!python/object/apply:datetime.date [2018, 12, 15] + currency: USD + original_currency: GBP + payment_id: "10006789" + transaction_id: 2-34567899 + amount: !!python/object/apply:decimal.Decimal ["12.50"] + original_amount: !!python/object/apply:decimal.Decimal [10] + received_amount: !!python/object/apply:decimal.Decimal ["12.50"] + donor_amount: !!python/object/apply:decimal.Decimal ["12.50"] + match_amount: !!python/object/apply:decimal.Decimal [0] + dedication_type: "" + dedication: "" + designation: "" + payee: Alex Jones + donor: Alex Jones + corporation: Company C