meta_entity: Use payee as entity when metadata not available. RT#10529.
This commit is contained in:
parent
bff3eec952
commit
0413fed8b9
4 changed files with 65 additions and 2 deletions
|
@ -185,6 +185,15 @@ class PostingMeta(Metadata):
|
|||
else:
|
||||
self.meta = collections.ChainMap(post.meta, txn.meta)
|
||||
|
||||
def __getitem__(self, key: MetaKey) -> MetaValue:
|
||||
try:
|
||||
return super().__getitem__(key)
|
||||
except KeyError:
|
||||
if key == 'entity' and self.txn.payee is not None:
|
||||
return self.txn.payee
|
||||
else:
|
||||
raise
|
||||
|
||||
def __setitem__(self, key: MetaKey, value: MetaValue) -> None:
|
||||
if self.post.meta is None:
|
||||
self.post = self.post._replace(meta={key: value})
|
||||
|
|
|
@ -49,7 +49,7 @@ class MetaEntity(core.TransactionHook):
|
|||
del alnum
|
||||
|
||||
def run(self, txn: Transaction) -> errormod.Iter:
|
||||
txn_entity = txn.meta.get(self.METADATA_KEY)
|
||||
txn_entity = txn.meta.get(self.METADATA_KEY, txn.payee)
|
||||
if txn_entity is None:
|
||||
txn_entity_ok = None
|
||||
elif isinstance(txn_entity, str):
|
||||
|
|
|
@ -21,13 +21,21 @@ from . import testutil
|
|||
from conservancy_beancount import data
|
||||
|
||||
@pytest.fixture
|
||||
def simple_txn(index=None, key=None):
|
||||
def simple_txn():
|
||||
return testutil.Transaction(note='txn note', postings=[
|
||||
('Assets:Cash', 5),
|
||||
('Income:Donations', -5, {'note': 'donation love', 'extra': 'Extra'}),
|
||||
])
|
||||
SIMPLE_TXN_METAKEYS = frozenset(['filename', 'lineno', 'note'])
|
||||
|
||||
@pytest.fixture
|
||||
def payee_txn():
|
||||
return testutil.Transaction(payee='SampleCo', postings=[
|
||||
('Assets:Receivable:Accounts', -100),
|
||||
('Assets:Checking', 95),
|
||||
('Expenses:BankingFees', 5, {'entity': 'MyBank'}),
|
||||
])
|
||||
|
||||
def test_getitem_transaction(simple_txn):
|
||||
assert data.PostingMeta(simple_txn, 0)['note'] == 'txn note'
|
||||
|
||||
|
@ -88,6 +96,22 @@ def test_get_links_from_post_override(simple_txn):
|
|||
meta = data.PostingMeta(simple_txn, 1)
|
||||
assert list(meta.get_links('note')) == ['donation', 'love']
|
||||
|
||||
def test_payee_used_as_entity(payee_txn):
|
||||
actual = [data.PostingMeta(payee_txn, n, p)['entity']
|
||||
for n, p in enumerate(payee_txn.postings)]
|
||||
assert actual == ['SampleCo', 'SampleCo', 'MyBank']
|
||||
|
||||
def test_entity_metadata_has_precedence_over_payee(payee_txn):
|
||||
payee_txn.meta['entity'] = 'ExampleCo'
|
||||
actual = [data.PostingMeta(payee_txn, n, p)['entity']
|
||||
for n, p in enumerate(payee_txn.postings)]
|
||||
assert actual == ['ExampleCo', 'ExampleCo', 'MyBank']
|
||||
|
||||
def test_keyerror_when_no_entity_or_payee(simple_txn):
|
||||
meta = data.PostingMeta(simple_txn, 1)
|
||||
with pytest.raises(KeyError):
|
||||
meta['entity']
|
||||
|
||||
# The .get() tests are arguably testing the stdlib, but they're short and
|
||||
# they confirm that we're using the stdlib as we intend.
|
||||
def test_get_with_meta_value(simple_txn):
|
||||
|
|
|
@ -110,6 +110,36 @@ def test_invalid_values_on_transactions(hook, src_value):
|
|||
assert all(error.message == "transaction has invalid entity: {}".format(src_value)
|
||||
for error in hook.run(txn))
|
||||
|
||||
@pytest.mark.parametrize('src_value', VALID_VALUES)
|
||||
def test_valid_values_on_payee(hook, src_value):
|
||||
txn = testutil.Transaction(payee=src_value, postings=[
|
||||
('Assets:Cash', -25),
|
||||
('Expenses:General', 25),
|
||||
])
|
||||
assert not any(hook.run(txn))
|
||||
|
||||
@pytest.mark.parametrize('src_value', INVALID_VALUES)
|
||||
def test_invalid_values_on_payee(hook, src_value):
|
||||
txn = testutil.Transaction(payee=src_value, postings=[
|
||||
('Assets:Cash', -25),
|
||||
('Expenses:General', 25),
|
||||
])
|
||||
errors = list(hook.run(txn))
|
||||
assert 1 <= len(errors) <= 2
|
||||
assert all(error.message == "transaction has invalid entity: {}".format(src_value)
|
||||
for error in hook.run(txn))
|
||||
|
||||
@pytest.mark.parametrize('payee,src_value', testutil.combine_values(
|
||||
INVALID_VALUES,
|
||||
VALID_VALUES,
|
||||
))
|
||||
def test_invalid_payee_but_valid_metadata(hook, payee, src_value):
|
||||
txn = testutil.Transaction(**{'payee': payee, TEST_KEY: src_value}, postings=[
|
||||
('Assets:Cash', -25),
|
||||
('Expenses:Other', 25),
|
||||
])
|
||||
assert not any(hook.run(txn))
|
||||
|
||||
@pytest.mark.parametrize('account,required', [
|
||||
('Assets:Bank:Checking', False),
|
||||
('Assets:Cash', False),
|
||||
|
|
Loading…
Reference in a new issue