Compare commits
No commits in common. "111b1fdf30565575856008e575da4f4284cb7e3f" and "579f6dde4bfe8f0d57a31b7d5d7deb9dc76d37a9" have entirely different histories.
111b1fdf30
...
579f6dde4b
15 changed files with 501 additions and 500 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
import datetime
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
from . import _csv
|
from . import _csv
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,30 @@
|
||||||
import datetime
|
import decimal
|
||||||
|
|
||||||
from . import _csv
|
from . import _csv
|
||||||
from .. import strparse
|
from .. import strparse
|
||||||
|
|
||||||
|
|
||||||
class SalesImporter(_csv.CSVImporterBase):
|
class SalesImporter(_csv.CSVImporterBase):
|
||||||
DECIMAL_FIELDS = {
|
DECIMAL_FIELDS = {
|
||||||
'Eventbrite service fee': 'service_fee',
|
'Eventbrite Fees': 'eventbrite_fees',
|
||||||
'Eventbrite payment processing fee': 'payment_processing_fee',
|
'Eventbrite Payment Processing': 'payment_fees',
|
||||||
'Ticket quantity': 'ticket_quantity',
|
'Fees Paid': 'total_fees',
|
||||||
'Eventbrite tax': 'eventbrite_tax',
|
'Quantity': 'quantity',
|
||||||
'Organizer tax': 'organizer_tax',
|
'Tax Paid': 'tax',
|
||||||
'Gross sales': 'amount',
|
'Total Paid': 'amount',
|
||||||
}
|
}
|
||||||
NEEDED_FIELDS = frozenset([
|
NEEDED_FIELDS = frozenset([
|
||||||
'Order date',
|
'Order Date',
|
||||||
'Payment status',
|
'Order Type',
|
||||||
*DECIMAL_FIELDS,
|
*DECIMAL_FIELDS,
|
||||||
])
|
])
|
||||||
OPTIONAL_FIELDS = {
|
OPTIONAL_FIELDS = {
|
||||||
|
'Attendee #': 'attendee_id',
|
||||||
|
'Company': 'corporation',
|
||||||
'Currency': 'currency',
|
'Currency': 'currency',
|
||||||
'Event ID': 'event_id',
|
'Event ID': 'event_id',
|
||||||
'Event name': 'event_name',
|
'Event Name': 'event_name',
|
||||||
'Order ID': 'order_id',
|
'Order #': 'order_id',
|
||||||
|
'Ticket Type': 'ticket_type',
|
||||||
}
|
}
|
||||||
ENTRY_SEED = {'currency': 'USD'}
|
ENTRY_SEED = {'currency': 'USD'}
|
||||||
|
|
||||||
|
|
@ -34,9 +36,12 @@ class SalesImporter(_csv.CSVImporterBase):
|
||||||
self.DECIMAL_FIELDS[key]: strparse.currency_decimal(row[key])
|
self.DECIMAL_FIELDS[key]: strparse.currency_decimal(row[key])
|
||||||
for key in self.DECIMAL_FIELDS
|
for key in self.DECIMAL_FIELDS
|
||||||
}
|
}
|
||||||
retval['date'] = datetime.datetime.fromisoformat(row['Order date']).date()
|
date_s, _, _ = row['Order Date'].partition(' ')
|
||||||
retval['payee'] = '{Buyer first name} {Buyer last name}'.format_map(row)
|
retval['date'] = strparse.date(date_s, '%Y-%m-%d')
|
||||||
retval['total_fees'] = retval['service_fee'] + retval['payment_processing_fee']
|
try:
|
||||||
|
retval['payee'] = '{Buyer First Name} {Buyer Last Name}'.format_map(row)
|
||||||
|
except KeyError:
|
||||||
|
retval['payee'] = '{First Name} {Last Name}'.format_map(row)
|
||||||
retval.update(
|
retval.update(
|
||||||
(self.OPTIONAL_FIELDS[key], row.get(key, ''))
|
(self.OPTIONAL_FIELDS[key], row.get(key, ''))
|
||||||
for key in self.OPTIONAL_FIELDS
|
for key in self.OPTIONAL_FIELDS
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import decimal
|
||||||
|
|
||||||
from . import _csv
|
from . import _csv
|
||||||
from .. import strparse
|
from .. import strparse
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ class Invoice2017:
|
||||||
for key, value in rows_text:
|
for key, value in rows_text:
|
||||||
if key == 'Issue date':
|
if key == 'Issue date':
|
||||||
self.invoice_date = self._strpdate(value)
|
self.invoice_date = self._strpdate(value)
|
||||||
recipient_h = table.find('th', string='Recipient')
|
recipient_h = table.find('th', text='Recipient')
|
||||||
recipient_cell = recipient_h.find_next_sibling('td')
|
recipient_cell = recipient_h.find_next_sibling('td')
|
||||||
self.payee = next(recipient_cell.stripped_strings)
|
self.payee = next(recipient_cell.stripped_strings)
|
||||||
|
|
||||||
|
|
@ -139,7 +139,6 @@ def _parse_invoice(parser_class, source_file):
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class InvoiceImporter:
|
class InvoiceImporter:
|
||||||
INVOICE_CLASS = Invoice2017
|
INVOICE_CLASS = Invoice2017
|
||||||
LEDGER_TEMPLATE_KEY_FMT = 'nbpy2017 {0} ledger entry'
|
LEDGER_TEMPLATE_KEY_FMT = 'nbpy2017 {0} ledger entry'
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,7 @@ class VATImporter(FeeImporterBase):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Income2020OctoberImporter(IncomeImporter):
|
class Income2020OctoberImporter(IncomeImporter):
|
||||||
AMOUNT_KEY = 'Pledge $'
|
AMOUNT_KEY = 'Pledge $'
|
||||||
|
|
||||||
|
|
|
||||||
2
setup.py
2
setup.py
|
|
@ -30,7 +30,7 @@ REQUIREMENTS['tests_require'] = [
|
||||||
setup(
|
setup(
|
||||||
name='import2ledger',
|
name='import2ledger',
|
||||||
description="Import different sources of financial data to Ledger",
|
description="Import different sources of financial data to Ledger",
|
||||||
version='1.4.6',
|
version='1.4.5',
|
||||||
author='Brett Smith',
|
author='Brett Smith',
|
||||||
author_email='brettcsmith@brettcsmith.org',
|
author_email='brettcsmith@brettcsmith.org',
|
||||||
license='GNU AGPLv3+',
|
license='GNU AGPLv3+',
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
Created,Disbursement ID,Donor Name,Fund,Amount,Designation,On Behalf Of,Donor Email,Company Name,Type
|
Date,Disbursement ID,Name,Fund,Amount,Designation,On Behalf Of,Email,Company Name,Donation Type
|
||||||
10/01/2020,123456,Company ,,15,,Employed Person,,Company,MatchingTransaction
|
10/01/20,123456,Company ,,15,,Employed Person,,Company,MatchingTransaction
|
||||||
09/24/2020,123456,Employed Person ,,15,,-,person@example.com,Company,CreditCardTransaction
|
09/24/20,123456,Employed Person ,,15,,-,person@example.com,Company,CreditCardTransaction
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
sponsor handle,sponsor email,sponsorship started on,is public?,is yearly?,stripe transfer id,tier name,tier monthly amount,transferred amount,is prorated?,status,transaction timestamp
|
sponsor handle,sponsor email,sponsorship started on,is public?,is yearly?,transaction id,tier name,tier monthly amount,processed amount,is prorated?,status,transaction date
|
||||||
exampleA,ajones@example.com,2019-10-01 10:00:00 -0400,TRUE,FALSE,ch_1Gabcdefghijklmnopqrstuv,$1/month,$1.00,$1.00,FALSE,settled,2020-01-02 14:02:00 -0500
|
exampleA,ajones@example.com,2019-10-01 10:00:00 -0400,TRUE,FALSE,ch_1Gabcdefghijklmnopqrstuv,$1/month,$1.00,$1.00,FALSE,settled,2020-01-02 14:02:00 -0500
|
||||||
exampleB,,2019-11-01 11:00:00 -0400,FALSE,FALSE,1023ABCD5678EFGHI,$10/month,$10.00,$10.00,FALSE,settled,2020-01-03 15:03:00 -0500
|
exampleB,,2019-11-01 11:00:00 -0400,FALSE,FALSE,1023ABCD5678EFGHI,$10/month,$10.00,$10.00,FALSE,settled,2020-01-03 15:03:00 -0500
|
||||||
exampleC,info@example.com,2019-12-01 12:00:00 -0500,TRUE,TRUE,ch_1Gabcdefghijklmnopqrstuw,$10/month,$10.00,$120.00,FALSE,settled,2020-01-04 16:04:00 -0500
|
exampleC,info@example.com,2019-12-01 12:00:00 -0500,TRUE,TRUE,ch_1Gabcdefghijklmnopqrstuw,$10/month,$10.00,$120.00,FALSE,settled,2020-01-04 16:04:00 -0500
|
||||||
|
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
id,Description,Created (UTC),Amount,Amount Refunded,Currency,Converted Amount,Converted Amount Refunded,Fee,Taxes On Fee,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
|
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,0,American Express,credit,1,2010,Dakota Smith,1 Example St,,City,State,United States,12345,US,queiheVu2ohyei2u,pass,pass,pass,,,,,,,,card,,po_aeYees2ahtier8ohju7Eeyie,
|
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,0,American Express,credit,1,2010,Dakota Smith,1 Example St,,City,State,United States,12345,US,queiheVu2ohyei2u,pass,pass,pass,,,,,,,,card,,po_aeYees2ahtier8ohju7Eeyie,
|
||||||
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,1,Visa,credit,2,2011,Dakota Jones,2 Example St,,City,State,United States,12345,US,men2shi3xo1Mao4u,pass,pass,pass,,,,,,,,card,,po_aeYees2ahtier8ohju7Eeyie,
|
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,1,Visa,credit,2,2011,Dakota Jones,2 Example St,,City,State,United States,12345,US,men2shi3xo1Mao4u,pass,pass,pass,,,,,,,,card,,po_aeYees2ahtier8ohju7Eeyie,
|
||||||
|
|
|
||||||
|
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
date_format = %%Y-%%m-%%d
|
date_format = %%Y-%%m-%%d
|
||||||
signed_currencies = CAD
|
signed_currencies = USD, CAD
|
||||||
signed_currency_format = ¤#,##0.###
|
signed_currency_format = ¤#,##0.###
|
||||||
unsigned_currency_format = #,##0.### ¤¤
|
unsigned_currency_format = #,##0.### ¤¤
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
default_date = 2016/04/04
|
default_date = 2016/04/04
|
||||||
loglevel = critical
|
loglevel = critical
|
||||||
signed_currencies =
|
signed_currencies = USD
|
||||||
|
|
||||||
[One]
|
[One]
|
||||||
patreon cardfees ledger entry =
|
patreon cardfees ledger entry =
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
2017/09/01 Patreon
|
2017/09/01 Patreon
|
||||||
Accrued:Accounts Receivable -52.47 USD
|
Accrued:Accounts Receivable $-52.47
|
||||||
Expenses:Fees:Credit Card 52.47 USD
|
Expenses:Fees:Credit Card $52.47
|
||||||
|
|
||||||
2017/10/01 Patreon
|
2017/10/01 Patreon
|
||||||
Accrued:Accounts Receivable -99.47 USD
|
Accrued:Accounts Receivable $-99.47
|
||||||
Expenses:Fees:Credit Card 99.47 USD
|
Expenses:Fees:Credit Card $99.47
|
||||||
|
|
||||||
2017/09/01 Patreon
|
2017/09/01 Patreon
|
||||||
;SourcePath: {source_abspath}
|
;SourcePath: {source_abspath}
|
||||||
;SourceName: {source_name}
|
;SourceName: {source_name}
|
||||||
Accrued:Accounts Receivable -61.73 USD
|
Accrued:Accounts Receivable $-61.73
|
||||||
Expenses:Fundraising 61.73 USD
|
Expenses:Fundraising $61.73
|
||||||
|
|
||||||
2017/10/01 Patreon
|
2017/10/01 Patreon
|
||||||
;SourcePath: {source_abspath}
|
;SourcePath: {source_abspath}
|
||||||
;SourceName: {source_name}
|
;SourceName: {source_name}
|
||||||
Accrued:Accounts Receivable -117.03 USD
|
Accrued:Accounts Receivable $-117.03
|
||||||
Expenses:Fundraising 117.03 USD
|
Expenses:Fundraising $117.03
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ def test_date_formatting():
|
||||||
|
|
||||||
def test_currency_formatting():
|
def test_currency_formatting():
|
||||||
tmpl = template_from('Simplest', signed_currencies=['USD'])
|
tmpl = template_from('Simplest', signed_currencies=['USD'])
|
||||||
assert_easy_render(tmpl, 'CC', '7.99', 'USD', '2015/03/14', 'USD7.99')
|
assert_easy_render(tmpl, 'CC', '7.99', 'USD', '2015/03/14', '$7.99')
|
||||||
|
|
||||||
def test_empty_template():
|
def test_empty_template():
|
||||||
tmpl = ledger_entry.Template("\n \n")
|
tmpl = ledger_entry.Template("\n \n")
|
||||||
|
|
@ -76,18 +76,19 @@ def test_complex_template():
|
||||||
lines = render_lines(
|
lines = render_lines(
|
||||||
render_vars, 'Complex',
|
render_vars, 'Complex',
|
||||||
date_fmt='%Y-%m-%d',
|
date_fmt='%Y-%m-%d',
|
||||||
|
signed_currencies=['USD'],
|
||||||
)
|
)
|
||||||
assert lines == [
|
assert lines == [
|
||||||
"",
|
"",
|
||||||
"2015-03-14 TT",
|
"2015-03-14 TT",
|
||||||
" ;Tag: Value",
|
" ;Tag: Value",
|
||||||
" ;TransactionID: ABCDEF",
|
" ;TransactionID: ABCDEF",
|
||||||
" Accrued:Accounts Receivable 125.50 USD",
|
" Accrued:Accounts Receivable $125.50",
|
||||||
" ;Entity: Supplier",
|
" ;Entity: Supplier",
|
||||||
" Income:Donations:Spectrum Defense -119.85 USD",
|
" Income:Donations:Spectrum Defense $-119.85",
|
||||||
" ;Program: Spectrum Defense",
|
" ;Program: Spectrum Defense",
|
||||||
" ;Entity: T-T",
|
" ;Entity: T-T",
|
||||||
" Income:Donations:General -5.65 USD",
|
" Income:Donations:General $-5.65",
|
||||||
" ;Entity: T-T",
|
" ;Entity: T-T",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -107,18 +108,19 @@ def test_variable_whitespace_cleaned():
|
||||||
lines = render_lines(
|
lines = render_lines(
|
||||||
render_vars, 'Complex',
|
render_vars, 'Complex',
|
||||||
date_fmt='%Y-%m-%d',
|
date_fmt='%Y-%m-%d',
|
||||||
|
signed_currencies=['USD'],
|
||||||
)
|
)
|
||||||
assert lines == [
|
assert lines == [
|
||||||
"",
|
"",
|
||||||
"2015-03-14 W S",
|
"2015-03-14 W S",
|
||||||
" ;Tag: Value",
|
" ;Tag: Value",
|
||||||
" ;TransactionID: ABC DEF",
|
" ;TransactionID: ABC DEF",
|
||||||
" Accrued:Accounts Receivable 125.50 USD",
|
" Accrued:Accounts Receivable $125.50",
|
||||||
" ;Entity: Supplier",
|
" ;Entity: Supplier",
|
||||||
" Income:Donations:Spectrum Defense -119.85 USD",
|
" Income:Donations:Spectrum Defense $-119.85",
|
||||||
" ;Program: Spectrum Defense",
|
" ;Program: Spectrum Defense",
|
||||||
" ;Entity: W S",
|
" ;Entity: W S",
|
||||||
" Income:Donations:General -5.65 USD",
|
" Income:Donations:General $-5.65",
|
||||||
" ;Entity: W S",
|
" ;Entity: W S",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -340,8 +342,8 @@ def test_hook_renders_template():
|
||||||
assert lines == [
|
assert lines == [
|
||||||
"",
|
"",
|
||||||
"2015-03-14 BB",
|
"2015-03-14 BB",
|
||||||
" Accrued:Accounts Receivable 0.99 USD",
|
" Accrued:Accounts Receivable $0.99",
|
||||||
" Income:Donations -0.99 USD",
|
" Income:Donations -$0.99",
|
||||||
]
|
]
|
||||||
|
|
||||||
def test_hook_handles_empty_template():
|
def test_hook_handles_empty_template():
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import importlib
|
||||||
import itertools
|
import itertools
|
||||||
import pathlib
|
import pathlib
|
||||||
import shutil
|
import shutil
|
||||||
|
import re
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import yaml
|
import yaml
|
||||||
|
|
@ -13,23 +14,14 @@ from import2ledger import importers, strparse
|
||||||
|
|
||||||
from . import DATA_DIR
|
from . import DATA_DIR
|
||||||
|
|
||||||
|
try:
|
||||||
def decimal_constructor(loader, node):
|
load_yaml = yaml.full_load
|
||||||
value = loader.construct_scalar(node)
|
except AttributeError:
|
||||||
return decimal.Decimal(value)
|
load_yaml = yaml.load
|
||||||
|
|
||||||
|
|
||||||
def date_constructor(loader, node):
|
|
||||||
value = loader.construct_scalar(node)
|
|
||||||
return datetime.date.fromisoformat(value)
|
|
||||||
|
|
||||||
|
|
||||||
class TestImporters:
|
class TestImporters:
|
||||||
Loader = yaml.Loader
|
|
||||||
Loader.add_constructor('!decimal', decimal_constructor)
|
|
||||||
Loader.add_constructor('!date', date_constructor)
|
|
||||||
with pathlib.Path(DATA_DIR, 'imports.yml').open() as yaml_file:
|
with pathlib.Path(DATA_DIR, 'imports.yml').open() as yaml_file:
|
||||||
test_data = yaml.load(yaml_file, Loader=Loader)
|
test_data = load_yaml(yaml_file)
|
||||||
for test in test_data:
|
for test in test_data:
|
||||||
test['source'] = DATA_DIR / test['source']
|
test['source'] = DATA_DIR / test['source']
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue