sort.py (3433B) - raw


      1 from utils.read_file import entry
      2 from typing import List
      3 from utils.register import complete_prices
      4 
      5 
      6 def separate_currencies(my_entries: List[entry]):
      7     """
      8     Given a list of entries with just one transaction, group entries with
      9     respect to their currencies symbols.
     10     """
     11     seen_curr = set()
     12     list_curr = []
     13 
     14     # First search for every currency we can find in `my_entries`.
     15     for ent in my_entries:
     16         for trans in ent.transactions:
     17             wallet = trans[1]
     18 
     19             if len(wallet.money.keys()) != 1:
     20                 raise Exception('Cannot compare more than one currency at a time.')
     21 
     22             for curr in wallet.money.keys():
     23                 break
     24 
     25             if curr not in seen_curr:
     26                 seen_curr.add(curr)
     27                 list_curr.append(curr)
     28 
     29     # Now group each currency. Select a currency and append entries that have
     30     # that specific currency. Then select the next seen currency and so on.
     31     result = []
     32     for my_currency in list_curr:
     33         for ent in my_entries:
     34             wallet = ent.transactions[0][1]
     35 
     36             for curr in wallet.money.keys():
     37                 break
     38 
     39             if my_currency == curr:
     40                 result.append(ent)
     41 
     42     return result
     43 
     44 
     45 def join_concurrent_entries(my_entries: List[entry]):
     46     result = []
     47     for ent in my_entries:
     48         if len(result) == 0:
     49             result.append(ent)
     50 
     51         elif ent.comment == result[-1].comment and ent.date == result[-1].date:
     52             result[-1].transactions.append(
     53                 ent.transactions[0]
     54             )
     55 
     56         else:
     57             result.append(ent)
     58 
     59     return result
     60 
     61 
     62 def sort_by_date(my_entries: List[entry]):
     63     my_entries.sort(key=lambda x: x.date)
     64 
     65 
     66 def sort_by_amount(my_entries: List[entry]):
     67     """
     68     We have to break entries by their transactions. Then we can sort the
     69     entries by their amount in their unique transaction.
     70     """
     71 
     72     # Break entries for them to have only one transaction.
     73     result = []
     74     for ent in my_entries:
     75         complete_prices(ent)
     76 
     77         for trans in ent.transactions:
     78             result.append(
     79                 entry(
     80                     date=ent.date.strftime('%Y/%m/%d'),
     81                     comment=ent.comment,
     82                     transactions=[trans]
     83                 )
     84             )
     85     # Sort each transaction given the amount value.
     86     result.sort(key=lambda x: x.transactions[0][1])
     87     # Separate different currencies from each other.
     88     result = separate_currencies(result)
     89     # Join concurrent entries if they have the same comment and date.
     90     result = join_concurrent_entries(result)
     91 
     92     # Hacky way of modifying the original `my_entries` list.
     93     while my_entries:
     94         my_entries.pop()
     95     for item in result:
     96         my_entries.append(item)
     97 
     98     # Each transaction now has the `currencies` class format. Convert all of
     99     # them into strings.
    100     for ent in my_entries:
    101         for trans in ent.transactions:
    102             for price in trans[1]:
    103                 break
    104 
    105             trans[1] = price
    106 
    107 
    108 def sort_entries(my_entries: List[entry], rule: str) -> None:
    109     """
    110     Sort the list of entries in-place. This function returns None, the list
    111     given as a parameter will be modified.
    112     """
    113     # Sort by date.
    114     if rule.lower() in ['d', 'date']:
    115         sort_by_date(my_entries)
    116     # Sort by amount.
    117     if rule.lower() in ['a', 'amount']:
    118         sort_by_amount(my_entries)