def __init__(self, purchases=[]): self.categories = defaultdict(lambda: [0.0, set(), 0.0]) self.purchases = purchases self.unsane_items = [] self.unsane_categories = [] self.category_dict = ItemCategoryDict() self.total = 0.0
def test_purchase(): expected_positions = [] cat_dict = ItemCategoryDict() cat_dict.item_category_dict = {'Pfand': 'Pfand', 'Cola Zero': 'Cola'} Position = namedtuple('item', ['name', 'category', 'price', 'count', 'weight']) expected_positions.append(Position('Cola Zero', 'Cola', 0.39, 1, '1.5l')) expected_positions.append(Position('Pfand', 'Pfand', 0.25, 1, '')) expected_positions.append(Position('Mandelhörnchen', '', 1.59, 1, '')) expected_positions.append(Position('Kaffeegetränk', '', 0.49, 1, '0.25l')) expected_positions.append( Position('Schokolade Edelbitter', '', 1.09, 1, '')) expected_positions.append( Position('Schokolade Erdbeere Joghurt Crisp', '', 1.19, 1, '200g')) with Purchase('2015-05-21', 'Aldi', payment_method='cash', category_dict=cat_dict) as purchase: purchase.add_item('Cola Zero', 0.39, 1, weight='1.5l') purchase.add_item('Pfand', 0.25, 1) purchase.add_item('Mandelhörnchen', 1.59, 1) purchase.add_item('Kaffeegetränk', 0.49, 1, weight='0.25l') purchase.add_item('Schokolade Edelbitter', 1.09, 1) purchase.add_item('Schokolade Erdbeere Joghurt Crisp', 1.19, 1, weight='200g') assert expected_positions == purchase.positions assert purchase.total == 5
def test_category_create(factory_file): category_dict = ItemCategoryDict() category_dict.item_category_dict = {} category_dict.extract_new_categories('receipts_test.csv') assert '' not in category_dict.item_category_dict assert 'Bio Company' not in category_dict.item_category_dict assert category_dict.item_category_dict['Blanc de Pomm'] == 'Zubrot'
def test_category(self): category_dict = ItemCategoryDict() category_dict.item_category_dict = {'Pfand': 'Pfand', 'Pesto': 'Pesto', 'Parmesan': 'Käse', 'Heumilch': 'Milch', 'Milch': 'Milch', } cat_milch = category_dict.get_category('Milch') assert cat_milch == 'Milch'
def test_category(self): category_dict = ItemCategoryDict() category_dict.item_category_dict = { 'Pfand': 'Pfand', 'Pesto': 'Pesto', 'Parmesan': 'Käse', 'Heumilch': 'Milch', 'Milch': 'Milch', } cat_milch = category_dict.get_category('Milch') assert cat_milch == 'Milch'
def test_purchase_ledger_only(): cat_dict = ItemCategoryDict() cat_dict.item_category_dict = {'Pfand': 'Aktiva:Pfand', 'Cola': 'Ausgaben:Konsum:Cola'} with Purchase('2015-05-21', 'Übertrag', payment_method='Giro', category_dict=cat_dict, flags='L') as purchase: purchase.add_item('Auszahlung', 100, 1, category='Aktiva:Portmonaie') actual_output = purchase.get_ledger() expected_output = "2015-05-21 Übertrag\n" expected_output += " Aktiva:Giro -100.0\n" expected_output += " Aktiva:Portmonaie 100.0\n" expected_output += "\n" assert expected_output == actual_output
def test_purchase_ledger(): cat_dict = ItemCategoryDict() cat_dict.item_category_dict = {'Pfand': 'Aktiva:Pfand', 'Cola': 'Ausgaben:Konsum:Cola'} with Purchase('2015-05-21', 'Testgeschäft', payment_method='cash', category_dict=cat_dict) as purchase: purchase.add_item('Cola', 0.39, 1, weight='1.5l') purchase.add_item('Pfand', 0.25, 1) actual_output = purchase.get_ledger() expected_output = "2015-05-21 Testgeschäft\n" expected_output += " Aktiva:Portmonaie -0.64\n" expected_output += " Ausgaben:Konsum:Cola 0.39\n" expected_output += " Aktiva:Pfand 0.25\n" expected_output += "\n" assert expected_output == actual_output
def test_purchase_ledger_only(): cat_dict = ItemCategoryDict() cat_dict.item_category_dict = { 'Pfand': 'Aktiva:Pfand', 'Cola': 'Ausgaben:Konsum:Cola' } with Purchase('2015-05-21', 'Übertrag', payment_method='Giro', category_dict=cat_dict, flags='L') as purchase: purchase.add_item('Auszahlung', 100, 1, category='Aktiva:Portmonaie') actual_output = purchase.get_ledger() expected_output = "2015-05-21 Übertrag\n" expected_output += " Aktiva:Giro -100.0\n" expected_output += " Aktiva:Portmonaie 100.0\n" expected_output += "\n" assert expected_output == actual_output
def test_readfile(factory_file): empty_dict = ItemCategoryDict() empty_dict.item_category_dict = {} with Parser(category_dictionary=empty_dict) as p: purchases = p.read_file('receipts_test.csv') assert purchases[0].date == '2015-11-29' assert purchases[0].shop == 'Bio Company' assert purchases[0].payment_method == 'cash' assert purchases[0].positions[0].name == 'Blanc de Pomm' assert purchases[0].positions[0].price == 1.69 assert purchases[0].positions[0].count == 1 assert purchases[0].positions[0].category == 'Zubrot' assert purchases[0].positions[1].name == 'Seidentofu' assert purchases[0].positions[1].price == 5.18 assert purchases[0].positions[1].count == 2 assert purchases[0].positions[1].category == '' assert purchases[1].date == '2014-11-01' assert purchases[1].shop == 'Bio Company' assert purchases[1].payment_method == 'Giro'
def test_purchase_ledger(): cat_dict = ItemCategoryDict() cat_dict.item_category_dict = { 'Pfand': 'Aktiva:Pfand', 'Cola': 'Ausgaben:Konsum:Cola' } with Purchase('2015-05-21', 'Testgeschäft', payment_method='cash', category_dict=cat_dict) as purchase: purchase.add_item('Cola', 0.39, 1, weight='1.5l') purchase.add_item('Pfand', 0.25, 1) actual_output = purchase.get_ledger() expected_output = "2015-05-21 Testgeschäft\n" expected_output += " Aktiva:Portmonaie -0.64\n" expected_output += " Ausgaben:Konsum:Cola 0.39\n" expected_output += " Aktiva:Pfand 0.25\n" expected_output += "\n" assert expected_output == actual_output
def __init__(self, date, shop, **kwargs): self._date = None self.date = date self.shop = shop self.payment_method = kwargs.get('payment_method', 'cash') self._positions = [] self.category_dict = kwargs.get('category_dict', ItemCategoryDict()) self._total = 0.0 self.flags = {} self.extract_flags(kwargs.get('flags', '')) self.unsane_items = []
def test_purchase(): expected_positions = [] cat_dict = ItemCategoryDict() cat_dict.item_category_dict = {'Pfand': 'Pfand', 'Cola Zero': 'Cola'} Position = namedtuple('item', ['name', 'category', 'price', 'count', 'weight']) expected_positions.append(Position('Cola Zero', 'Cola', 0.39, 1, '1.5l')) expected_positions.append(Position('Pfand', 'Pfand', 0.25, 1, '')) expected_positions.append(Position('Mandelhörnchen', '', 1.59, 1, '')) expected_positions.append(Position('Kaffeegetränk', '', 0.49, 1, '0.25l')) expected_positions.append(Position('Schokolade Edelbitter', '', 1.09, 1, '')) expected_positions.append(Position('Schokolade Erdbeere Joghurt Crisp', '', 1.19, 1, '200g')) with Purchase('2015-05-21', 'Aldi', payment_method='cash', category_dict=cat_dict) as purchase: purchase.add_item('Cola Zero', 0.39, 1, weight='1.5l') purchase.add_item('Pfand', 0.25, 1) purchase.add_item('Mandelhörnchen', 1.59, 1) purchase.add_item('Kaffeegetränk', 0.49, 1, weight='0.25l') purchase.add_item('Schokolade Edelbitter', 1.09, 1) purchase.add_item('Schokolade Erdbeere Joghurt Crisp', 1.19, 1, weight='200g') assert expected_positions == purchase.positions assert purchase.total == 5
def __init__(self, *args, **kwargs): self.dictionary = kwargs.get('category_dictionary', ItemCategoryDict()) self.purchase_is_active = None self.active_purchase = None self.purchases = []
parser.add_argument("-l", "--ledger", action="store_true", help="show receipts in ledger format ") parser.add_argument("-d", "--date", metavar=('date'), default="1900-01-01", help="show only output from this day on") args = parser.parse_args() parser_args = {} if args.categories_file: cat_dict = ItemCategoryDict(path=args.categories_file) parser_args['category_dictionary'] = cat_dict with ReceiptParser(**parser_args) as p: purchases = p.read_file(args.receipts_file) rc = ReceiptCollection(purchases) rc.collect_items() if args.categories: for key in rc.categories: print key elif args.show_null: print 'Items without category:' for item in rc.categories[''][1]: print item elif args.show_category is not None:
class ReceiptCollection(object): ''' Collection of purchases with evaluation and output options. ''' def __init__(self, purchases=[]): self.categories = defaultdict(lambda: [0.0, set(), 0.0]) self.purchases = purchases self.unsane_items = [] self.unsane_categories = [] self.category_dict = ItemCategoryDict() self.total = 0.0 def collect_items(self): ''' sort all positions in our stored receipts/purchases into their respective categories ''' for purchase in self.purchases: self.unsane_items.extend(purchase.unsane_items) for item in purchase.positions: self.categories[item.category][1].add(item.name) self.categories[item.category][0] += item.price self.check_sanity() self.calculate_total() def totalize_categories(self): self.initialize_super_categories() for category in self.categories.keys(): catsum = 0 length = len(category) for cat in self.categories.keys(): if (cat[0:length] == category): catsum += self.categories[cat][0] self.categories[category][2] = catsum def initialize_super_categories(self): missing_super_categories = [] for category in self.categories.keys(): if (category[:category.rfind(':')] not in self.categories.keys()): missing_super_categories.append(category[:category.rfind(':')]) for missing in missing_super_categories: while True: if missing not in self.categories: self.categories[missing][0] = 0 if missing.rfind(':') == -1: break missing = missing[:missing.rfind(':')] def check_category(self, category, item): ''' make list of conflicting categories ''' stored_category = self.category_dict.get_category(item) if category != stored_category: self.unsane_categories.append((item, category, stored_category)) def check_sanity(self): ''' make list of items belonging to more than one category ''' all_items = set() for category in self.categories: if category is '': continue for item in self.categories[category][1]: if item in all_items: self.unsane_items.append(item) self.check_category(category, item) all_items.add(item) def calculate_total(self): ''' calculate the grand total across all categories ''' self.total = 0.0 for category in self.categories: self.total += self.categories[category][0] def get_ledger(self, date='1900-01-01'): ''' create output in the format of the ledger application ''' ledger_output = "" for receipt in sorted(self.purchases, key=lambda t: t.date): if receipt.date >= date: ledger_output += receipt.get_ledger() return ledger_output