Beispiel #1
0
 def test_group_entries_by_link(self):
     entries, _, __ = loader.load_string(self.test_doc)
     entries = [entry._replace(meta=None, postings=None)
                for entry in entries
                if isinstance(entry, data.Transaction)]
     link_groups = basicops.group_entries_by_link(entries)
     date = datetime.date(2014, 5, 10)
     self.assertEqual(
         {'apple': [
             data.Transaction(None, date, '*', None, 'B', None, {'apple'}, None),
             data.Transaction(None, date, '*', None, 'D', None, {'apple', 'banana'},
                              None)],
          'banana': [
              data.Transaction(None, date, '*', None, 'C', None, {'banana'}, None),
              data.Transaction(None, date, '*', None, 'D', None, {'apple', 'banana'},
                               None)]},
         link_groups)
Beispiel #2
0
def tag_pending_transactions(entries, tag_name='PENDING'):
    """Filter out incomplete linked transactions to a transfer account.

    Given a list of entries, group the entries by their link and compute the
    balance of the intersection of their common accounts. If the balance does
    not sum to zero, insert a 'tag_name' tag in the entries.

    Args:
      entries: A list of directives/transactions to process.
      tag_name: A string, the name of the tag to be inserted if a linked group
        of entries is found not to match
    Returns:
      A modified set of entries, possibly tagged as pending.

    """
    link_groups = basicops.group_entries_by_link(entries)

    pending_entry_ids = set()
    for link, link_entries in link_groups.items():
        assert link_entries
        if len(link_entries) == 1:
            # If a single entry is present, it is assumed incomplete.
            pending_entry_ids.add(id(link_entries[0]))
        else:
            # Compute the sum total balance of the common accounts.
            common_accounts = basicops.get_common_accounts(link_entries)
            common_balance = inventory.Inventory()
            for entry in link_entries:
                for posting in entry.postings:
                    if posting.account in common_accounts:
                        common_balance.add_position(posting.position)

            # Mark entries as pending if a residual balance is found.
            if not common_balance.is_empty():
                for entry in link_entries:
                    pending_entry_ids.add(id(entry))

    # Insert tags if marked.
    return [(entry._replace(
        tags=(entry.tags or set())
        | set((tag_name, ))) if id(entry) in pending_entry_ids else entry)
            for entry in entries]