From e5a0089eb900761fe363853aa156250e32194dbe Mon Sep 17 00:00:00 2001 From: Brett Smith Date: Thu, 9 Nov 2017 15:06:02 -0500 Subject: [PATCH] importers: Add an importer for Stripe payments. --- README.rst | 22 +++++++++++++++++++++ import2ledger/importers/stripe.py | 32 +++++++++++++++++++++++++++++++ tests/data/StripePayments.csv | 3 +++ tests/data/imports.yml | 20 +++++++++++++++++++ tests/test_importers.py | 19 ++++++++++++++---- 5 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 import2ledger/importers/stripe.py create mode 100644 tests/data/StripePayments.csv diff --git a/README.rst b/README.rst index 7c32836..0460094 100644 --- a/README.rst +++ b/README.rst @@ -108,6 +108,28 @@ Patreon withheld for ============== ============================================================ +Stripe +^^^^^^ + +``template stripe payments`` + Imports one transaction per payment. Generated from Stripe's payments CSV export. + + This template can use these variables: + + ============ ============================================================ + Name Contents + ============ ============================================================ + description The description given to the payment when it was created + ------------ ------------------------------------------------------------ + fee The amount of fees charged by Stripe for this payment, as a + plain decimal number + ------------ ------------------------------------------------------------ + payment_id The id assigned to this payment by Stripe + ------------ ------------------------------------------------------------ + tax The amount of tax withheld by Stripe for this payment, as a + plain decimal number + ============ ============================================================ + Other output options ~~~~~~~~~~~~~~~~~~~~ diff --git a/import2ledger/importers/stripe.py b/import2ledger/importers/stripe.py new file mode 100644 index 0000000..68debcd --- /dev/null +++ b/import2ledger/importers/stripe.py @@ -0,0 +1,32 @@ +import decimal + +from . import _csv +from .. import util + +class PaymentImporter(_csv.CSVImporterBase): + NEEDED_FIELDS = frozenset([ + 'Converted Currency', + 'Created (UTC)', + 'Fee', + 'Status', + 'Tax', + ]) + COPIED_FIELDS = { + 'Card Name': 'payee', + 'Converted Amount': 'amount', + 'Description': 'description', + 'id': 'payment_id', + } + TEMPLATE_KEY = 'template stripe payments' + DATE_FMT = '%Y-%m-%d' + + def _read_row(self, row): + if row['Status'] != 'Paid': + return None + else: + return { + 'currency': row['Converted Currency'].upper(), + 'date': util.strpdate(row['Created (UTC)'].split(None, 1)[0], self.DATE_FMT), + 'fee': decimal.Decimal(row['Fee']), + 'tax': decimal.Decimal(row['Tax']), + } diff --git a/tests/data/StripePayments.csv b/tests/data/StripePayments.csv new file mode 100644 index 0000000..8c9b3e0 --- /dev/null +++ b/tests/data/StripePayments.csv @@ -0,0 +1,3 @@ +id,Description,Created (UTC),Amount,Amount Refunded,Currency,Converted Amount,Converted Amount Refunded,Fee,Tax,Converted Currency,Mode,Status,Statement Descriptor,Customer ID,Customer Description,Customer Email,Captured,Card ID,Card Last4,Card Brand,Card Funding,Card Exp Month,Card Exp Year,Card Name,Card Address Line1,Card Address Line2,Card Address City,Card Address State,Card Address Country,Card Address Zip,Card Issue Country,Card Fingerprint,Card CVC Status,Card AVS Zip Status,Card AVS Line1 Status,Card Tokenization Method,Disputed Amount,Dispute Status,Dispute Reason,Dispute Date (UTC),Dispute Evidence Due (UTC),Invoice ID,Payment Source Type,Destination,Transfer,Transfer Group +ch_oxuish6phae2Raighooghi3U,Payment for invoice #102,2017-11-08 16:56,100,0,usd,100,0,3,0,usd,Live,Paid,,cus_DohSheeQu8eng3,,one@example.org,true,card_na1joNohg9Aim6eg9eefooRe,0000,American Express,credit,1,2010,Dakota Smith,1 Example St,,City,State,United States,12345,US,queiheVu2ohyei2u,pass,pass,pass,,,,,,,,card,,, +ch_hHee9ef1aeyee1ruo7ochee9,Payment for invoice #100,2017-10-28 02:32,50,0,usd,50,0,1.4,0,usd,Live,Paid,,cus_iepae2Iecae8Ei,,two@example.org,true,card_sitej3Xi2aNgo1ohfoahue8e,0001,Visa,credit,2,2011,Dakota Jones,2 Example St,,City,State,United States,12345,US,men2shi3xo1Mao4u,pass,pass,pass,,,,,,,,card,,, diff --git a/tests/data/imports.yml b/tests/data/imports.yml index 427667e..f79d2e0 100644 --- a/tests/data/imports.yml +++ b/tests/data/imports.yml @@ -61,3 +61,23 @@ currency: USD country_code: CZ country_name: Czech Republic + +- source: StripePayments.csv + importer: stripe.PaymentImporter + expect: + - payee: Dakota Smith + date: [2017, 11, 8] + amount: "100" + fee: "3" + tax: "0" + currency: USD + payment_id: ch_oxuish6phae2Raighooghi3U + description: "Payment for invoice #102" + - payee: Dakota Jones + date: [2017, 10, 28] + amount: "50" + fee: "1.4" + tax: "0" + currency: USD + payment_id: ch_hHee9ef1aeyee1ruo7ochee9 + description: "Payment for invoice #100" diff --git a/tests/test_importers.py b/tests/test_importers.py index 1a47d56..fcf8713 100644 --- a/tests/test_importers.py +++ b/tests/test_importers.py @@ -1,4 +1,5 @@ import datetime +import decimal import importlib import itertools import pathlib @@ -10,6 +11,15 @@ from import2ledger import importers from . import DATA_DIR class TestImporters: + def _date(parts_list): + return datetime.date(*parts_list) + + DATA_TYPES = { + 'date': _date, + 'fee': decimal.Decimal, + 'tax': decimal.Decimal, + } + with pathlib.Path(DATA_DIR, 'imports.yml').open() as yaml_file: test_data = yaml.load(yaml_file) for test in test_data: @@ -20,10 +30,11 @@ class TestImporters: test['importer'] = getattr(module, class_name) for expect_result in test['expect']: - try: - expect_result['date'] = datetime.date(*expect_result['date']) - except KeyError: - pass + for key, type_func in DATA_TYPES.items(): + try: + expect_result[key] = type_func(expect_result[key]) + except KeyError: + pass @pytest.mark.parametrize('source_path,importer', [ (t['source'], t['importer']) for t in test_data