From 5c541fc03efe3b79202fcfa2cb7097ba958e39b3 Mon Sep 17 00:00:00 2001 From: Xevion Date: Wed, 24 Jul 2019 19:22:43 -0500 Subject: [PATCH] ledger exercise --- python/ledger/ledger.py | 280 ++++++---------------------------------- 1 file changed, 41 insertions(+), 239 deletions(-) diff --git a/python/ledger/ledger.py b/python/ledger/ledger.py index 14deeed..ae31bdb 100644 --- a/python/ledger/ledger.py +++ b/python/ledger/ledger.py @@ -1,262 +1,64 @@ -# -*- coding: utf-8 -*- from datetime import datetime +# Currency formatters +def ENUS_(v, c): v /= 100.0; return ('(' if v < 0 else ' ') + c + format(abs(v), ',.2f') + (')' if v < 0 else ' ') +def NLNL_(v, c): v /= 100.0; return c + (' -' if v < 0 else ' ') + format(abs(v), ',.2f').translate(str.maketrans(',.', '.,')) + ' ' -class LedgerEntry(object): - def __init__(self, date, description, change): - self.date, self.description, self.change = date, description, change +# Date formatters (could be made intro a format creator which is called in locales dict) +def MDY_(date): return "{}/{}/{}".format(str(date.month).zfill(2), str(date.day).zfill(2), str(date.year).zfill(4)) +def DMY_(date): return "{}-{}-{}".format(str(date.day).zfill(2), str(date.month).zfill(2), str(date.year).zfill(4)) locales = { 'en_US' : { 'date' : 'Date', 'desc' : 'Description', - 'change' : 'Change' + 'change' : 'Change', + 'date_formatter' : MDY_, + 'currency_formatter' : ENUS_ }, 'nl_NL' : { 'date' : 'Datum', 'desc' : 'Omschrijving', - 'change' : 'Verandering' - } + 'change' : 'Verandering', + 'date_formatter' : DMY_, + 'currency_formatter' : NLNL_ + }, } -currencies = { +locales_currency = { 'USD' : '$', - 'EUR' : '€' + 'EUR' : u'€' } +class LedgerEntry(object): + def __init__(self, date, description, change): + self.date, self.description, self.change = date, description, change + def create_entry(date, description, change): return LedgerEntry(datetime.strptime(date, '%Y-%m-%d'), description, change) def format_entries(currency, locale, entries): - if locale == 'en_US': - # Generate Header Row - table = ' | '.join([locales[locale]['date'].ljust(10), locales[locale]['desc'].ljust(25), locales[locale]['change'].ljust(13)]) - - entries.sort(key=lambda item : (item.date, item.change)) - - while len(entries) > 0: - table += '\n' - entry = entries.pop(0) + table = [] - date_str = "{}/{}/{}".format(str(entry.date.month).zfill(2), str(entry.date.day).zfill(2), str(entry.date.year).zfill(4)) - table += date_str + ' | ' + # Table header. + table.append(' | '.join([ + locales[locale]['date'].ljust(10), + locales[locale]['desc'].ljust(25), + locales[locale]['change'].ljust(13)] + )) + + # Sort entries to ring out by date, then by change amount + entries.sort(key=lambda item : (item.date, item.change)) + + # Process all entries given + for entry in entries: + # Using the locale given, get it's date formatter + date = locales[locale]['date_formatter'](entry.date) + # Truncate description + description = (entry.description[:22] + '...' if len(entry.description) > 25 else entry.description).ljust(25) + # Using the locale and currency given, get the currency formatter and justify + change = locales[locale]['currency_formatter'](entry.change, locales_currency[currency]).rjust(13) + # Write entry change to table + table.append(' | '.join([date, description, change])) - # Write entry description to table - # Truncate if necessary - table += (entry.description[:22] + '...' if len(entry.description) > 25 else entry.description).ljust(25) - table += ' | ' - - # Write entry change to table - if currency == 'USD': - change_str = '' - if entry.change < 0: - change_str = '(' - change_str += '$' - change_dollar = abs(int(entry.change / 100.0)) - - dollar_parts = [] - while change_dollar > 0: - dollar_parts.insert(0, str(change_dollar % 1000)) - change_dollar = change_dollar // 1000 - if len(dollar_parts) == 0: - change_str += '0' - else: - while True: - change_str += dollar_parts[0] - dollar_parts.pop(0) - if len(dollar_parts) == 0: - break - change_str += ',' - change_str += '.' - change_cents = abs(entry.change) % 100 - change_cents = str(change_cents) - if len(change_cents) < 2: - change_cents = '0' + change_cents - change_str += change_cents - if entry.change < 0: - change_str += ')' - else: - change_str += ' ' - while len(change_str) < 13: - change_str = ' ' + change_str - table += change_str - elif currency == 'EUR': - change_str = '' - if entry.change < 0: - change_str = '(' - change_str += u'€' - change_euro = abs(int(entry.change / 100.0)) - euro_parts = [] - while change_euro > 0: - euro_parts.insert(0, str(change_euro % 1000)) - change_euro = change_euro // 1000 - if len(euro_parts) == 0: - change_str += '0' - else: - while True: - change_str += euro_parts[0] - euro_parts.pop(0) - if len(euro_parts) == 0: - break - change_str += ',' - change_str += '.' - change_cents = abs(entry.change) % 100 - change_cents = str(change_cents) - if len(change_cents) < 2: - change_cents = '0' + change_cents - change_str += change_cents - if entry.change < 0: - change_str += ')' - else: - change_str += ' ' - while len(change_str) < 13: - change_str = ' ' + change_str - table += change_str - return table - - - elif locale == 'nl_NL': - # Generate Header Row - table = 'Datum' - for _ in range(6): - table += ' ' - table += '| Omschrijving' - for _ in range(14): - table += ' ' - table += '| Verandering' - for _ in range(2): - table += ' ' - - while len(entries) > 0: - table += '\n' - - # Find next entry in order - min_entry_index = -1 - for i in range(len(entries)): - entry = entries[i] - if min_entry_index < 0: - min_entry_index = i - continue - min_entry = entries[min_entry_index] - if entry.date < min_entry.date: - min_entry_index = i - continue - if ( - entry.date == min_entry.date and - entry.change < min_entry.change - ): - min_entry_index = i - continue - if ( - entry.date == min_entry.date and - entry.change == min_entry.change and - entry.description < min_entry.description - ): - min_entry_index = i - continue - entry = entries[min_entry_index] - entries.pop(min_entry_index) - - # Write entry date to table - day = entry.date.day - day = str(day) - if len(day) < 2: - day = '0' + day - date_str = day - date_str += '-' - month = entry.date.month - month = str(month) - if len(month) < 2: - month = '0' + month - date_str += month - date_str += '-' - year = entry.date.year - year = str(year) - while len(year) < 4: - year = '0' + year - date_str += year - table += date_str - table += ' | ' - - # Write entry description to table - # Truncate if necessary - if len(entry.description) > 25: - for i in range(22): - table += entry.description[i] - table += '...' - else: - for i in range(25): - if len(entry.description) > i: - table += entry.description[i] - else: - table += ' ' - table += ' | ' - - # Write entry change to table - if currency == 'USD': - change_str = '$ ' - if entry.change < 0: - change_str += '-' - change_dollar = abs(int(entry.change / 100.0)) - dollar_parts = [] - while change_dollar > 0: - dollar_parts.insert(0, str(change_dollar % 1000)) - change_dollar = change_dollar // 1000 - if len(dollar_parts) == 0: - change_str += '0' - else: - while True: - change_str += dollar_parts[0] - dollar_parts.pop(0) - if len(dollar_parts) == 0: - break - change_str += '.' - change_str += ',' - change_cents = abs(entry.change) % 100 - change_cents = str(change_cents) - if len(change_cents) < 2: - change_cents = '0' + change_cents - change_str += change_cents - change_str += ' ' - while len(change_str) < 13: - change_str = ' ' + change_str - table += change_str - elif currency == 'EUR': - change_str = u'€ ' - if entry.change < 0: - change_str += '-' - change_euro = abs(int(entry.change / 100.0)) - euro_parts = [] - while change_euro > 0: - euro_parts.insert(0, str(change_euro % 1000)) - change_euro = change_euro // 1000 - if len(euro_parts) == 0: - change_str += '0' - else: - while True: - change_str += euro_parts[0] - euro_parts.pop(0) - if len(euro_parts) == 0: - break - change_str += '.' - change_str += ',' - change_cents = abs(entry.change) % 100 - change_cents = str(change_cents) - if len(change_cents) < 2: - change_cents = '0' + change_cents - change_str += change_cents - change_str += ' ' - while len(change_str) < 13: - change_str = ' ' + change_str - table += change_str - return table - -entries = [ - create_entry('2015-01-02', 'Something', 0), - create_entry('2015-01-02', 'Something', -1), - create_entry('2015-01-02', 'Something', 1), - create_entry('2015-01-01', 'Something', 0), - create_entry('2015-01-01', 'Something', -1), - create_entry('2015-01-01', 'Something', 1) -] -print(format_entries('USD', 'en_US', entries)) \ No newline at end of file + return '\n'.join(table) \ No newline at end of file