Files @ d8f4eac53bb7
Branch filter:

Location: NPO-Accounting/conservancy_beancount/tests/test_reconcile.py - annotation

bsturmfels
reconcile: Improve reconciler matching and add test cases.
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
d8f4eac53bb7
import datetime
import decimal

from conservancy_beancount.reconcile.prototype_amex_reconciler import match_statement_and_books2 as match_statement_and_books, remove_payee_junk, date_proximity

S1 = {
    'date': datetime.date(2022, 1, 1),
    'amount': decimal.Decimal('10.00'),
    'payee': 'Patreon         / Patreon   / 123456/ ST-A1B2C3D4G5H6       /',
    'line': 222,
}
S2 = {
    'date': datetime.date(2022, 1, 2),
    'amount': decimal.Decimal('20.00'),
    'payee': 'BT*LINODE           PHILADELPHIA        P',
    'line': 333,
}
S3 = {
    'date': datetime.date(2022, 1, 3),
    'amount': decimal.Decimal('30.00'),
    'payee': 'USPS PO 4067540039 0PORTLAND            OR',
    'line': 444,
}

B1 = {
    'date': datetime.date(2022, 1, 1),
    'amount': decimal.Decimal('10.00'),
    'payee': 'Patreon',
    'entity': '',
    'check_id': None,
    'filename': '2022/imports.beancount',
    'line': 777,
    'bank_statement': "Financial/Bank-Statements/AMEX/2022-01-12_AMEX_statement.pdf"
}
B2 = {
    'date': datetime.date(2022, 1, 2),
    'amount': decimal.Decimal('20.00'),
    'payee': 'Linode',
    'entity': '',
    'check_id': None,
    'filename': '2022/main.beancount',
    'line': 888,
    'bank_statement': "Financial/Bank-Statements/AMEX/2022-01-12_AMEX_statement.pdf"
}
B3_next_day = {
    'date': datetime.date(2022, 1, 4),
    'amount': decimal.Decimal('30.00'),
    'payee': 'USPS',
    'entity': '',
    'check_id': None,
    'filename': '2022/main.beancount',
    'line': 999,
    'bank_statement': "Financial/Bank-Statements/AMEX/2022-01-12_AMEX_statement.pdf"
}
B3_next_week = {
    'date': datetime.date(2022, 1, 10),
    'amount': decimal.Decimal('30.00'),
    'payee': 'USPS',
    'entity': '',
    'check_id': None,
    'filename': '2022/main.beancount',
    'line': 999,
    'bank_statement': "Financial/Bank-Statements/AMEX/2022-01-12_AMEX_statement.pdf"
}
B3_mismatch_amount = {
    'date': datetime.date(2022, 1, 3),
    'amount': decimal.Decimal('31.00'),
    'payee': 'USPS',
    'entity': '',
    'check_id': None,
    'filename': '2022/main.beancount',
    'line': 999,
    'bank_statement': "Financial/Bank-Statements/AMEX/2022-01-12_AMEX_statement.pdf"
}
B3_payee_mismatch_1 = {
    'date': datetime.date(2022, 1, 3),
    'amount': decimal.Decimal('30.00'),
    'payee': 'Credit X',
    'entity': '',
    'check_id': None,
    'filename': '2022/main.beancount',
    'line': 999,
    'bank_statement': "Financial/Bank-Statements/AMEX/2022-01-12_AMEX_statement.pdf"
}
B3_payee_mismatch_2 = {
    'date': datetime.date(2022, 1, 3),
    'amount': decimal.Decimal('30.00'),
    'payee': 'Credit Y',
    'entity': '',
    'check_id': None,
    'filename': '2022/main.beancount',
    'line': 999,
    'bank_statement': "Financial/Bank-Statements/AMEX/2022-01-12_AMEX_statement.pdf"
}


def test_one_exact_match():
    statement = [S1]
    books = [B1]
    assert match_statement_and_books(statement, books) == [
        ([S1], [B1], []),
    ]

def test_multiple_exact_matches():
    statement = [S1, S2]
    books = [B1, B2]
    assert match_statement_and_books(statement, books) == [
        ([S1], [B1], []),
        ([S2], [B2], []),
    ]

def test_one_mismatch():
    statement = [S1]
    books = []
    assert match_statement_and_books(statement, books) == [
        ([S1], [], ['no match']),
    ]

def test_multiple_mismatches():
    statement = [S1]
    books = [B2]
    assert match_statement_and_books(statement, books) == [
        ([S1], [], ['no match']),
        ([], [B2], ['no match']),
    ]

def test_next_day_matches():
    statement = [S3]
    books = [B3_next_day]
    assert match_statement_and_books(statement, books) == [
        ([S3], [B3_next_day], ['+/- 1 days']),
    ]

def test_next_week_matches():
    statement = [S3]
    books = [B3_next_week]
    assert match_statement_and_books(statement, books) == [
        ([S3], [B3_next_week], ['+/- 7 days']),
    ]

def test_incorrect_amount_does_not_match():
    statement = [S3]
    books = [B3_mismatch_amount]
    assert match_statement_and_books(statement, books) == [
        ([S3], [], ['no match']),
        ([], [B3_mismatch_amount], ['no match']),
    ]

def test_payee_mismatch_ok_when_only_one_that_amount_and_date():
    statement = [S3]
    books = [B3_payee_mismatch_1]
    assert match_statement_and_books(statement, books) == [
        ([S3], [B3_payee_mismatch_1], ['payee mismatch', 'only one decent match']),
    ]

def test_payee_mismatch_not_ok_when_multiple_that_amount_and_date():
    statement = [S3]
    books = [B3_payee_mismatch_1, B3_payee_mismatch_2]
    match = match_statement_and_books(statement, books)
    assert match == [
        ([S3], [], ['no match']),
        ([], [B3_payee_mismatch_1], ['no match']),
        ([], [B3_payee_mismatch_2], ['no match']),
    ]

# def test_subset_sum_with_same_date_and_payee():

def test_remove_payee_junk():
    assert remove_payee_junk('WIDGETSRUS INC PAYMENT 1') == 'WIDGETSRUS'
    assert remove_payee_junk('0000010017') == '10017'

def test_date_proximity():
    assert date_proximity(datetime.date(2021, 8, 23), datetime.date(2021, 8, 23)) == 1.0
    assert date_proximity(datetime.date(2021, 8, 23), datetime.date(2021, 8, 23) - datetime.timedelta(days=30)) == 0.5
    assert date_proximity(datetime.date(2021, 8, 23), datetime.date(2021, 8, 23) - datetime.timedelta(days=60)) == 0.0