diff --git a/import2ledger/importers/stripe.py b/import2ledger/importers/stripe.py index e70b285..9a74513 100644 --- a/import2ledger/importers/stripe.py +++ b/import2ledger/importers/stripe.py @@ -33,3 +33,58 @@ class PaymentImporter(_csv.CSVImporterBase): 'fee': strparse.currency_decimal(row['Fee']), 'tax': strparse.currency_decimal(row['Tax']), } + + +class PayoutImporter(_csv.CSVImporterBase): + DECIMAL_FIELDS = {key: key.lower().replace(' ', '_') for key in [ + 'Amount', + 'Payment Count', + 'Payment Gross', + 'Payment Fees', + 'Payment Net', + 'Refund Count', + 'Refund Gross', + 'Refund Fees', + 'Refund Net', + 'Collected Fee Count', + 'Collected Fee Gross', + 'Collected Fee Refund Count', + 'Collected Fee Refund Gross', + 'Adjustment Count', + 'Adjustment Gross', + 'Adjustment Fees', + 'Adjustment Net', + 'Validation Count', + 'Validation Fees', + 'Retried Payout Count', + 'Retried Payout Net', + 'Total Count', + 'Total Gross', + 'Total Fees', + 'Total Net', + ]} + NEEDED_FIELDS = frozenset([ + 'Currency', + 'Created (UTC)', + 'Status', + *DECIMAL_FIELDS, + ]) + COPIED_FIELDS = { + 'Balance Transaction': 'balance_txid', + 'Destination': 'destination_id', + 'Failure Balance Transaction': 'failure_txid', + 'id': 'payout_id', + } + DATE_FMT = '%Y-%m-%d %H:%M' + ENTRY_SEED = {'payee': "Stripe"} + + def _read_row(self, row): + if row['Status'] != 'paid': + return None + retval = { + self.DECIMAL_FIELDS[key]: strparse.currency_decimal(row[key]) + for key in self.DECIMAL_FIELDS + } + retval['currency'] = row['Currency'].upper() + retval['date'] = strparse.date(row['Created (UTC)'], self.DATE_FMT) + return retval diff --git a/tests/data/StripePayouts.csv b/tests/data/StripePayouts.csv new file mode 100644 index 0000000..072a25e --- /dev/null +++ b/tests/data/StripePayouts.csv @@ -0,0 +1,3 @@ +id,Amount,Created (UTC),Currency,Livemode,Arrival Date (UTC),Source Type,Destination,Status,Type,Method,Description,Balance Transaction,Failure Balance Transaction,Failure Message,Failure Code,Statement Descriptor,Destination Name,Destination Country,Destination Last 4,Payment Count,Payment Gross,Payment Fees,Payment Net,Refund Count,Refund Gross,Refund Fees,Refund Net,Collected Fee Count,Collected Fee Gross,Collected Fee Refund Count,Collected Fee Refund Gross,Adjustment Count,Adjustment Gross,Adjustment Fees,Adjustment Net,Validation Count,Validation Fees,Retried Payout Count,Retried Payout Net,Total Count,Total Gross,Total Fees,Total Net +po_faegh6aeghishuethuoSoT2i,-50,2017-11-30 10:24,usd,true,2017-12-01 00:00,card,ba_chu0Woop5queewi2Ea1Aibah,paid,bank_account,standard,STRIPE TRANSFER,txn_EiKahrazei3aeMohk7EeDigh,,,,,YOUR BANK,US,1234,0,0,0,0,1,-50,0,-50,0,0,0,0,0,0,0,0,0,0,0,0,1,-50,0,-50 +po_Do9pathoo9Pu8jaePhahJa0e,146.5,2017-11-29 10:46,usd,true,2017-11-30 00:00,card,ba_chu0Woop5queewi2Ea1Aibah,paid,bank_account,standard,STRIPE TRANSFER,txn_ahsaixiene6Thie1aiti3tuo,,,,,YOUR BANK,US,1234,2,150,3.5,146.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,150,3.5,146.5 diff --git a/tests/data/imports.yml b/tests/data/imports.yml index 6c6aa9c..88baf34 100644 --- a/tests/data/imports.yml +++ b/tests/data/imports.yml @@ -88,6 +88,74 @@ payout_id: po_aeYees2ahtier8ohju7Eeyie description: "Payment for invoice #100" +- source: StripePayouts.csv + importer: stripe.PayoutImporter + expect: + - payee: Stripe + date: !!python/object/apply:datetime.date [2017, 11, 30] + amount: !!python/object/apply:decimal.Decimal ["-50"] + currency: USD + payment_count: !!python/object/apply:decimal.Decimal ["0"] + payment_gross: !!python/object/apply:decimal.Decimal ["0"] + payment_fees: !!python/object/apply:decimal.Decimal ["0"] + payment_net: !!python/object/apply:decimal.Decimal ["0"] + refund_count: !!python/object/apply:decimal.Decimal ["1"] + refund_gross: !!python/object/apply:decimal.Decimal ["-50"] + refund_fees: !!python/object/apply:decimal.Decimal ["0"] + refund_net: !!python/object/apply:decimal.Decimal ["-50"] + collected_fee_count: !!python/object/apply:decimal.Decimal ["0"] + collected_fee_gross: !!python/object/apply:decimal.Decimal ["0"] + collected_fee_refund_count: !!python/object/apply:decimal.Decimal ["0"] + collected_fee_refund_gross: !!python/object/apply:decimal.Decimal ["0"] + adjustment_count: !!python/object/apply:decimal.Decimal ["0"] + adjustment_gross: !!python/object/apply:decimal.Decimal ["0"] + adjustment_fees: !!python/object/apply:decimal.Decimal ["0"] + adjustment_net: !!python/object/apply:decimal.Decimal ["0"] + validation_count: !!python/object/apply:decimal.Decimal ["0"] + validation_fees: !!python/object/apply:decimal.Decimal ["0"] + retried_payout_count: !!python/object/apply:decimal.Decimal ["0"] + retried_payout_net: !!python/object/apply:decimal.Decimal ["0"] + total_count: !!python/object/apply:decimal.Decimal ["1"] + total_gross: !!python/object/apply:decimal.Decimal ["-50"] + total_fees: !!python/object/apply:decimal.Decimal ["0"] + total_net: !!python/object/apply:decimal.Decimal ["-50"] + payout_id: po_faegh6aeghishuethuoSoT2i + destination_id: ba_chu0Woop5queewi2Ea1Aibah + balance_txid: txn_EiKahrazei3aeMohk7EeDigh + failure_txid: "" + - payee: Stripe + date: !!python/object/apply:datetime.date [2017, 11, 29] + amount: !!python/object/apply:decimal.Decimal ["146.50"] + currency: USD + payment_count: !!python/object/apply:decimal.Decimal ["2"] + payment_gross: !!python/object/apply:decimal.Decimal ["150"] + payment_fees: !!python/object/apply:decimal.Decimal ["3.5"] + payment_net: !!python/object/apply:decimal.Decimal ["146.5"] + refund_count: !!python/object/apply:decimal.Decimal ["0"] + refund_gross: !!python/object/apply:decimal.Decimal ["0"] + refund_fees: !!python/object/apply:decimal.Decimal ["0"] + refund_net: !!python/object/apply:decimal.Decimal ["0"] + collected_fee_count: !!python/object/apply:decimal.Decimal ["0"] + collected_fee_gross: !!python/object/apply:decimal.Decimal ["0"] + collected_fee_refund_count: !!python/object/apply:decimal.Decimal ["0"] + collected_fee_refund_gross: !!python/object/apply:decimal.Decimal ["0"] + adjustment_count: !!python/object/apply:decimal.Decimal ["0"] + adjustment_gross: !!python/object/apply:decimal.Decimal ["0"] + adjustment_fees: !!python/object/apply:decimal.Decimal ["0"] + adjustment_net: !!python/object/apply:decimal.Decimal ["0"] + validation_count: !!python/object/apply:decimal.Decimal ["0"] + validation_fees: !!python/object/apply:decimal.Decimal ["0"] + retried_payout_count: !!python/object/apply:decimal.Decimal ["0"] + retried_payout_net: !!python/object/apply:decimal.Decimal ["0"] + total_count: !!python/object/apply:decimal.Decimal ["2"] + total_gross: !!python/object/apply:decimal.Decimal ["150"] + total_fees: !!python/object/apply:decimal.Decimal ["3.5"] + total_net: !!python/object/apply:decimal.Decimal ["146.5"] + payout_id: po_Do9pathoo9Pu8jaePhahJa0e + destination_id: ba_chu0Woop5queewi2Ea1Aibah + balance_txid: txn_ahsaixiene6Thie1aiti3tuo + failure_txid: "" + - source: nbpy2017a.html importer: nbpy2017.InvoiceImporter expect: