commit 03304074913aaf5cfc05de8ffc00f66823896e50
parent 4875c36a055ea89118e665bdd8b3d0148b112307
Author: Adrián Oliva <[email protected]>
Date: Sun, 7 May 2023 00:17:58 -0600
First attempt at sorting.
We can only sort by date and amount right now. I don't know if there are
other important ways of sorting. D:
Diffstat:
M | ledger.py | | | 4 | ++++ |
A | utils/sort.py | | | 119 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 123 insertions(+), 0 deletions(-)
diff --git a/ledger.py b/ledger.py
@@ -2,6 +2,7 @@
from utils.args import get_arguments, test_args
from utils.read_file import read_ledger
from utils.register import print_register
+from utils.sort import sort_entries
def main():
args = get_arguments()
@@ -12,6 +13,9 @@ def main():
for file in args.files:
result += read_ledger(file)
+ if args.sort:
+ sort_entries(result, args.sort)
+
if args.verb == 'print':
for ent in result:
print(ent)
diff --git a/utils/sort.py b/utils/sort.py
@@ -0,0 +1,118 @@
+from utils.read_file import entry
+from typing import List
+from utils.register import complete_prices
+
+
+def separate_currencies(my_entries: List[entry]):
+ """
+ Given a list of entries with just one transaction, group entries with
+ respect to their currencies symbols.
+ """
+ seen_curr = set()
+ list_curr = []
+
+ # First search for every currency we can find in `my_entries`.
+ for ent in my_entries:
+ for trans in ent.transactions:
+ wallet = trans[1]
+
+ if len(wallet.money.keys()) != 1:
+ raise Exception('Cannot compare more than one currency at a time.')
+
+ for curr in wallet.money.keys():
+ break
+
+ if curr not in seen_curr:
+ seen_curr.add(curr)
+ list_curr.append(curr)
+
+ # Now group each currency. Select a currency and append entries that have
+ # that specific currency. Then select the next seen currency and so on.
+ result = []
+ for my_currency in list_curr:
+ for ent in my_entries:
+ wallet = ent.transactions[0][1]
+
+ for curr in wallet.money.keys():
+ break
+
+ if my_currency == curr:
+ result.append(ent)
+
+ return result
+
+
+def join_concurrent_entries(my_entries: List[entry]):
+ result = []
+ for ent in my_entries:
+ if len(result) == 0:
+ result.append(ent)
+
+ elif ent.comment == result[-1].comment and ent.date == result[-1].date:
+ result[-1].transactions.append(
+ ent.transactions[0]
+ )
+
+ else:
+ result.append(ent)
+
+ return result
+
+
+def sort_by_date(my_entries: List[entry]):
+ my_entries.sort(key=lambda x: x.date)
+
+
+def sort_by_amount(my_entries: List[entry]):
+ """
+ We have to break entries by their transactions. Then we can sort the
+ entries by their amount in their unique transaction.
+ """
+
+ # Break entries for them to have only one transaction.
+ result = []
+ for ent in my_entries:
+ complete_prices(ent)
+
+ for trans in ent.transactions:
+ result.append(
+ entry(
+ date=ent.date.strftime('%Y/%m/%d'),
+ comment=ent.comment,
+ transactions=[trans]
+ )
+ )
+ # Sort each transaction given the amount value.
+ result.sort(key=lambda x: x.transactions[0][1])
+ # Separate different currencies from each other.
+ result = separate_currencies(result)
+ # Join concurrent entries if they have the same comment and date.
+ result = join_concurrent_entries(result)
+
+ # Hacky way of modifying the original `my_entries` list.
+ while my_entries:
+ my_entries.pop()
+ for item in result:
+ my_entries.append(item)
+
+ # Each transaction now has the `currencies` class format. Convert all of
+ # them into strings.
+ for ent in my_entries:
+ for trans in ent.transactions:
+ for price in trans[1]:
+ break
+
+ trans[1] = price
+
+
+def sort_entries(my_entries: List[entry], rule: str) -> None:
+ """
+ Sort the list of entries in-place. This function returns None, the list
+ given as a parameter will be modified.
+ """
+ # Sort by date.
+ if rule.lower() in ['d', 'date']:
+ sort_by_date(my_entries)
+ # Sort by amount.
+ if rule.lower() in ['a', 'amount']:
+ sort_by_amount(my_entries)
+\ No newline at end of file