from grocy.entity import Entity import re from grocy.conf import Configuration import logging from tabulate import tabulate class Table(object): NOT_ENOUGH_IN_STOCK_MSG = '{glyph} Not enough in stock, {missing_amount} ingredient{s} missing' ENOUGH_IN_STOCK_MSG = '{glyph} Enough in stock' NOT_ENOUGH_BUT_IN_SHOPPING_LIST_MSG = '{not_enough}, but already on list'.format(not_enough=NOT_ENOUGH_IN_STOCK_MSG) def __init__(self, **entries): self.__dict__.update(entries) self.conf = Configuration() self.conf.load() @property def product(self): if not self.entry: raise Exception('Missing product') loaded_template = self.conf.templates('product/view') return loaded_template.render(self.entry) @property def products(self): if not self.entries: raise Exception('Missing entries') product_groups_map = {product_group['id']: product_group['name'] for product_group in self.entries['product_groups']} location_map = {location['id']: location['name'] for location in self.entries['locations']} quantity_unit_map = {quantity_unit['id']: quantity_unit['name'] for quantity_unit in self.entries['quantity_units']} table_entries = [] try: for entry in self.entries['products']: table_entry = [] product_group_name = 'N/A' if entry['product_group_id'] == '' else product_groups_map[entry['product_group_id']] mini_stock_amount = entry['mini_stock_amount'] if 'mini_stock_amount' in entry else 'N/A' qu_factor_purchase_to_stock = entry['qu_factor_purchase_to_stock'] if 'qu_factor_purchase_to_stock' in entry else 'N/A' location_name = location_map[entry['location_id']] if 'location_id' in entry else 'N/A' quantity_unit_purchase_name = quantity_unit_map[entry['qu_id_purchase']] if 'qu_id_purchase' in entry else 'N/A' quantity_unit_stock_name = quantity_unit_map[entry['qu_id_stock']] if 'qu_id_stock' in entry else 'N/A' table_entry.append(entry['id']) table_entry.append(entry['name']) table_entry.append(location_name) table_entry.append(quantity_unit_purchase_name) table_entry.append(quantity_unit_stock_name) table_entry.append(product_group_name) table_entry.append(mini_stock_amount) table_entry.append(quantity_unit_stock_name) table_entries.append(table_entry) table_headers = ['ID', 'Name', 'Location', 'Min\nStock Amount', 'QU\nPurchase', 'QU\nStock', 'QU\nFactor', 'Product\nGroup'] return tabulate(table_entries, headers=table_headers) except Exception as e: raise e @property def stock(self): logger = logging.getLogger('table.stock') entity = Entity(name='products') products = entity.get() products_map = {product['id']: product for product in products} try: # Get product names from ids and replace table_entries = [] try: for item in self.stocks: product = products_map[item['product_id']] item['product_id'] = product['name'] table_entry = list(dict.values(item)) table_entries.append(table_entry) except Exception as e: logger.error(e) raise e # Generate stock overview table table_headers = ['Product', 'Amount', 'Best Before Date', 'Amount Opened'] return tabulate(table_entries, headers=table_headers) except Exception as e: logger.error(e) raise e @property def recipe(self): checkmark_glyph = '' times_glyph = '' exclamation_glyph = '' logger = logging.getLogger('table.recipe') normal_recipes = [recipe for recipe in self.recipes if re.search(r'^normal', recipe['type'])] recipes_req_map = {recipe_reqs['recipe_id']: recipe_reqs for recipe_reqs in self.recipes_reqs} try: table_entries = [] try: for item in normal_recipes: table_entry = [] table_entry.append(item['id']) table_entry.append(item['name']) table_entry.append(item['base_servings']) recipe_reqs = recipes_req_map[item['id']] missing_amount = int(recipe_reqs['missing_products_count']) number_of_ingredients = 's' if missing_amount > 1 else '' if recipe_reqs['need_fulfilled'] == '1': table_entry.append(self.ENOUGH_IN_STOCK_MSG.format(glyph=checkmark_glyph)) elif recipe_reqs['need_fulfilled_with_shopping_list'] == '1': missing_amount = recipe_reqs['missing_products_count'] table_entry.append(self.NOT_ENOUGH_BUT_IN_SHOPPING_LIST_MSG.format(glyph=exclamation_glyph, missing_amount=missing_amount, s=number_of_ingredients)) else: table_entry.append(self.NOT_ENOUGH_IN_STOCK_MSG.format(glyph=times_glyph, missing_amount=missing_amount, s=number_of_ingredients)) table_entries.append(table_entry) except Exception as e: logger.error(e) raise e # Generate recipes overview table table_headers = ['Id', 'Name', 'Servings', 'Requirements Fulfilled'] return tabulate(table_entries, headers=table_headers) except Exception as e: logger.error(e) raise e @property def recipes(self): checkmark_glyph = '' times_glyph = '' exclamation_glyph = '' logger = logging.getLogger('table.recipe') normal_recipes = [recipe for recipe in self.recipes if re.search(r'^normal', recipe['type'])] recipes_req_map = {recipe_reqs['recipe_id']: recipe_reqs for recipe_reqs in self.recipes_reqs} try: table_entries = [] try: for item in normal_recipes: table_entry = [] table_entry.append(item['id']) table_entry.append(item['name']) table_entry.append(item['base_servings']) recipe_reqs = recipes_req_map[item['id']] missing_amount = int(recipe_reqs['missing_products_count']) number_of_ingredients = 's' if missing_amount > 1 else '' if recipe_reqs['need_fulfilled'] == '1': table_entry.append(self.ENOUGH_IN_STOCK_MSG.format(glyph=checkmark_glyph)) elif recipe_reqs['need_fulfilled_with_shopping_list'] == '1': missing_amount = recipe_reqs['missing_products_count'] table_entry.append(self.NOT_ENOUGH_BUT_IN_SHOPPING_LIST_MSG.format(glyph=exclamation_glyph, missing_amount=missing_amount, s=number_of_ingredients)) else: table_entry.append(self.NOT_ENOUGH_IN_STOCK_MSG.format(glyph=times_glyph, missing_amount=missing_amount, s=number_of_ingredients)) table_entries.append(table_entry) except Exception as e: logger.error(e) raise e # Generate recipes overview table table_headers = ['Id', 'Name', 'Servings', 'Requirements Fulfilled'] return tabulate(table_entries, headers=table_headers) except Exception as e: logger.error(e) raise e @property def shopping_list(self): logger = logging.getLogger('table.shopping_list') try: table_headers = ['Group', 'Product', 'Amount'] # Get product names and location from ids and replace product_ids = [entry['product_id'] for entry in self.shopping_list] products = [] location_ids = [] table_entries = [] for index in range(len(product_ids)): product_id = product_ids[index] entity = Entity(name='products') product = entity.get(id=product_id) entity = Entity(name='quantity_units') quantity_unit = entity.get(product['qu_id_purchase']) min_amount = '{} {}'.format(product['min_stock_amount'], quantity_unit['name']) if product['product_group_id'] == '': product_group_name = 'Uncategorized' else: entity = Entity(name='product_groups') product_group = product.get(id=product['product_group_id']) product_group_name = product_group['name'] shopping_item = [product_group_name, product['name'], min_amount] table_entries.append(shopping_item) except Exception as e: logger.error(e) raise e # Generate stock overview table return tabulate(table_entries, headers=table_headers)