From 6af9bef334733823e1cbfaaac598a763a52fc85f Mon Sep 17 00:00:00 2001 From: Aerex Date: Sun, 7 Jul 2019 13:58:01 -0500 Subject: [PATCH] refactor: Reanmed templates - fix: Added browse subcommand for products --- grocy/cli.py | 132 ++++++++++++++---- grocy/conf.py | 10 +- grocy/entity.py | 32 +++-- grocy/meta.py | 27 ++++ grocy/recipe.py | 40 +++++- grocy/request.py | 15 +- grocy/schema.py | 28 ++++ grocy/stock.py | 8 +- grocy/table.py | 69 +++++++-- models.json | 39 ++++++ setup.py | 2 +- templates/debug.yml | 1 + .../add.yml} | 0 templates/product/add.yml | 20 +++ .../{product_edit.yml => product/edit.yml} | 0 templates/product/table.yml | 0 .../{single_product.yml => product/view.yml} | 0 templates/{recipe_add.yml => recipe/add.yml} | 0 templates/recipe/edit.yml | 18 +++ templates/recipe/view.yml | 20 +++ templates/recipe_edit.yml | 24 ---- 21 files changed, 397 insertions(+), 88 deletions(-) create mode 100644 grocy/meta.py create mode 100644 grocy/schema.py create mode 100644 models.json create mode 100644 templates/debug.yml rename templates/{ingredient_add.yml => ingredient/add.yml} (100%) create mode 100644 templates/product/add.yml rename templates/{product_edit.yml => product/edit.yml} (100%) create mode 100644 templates/product/table.yml rename templates/{single_product.yml => product/view.yml} (100%) rename templates/{recipe_add.yml => recipe/add.yml} (100%) create mode 100644 templates/recipe/edit.yml create mode 100644 templates/recipe/view.yml delete mode 100644 templates/recipe_edit.yml diff --git a/grocy/cli.py b/grocy/cli.py index 7d25dde..712981e 100644 --- a/grocy/cli.py +++ b/grocy/cli.py @@ -1,6 +1,8 @@ import click from markdown import markdown +from html2text import html2text from jinja2 import Environment, FileSystemLoader +from grocy.meta import Meta from grocy.conf import Configuration from grocy.util import Util from grocy.recipe import Recipe @@ -104,7 +106,7 @@ def edit(product_id, name): cfg = Configuration() util = Util(cfg=cfg) cfg.load() - loaded_template = cfg.templates('product_edit') + loaded_template = cfg.templates('product/edit') entity = Entity(name='products') if product_id: product = entity.get(id=product_id) @@ -138,7 +140,8 @@ def edit(product_id, name): @product.command() @click.option('--name', '-n', 'name') -def list(name): +@click.option('-t', 'template') +def list(name, template): logger = logging.getLogger('cli.product.list') cfg = Configuration() cfg.load() @@ -160,12 +163,114 @@ def list(name): entries['locations'] = location_entity.get() entries['products'] = products table = Table(entries=entries) - click.echo(table.products) + click.echo_via_pager(table.products) except Exception as e: logger.error(e) raise e +@product.command() +@click.argument('product_id') +def browse(product_id): + logger = logging.getLogger('cli.product.browse') + try: + cfg = Configuration() + cfg.load() + url = '{domain}/product/{product_id}'.format(domain=cfg.domain, product_id=product_id) + click.launch(url, wait=False) + except Exception as e: + logger.error(e) + raise e + + +@product.command() +@click.option('-t', 'template') +def add(template): + logger = logging.getLogger('cli.product.add') + try: + cfg = Configuration() + cfg.load() + logger = logging.getLogger('cli.product.add') + meta = Meta() + # Get product_groups + meta.add(type='entities', name='product_groups') + # Get locations + meta.add(type='entities', name='locations') + # Get quantity_units + meta.add(type='entities', name='quantity_units') + if template: + loaded_template = cfg.templates(template) + else: + loaded_template = cfg.templates('product/add') + new_product = click.edit(loaded_template.render(grocy=meta.generate()), extension='.yml') + + if not new_product: + return + + parsed_new_product = yaml.safe_load(new_product) + if template == 'debug': + click.echo(parsed_new_product) + return + entity = Entity(name='products') + entity.create(parsed_new_product) + except Exception as e: + logger.error(e) + raise e + +@main.group() +@click.pass_context +def recipe(ctx): + pass + +@recipe.command() +@click.pass_context +@click.argument('recipe_id', required=False) +@click.option('-t', 'template') +def view(ctx, recipe_id, template): + logger = logging.getLogger('cli.recipes.view') + try: + cfg = Configuration() + cfg.load() + data = {'fields': {}} + if recipe_id: + entity = Entity(name='recipes') + data['fields'] = entity.get(id=recipe_id) + + # Change html markup to plain text + html_markup_description = data['fields']['description'] + plain_text_description = html2text(html_markup_description) + data['fields']['description'] = plain_text_description + + recipe = Recipe(id=recipe_id) + data['fields']['fulfillment'] = recipe.get_fulfillments() + + if template: + loaded_template = cfg.templates(template) + else: + loaded_template = cfg.templates('recipe/view') + + entity = Entity(name='recipes') + click.echo(loaded_template.render(grocy=data)) + else: + click.echo(ctx.get_help()) + except Exception as e: + logger.error(e) + raise e +#@recipe.command() +#def list(): +# logger = logging.getLogger('cli.recipe') +# try: +# entity = Entity(name='recipes') +# recipes = entity.get() +# recipe = Recipe( +# ingredient_reqs = recipe.get_ingredient_requirements() +# table = Table(recipes=recipes, recipes_reqs=recipes_reqs, ingredient_reqs=ingredient_reqs) +# click.echo(table.recipe) +# except Exception as e: +# logger.error(e) +# raise e +## +# #@main.command() #def shopping(): # logger = logging.getLogger('cli.shopping') @@ -232,27 +337,6 @@ def list(name): # raise e # # -#@main.group() -#@click.pass_context -#def recipe(ctx): -# pass -# -# -#@recipe.command('ls') -#def ls(): -# logger = logging.getLogger('cli.recipe') -# try: -# entity = Entity(name='recipes') -# recipes = entity.get() -# recipe = Recipe() -# recipes_reqs = recipe.get_requirements() -# table = Table(recipes=recipes, recipes_reqs=recipes_reqs) -# click.echo(table.recipe) -# except Exception as e: -# logger.error(e) -# raise e -# -# #@recipe.command('edit') #@click.argument('recipe_id') #def edit(recipe_id): diff --git a/grocy/conf.py b/grocy/conf.py index 44c080d..891d919 100644 --- a/grocy/conf.py +++ b/grocy/conf.py @@ -20,7 +20,7 @@ class Configuration(object): 'level': 'DEBUG', 'file_location': None }, - 'api': 'https://demo-en.grocy.info/api', + 'domain': 'https://demo-en.grocy.info', 'token': None, 'formats': { 'col': 'center', @@ -56,9 +56,9 @@ class Configuration(object): self.logger_file_location = user_cfg_options['logger_file_location'] cfg_json['logger']['file_location'] = self.logger_file_location - if user_cfg_options['api']: - self.api = user_cfg_options['api'] - cfg_json['api'] = self.api + if user_cfg_options['domain']: + self.domain = user_cfg_options['domain'] + cfg_json['domain'] = self.domain if user_cfg_options['token']: self.token = user_cfg_options['token'] @@ -99,7 +99,7 @@ class Configuration(object): def templates(self, name): try: TEMPLATE_LOADER = Environment(loader=FileSystemLoader([self.USER_TEMPLATE_DIR, self.PROJ_TEMPLATE_DIR]), - trim_blocks=True, lstrip_blocks=True) + trim_blocks=False, lstrip_blocks=True) return TEMPLATE_LOADER.get_template('{}.{}'.format(name, self.TEMPLATE_EXT)) except Exception as e: diff --git a/grocy/entity.py b/grocy/entity.py index 97b2ae5..7b98b13 100644 --- a/grocy/entity.py +++ b/grocy/entity.py @@ -1,16 +1,21 @@ from grocy.request import Request import re +from copy import deepcopy from grocy.conf import Configuration + import logging class Entity(object): - RESOURCE_URL_TEMPLATE = '{api}/objects/{entity}/{objectId}' - COLLECTION_URL_TEMPLATE = '{api}/objects/{entity}' - SCHEMA_URL_TEMPLATE = '{api}/openapi/specification' + RESOURCE_URL_TEMPLATE = '{domain}/api/objects/{entity}/{objectId}' + COLLECTION_URL_TEMPLATE = '{domain}/api/objects/{entity}' + SCHEMA_URL_TEMPLATE = '{domain}/api/openapi/specification' SCHEMA_MODEL_MAP = { 'products': 'Product', - 'stock': 'StockEntry' + 'stock': 'StockEntry', + 'product_groups':'ProductGroup', + 'locations': 'Location', + 'quantity_units': 'QuantityUnit' } def __init__(self, name, **props): @@ -19,12 +24,13 @@ class Entity(object): self.name = name self.__dict__.update(**props) + def get(self, id=None): logger = logging.getLogger('entity.get') if id: - url = self.RESOURCE_URL_TEMPLATE.format(api=self.conf.api, entity=self.name, objectId=id) + url = self.RESOURCE_URL_TEMPLATE.format(domain=self.conf.domain, entity=self.name, objectId=id) else: - url = self.COLLECTION_URL_TEMPLATE.format(api=self.conf.api, entity=self.name) + url = self.COLLECTION_URL_TEMPLATE.format(domain=self.conf.domain, entity=self.name) request = Request('get', url) try: @@ -54,9 +60,15 @@ class Entity(object): def create(self, entity): logger = logging.getLogger('entity.add') - url = self.COLLECTION_URL_TEMPLATE.format(api=self.conf.api, entity=self.name) + url = self.COLLECTION_URL_TEMPLATE.format(domain=self.conf.domain, entity=self.name) - request = Request('post', url, entity) + for key, value in entity.items(): + if type(value) == bool: + entity[key] = '1' if value else '0' + + print('{}'.format(entity)) + + request = Request('post', url, resource=entity) try: return request.send() except Exception as e: @@ -67,7 +79,7 @@ class Entity(object): if id is None: raise Exception('id property is required to update entity') logger = logging.getLogger('entity.update') - url = self.RESOURCE_URL_TEMPLATE.format(api=self.conf.api, entity=self.name, objectId=id) + url = self.RESOURCE_URL_TEMPLATE.format(domain=self.conf.domain, entity=self.name, objectId=id) request = Request('put', url, resource=entity) try: @@ -80,7 +92,7 @@ class Entity(object): def schema(self): logger = logging.getLogger('entity.schema') try: - url = self.SCHEMA_URL_TEMPLATE.format(api=self.conf.api) + url = self.SCHEMA_URL_TEMPLATE.format(domain=self.conf.domain) request = Request('get', url) response = request.send() schema_name = self.SCHEMA_MODEL_MAP[self.name] diff --git a/grocy/meta.py b/grocy/meta.py new file mode 100644 index 0000000..c236475 --- /dev/null +++ b/grocy/meta.py @@ -0,0 +1,27 @@ +from grocy.entity import Entity +from grocy.schema import get_schema +from grocy.recipe import Recipe +from fontawesome import icons as fa_icons + + +class Meta(object): + def __init__(self): + self.meta = {'meta': {'entities': {}, 'fa_icons': fa_icons}} + + def add(self, type, name): + if type == 'entities': + entity = Entity(name=name) + resources = entity.get() + schema = get_schema(name) + elif type == 'recipes': + recipe = Recipe() + if name == 'fulfillments': + resources = recipe.get_fulfillments() + schema = get_schema(name='recipe_fulfilments') + + self.meta['meta'][type][name] = {} + self.meta['meta'][type][name]['properties'] = schema['properties'] + self.meta['meta'][type][name]['valid_values'] = resources + + def generate(self): + return self.meta diff --git a/grocy/recipe.py b/grocy/recipe.py index c7b3e07..e65e5b4 100644 --- a/grocy/recipe.py +++ b/grocy/recipe.py @@ -1,18 +1,30 @@ from grocy.request import Request from grocy.conf import Configuration +from grocy.entity import Entity import logging class Recipe(object): - GET_RECIPE_REQUIRMENTS_URL_TEMPLATE = '{api}/recipes/requirements' + GET_RECIPES_FULFILLMENT_URL_TEMPLATE = '{domain}/api/recipes/fulfillment' + GET_RECIPE_FULFILLMENT_URL_TEMPLATE = '{domain}/api/recipes/{recipeId}/fulfillment' + GET_RECIPES_POS_FULFILLMENT_URL_TEMPLATE = '{domain}/api/recipes/pos/fulfillment' + GET_RECIPE_POS_FULFILLMENT_URL_TEMPLATE = '{domain}/api/recipes/{recipeId}/pos/{recipeId}/fulfillment' - def __init__(self): + def __init__(self, id=None): self.conf = Configuration() self.conf.load() + self.id = id - def get_requirements(self): + def get_ingredient_requirements(self, recipe_id=None): + logger = logging.getLogger('recipe.get_ingredient_requirements') + + + def get_fulfillments(self): logger = logging.getLogger('recipe.get_requirements') - url = self.GET_RECIPE_REQUIRMENTS_URL_TEMPLATE.format(api=self.conf.api) + if self.id: + url = self.GET_RECIPE_FULFILLMENT_URL_TEMPLATE.format(domain=self.conf.domain, recipeId=self.id) + else: + url = self.GET_RECIPES_FULFILLMENT_URL_TEMPLATE.format(domain=self.conf.domain) request = Request('get', url) try: return request.send() @@ -20,3 +32,23 @@ class Recipe(object): logger.error(e) raise e + def get(self): + # Get list of available ingredients + if self.id: + entity = Entity(name='recipes') + recipe = entity.get(id=self.id) + + if type(recipe) is list: + pass + + + + + + + + + + + + diff --git a/grocy/request.py b/grocy/request.py index 9378409..1117236 100644 --- a/grocy/request.py +++ b/grocy/request.py @@ -1,11 +1,13 @@ from grocy.conf import Configuration -import json -from requests import request -import requests +from requests import session import logging +import cachecontrol + +sess = cachecontrol.CacheControl(session()) class Request(object): + def __init__(self, method, url, resource=None): self.conf = Configuration() self.conf.load() @@ -22,13 +24,16 @@ class Request(object): def send(self): logger = logging.getLogger('request.send') if self.resource: - r = request(method=self.method, url=self.url, headers=self.headers, json=self.resource) + r = sess.request(method=self.method, url=self.url, headers=self.headers, json=self.resource) + print(r.text) else: - r = request(method=self.method, url=self.url, headers=self.headers) + r = sess.request(method=self.method, url=self.url, headers=self.headers) if r.raise_for_status(): logger.error(r.raise_for_status()) + logger.error(r.text) raise r.raise_for_status() + if r.status_code != 204: return r.json() diff --git a/grocy/schema.py b/grocy/schema.py new file mode 100644 index 0000000..c7771d3 --- /dev/null +++ b/grocy/schema.py @@ -0,0 +1,28 @@ +from grocy.request import Request +from grocy.conf import Configuration +import logging + +SCHEMA_URL_TEMPLATE = '{domain}/api/openapi/specification' +SCHEMA_MODEL_MAP = { + 'products': 'Product', + 'stock': 'StockEntry', + 'product_groups': 'ProductGroup', + 'locations': 'Location', + 'quantity_units': 'QuantityUnit', + 'recipe_requirements': 'RecipeFulfilmentResponse' +} + + +def get_schema(name): + logger = logging.getLogger('schema') + try: + cfg = Configuration() + cfg.load() + url = SCHEMA_URL_TEMPLATE.format(domain=cfg.domain) + request = Request('get', url) + response = request.send() + schema_name = SCHEMA_MODEL_MAP[name] + return response['components']['schemas'][schema_name] + except Exception as e: + logger.error(e) + raise e diff --git a/grocy/stock.py b/grocy/stock.py index dabf765..971fcb2 100644 --- a/grocy/stock.py +++ b/grocy/stock.py @@ -4,8 +4,8 @@ import logging class Stock(object): - GET_STOCK_URL_TEMPLATE = '{api}/stock' - GET_STOCK_PRODUCT_DETAIL_TEMPLATE = '{api}/stock/products/{product_id}' + GET_STOCK_URL_TEMPLATE = '{domain}/api/stock' + GET_STOCK_PRODUCT_DETAIL_TEMPLATE = '{domain}/api/stock/products/{product_id}' def __init__(self): self.conf = Configuration() @@ -22,10 +22,10 @@ class Stock(object): @property def products(self): logger = logging.getLogger('stock.products') - url = self.GET_STOCK_URL_TEMPLATE.format(api=self.conf.api) + url = self.GET_STOCK_URL_TEMPLATE.format(domain=self.conf.domain) return self.__get_resources(url, logger) def get_product(self, product_id): logger = logging.getLogger('stock.get_product') - url = self.GET_STOCK_PRODUCT_DETAIL_TEMPLATE.format(api=self.conf.api, product_id=product_id) + url = self.GET_STOCK_PRODUCT_DETAIL_TEMPLATE.format(domain=self.conf.domain, product_id=product_id) return self.__get_resources(url, logger) diff --git a/grocy/table.py b/grocy/table.py index c5b18f8..d84a8d7 100644 --- a/grocy/table.py +++ b/grocy/table.py @@ -20,7 +20,7 @@ class Table(object): def product(self): if not self.entry: raise Exception('Missing product') - loaded_template = self.conf.templates('single_product') + loaded_template = self.conf.templates('product/view') return loaded_template.render(self.entry) @property @@ -36,23 +36,26 @@ class Table(object): table_entries = [] try: for entry in self.entries['products']: - print('{}'.format(entry)) table_entry = [] - product_group_name = '' if entry['product_group_id'] == '' else product_groups_map[entry['product_group_id']] - location_name = location_map[entry['location_id']] - quantity_unit_purchase_name = quantity_unit_map[entry['qu_id_purchase']] - quantity_unit_stock_name = quantity_unit_map[entry['qu_id_stock']] + 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(entry['mini_stock_amount']) - table_entry.append(entry['qu_factor_purchase_to_stock']) + table_entry.append(mini_stock_amount) + table_entry.append(quantity_unit_stock_name) table_entries.append(table_entry) - table_headers = ['ID', 'Name', 'Location', 'Min Stock Amount', - 'QU Purchase', 'QU Stock', 'QU Factor', 'Product Group'] + 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 @@ -89,7 +92,49 @@ class Table(object): checkmark_glyph = '' times_glyph = '' exclamation_glyph = '' - logger = logging.getLogger('table.recipes') + 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} @@ -160,3 +205,5 @@ class Table(object): # Generate stock overview table return tabulate(table_entries, headers=table_headers) + + diff --git a/models.json b/models.json new file mode 100644 index 0000000..4059500 --- /dev/null +++ b/models.json @@ -0,0 +1,39 @@ +{ + "id": "3", + "name": "Garbonza Beans", + "description": "", + "location": { + "id": "3", + "name": "Pantry", + "description": "", + "row_created_timestamp": "2018-10-21 03:24:25" + }, + "quantity_unit": { + "stock": { + "id": "4", + "name": "Ib", + "description": "Pounds", + "row_created_timestamp": "2018-10-21 03:24:11", + "name_plural": "Ibs", + "plural_forms": null + }, + "purchase": { + "id": "4", + "name": "Ib", + "description": "Pounds", + "row_created_timestamp": "2018-10-21 03:24:11", + "name_plural": "Ibs" + } + }, + "qu_factor_purchase_to_stock": "1.0", + "barcode": "", + "min_stock_amount": "0", + "default_best_before_days": "0", + "row_created_timestamp": "2018-10-21 03:39:42", + "product_group_id": "", + "picture_file_name": null, + "default_best_before_days_after_open": "0", + "allow_partial_units_in_stock": "0", + "enable_tare_weight_handling": "0", + "tare_weight": "0.0", + "not_check_stock_fulfillment_for_recipes": "0" diff --git a/setup.py b/setup.py index b6708c4..f465297 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ setup( packages=find_packages(), include_package_data=True, zip_safe=False, - install_requires=['Click', 'pyyaml', 'requests', 'taskw', 'lockfile', 'tox', 'html2text', 'markdown'], + install_requires=['Click', 'pyyaml', 'requests', 'taskw', 'lockfile', 'tox', 'html2text', 'markdown', 'cachecontrol', 'fontawesome'], long_description=read('README.rst'), tests_require=[ "pytest_mock", diff --git a/templates/debug.yml b/templates/debug.yml new file mode 100644 index 0000000..dd1041d --- /dev/null +++ b/templates/debug.yml @@ -0,0 +1 @@ +{{ grocy | tojson(indent=2) | safe }} diff --git a/templates/ingredient_add.yml b/templates/ingredient/add.yml similarity index 100% rename from templates/ingredient_add.yml rename to templates/ingredient/add.yml diff --git a/templates/product/add.yml b/templates/product/add.yml new file mode 100644 index 0000000..84dc061 --- /dev/null +++ b/templates/product/add.yml @@ -0,0 +1,20 @@ +# Legend: +# Location Name (id): {% for valid_value in grocy.meta.entities.locations.valid_values %}{{ valid_value.name }}({{ valid_value.id}}){% if not loop.last %}{{ ', '}}{% endif %}{% endfor %} +# Product Group (id): {% for valid_value in grocy.meta.entities.product_groups.valid_values %}{{ valid_value.name }}({{ valid_value.id}}){% if not loop.last %}{{ ', '}}{% endif %}{% endfor %} +# Quanity Units (id): {% for valid_value in grocy.meta.entities.quantity_units.valid_values %}{{ valid_value.name }}({{ valid_value.id}}){% if not loop.last %}{{ ', '}}{% endif %}{% endfor %} + +name: +description: |- +barcode: +location_id: +min_stock_amount: 0 +default_best_before_days: 0 +product_group_id: +qu_id_purchase: +qu_id_stock: +default_best_before_days_after_open: 0 +qu_factor_purchase_to_stock: 0 +allow_partial_units_in_stock: False +enable_tare_weight_handling: False +tare_weight: 0 +not_check_stock_fulfillment_for_recipes: False diff --git a/templates/product_edit.yml b/templates/product/edit.yml similarity index 100% rename from templates/product_edit.yml rename to templates/product/edit.yml diff --git a/templates/product/table.yml b/templates/product/table.yml new file mode 100644 index 0000000..e69de29 diff --git a/templates/single_product.yml b/templates/product/view.yml similarity index 100% rename from templates/single_product.yml rename to templates/product/view.yml diff --git a/templates/recipe_add.yml b/templates/recipe/add.yml similarity index 100% rename from templates/recipe_add.yml rename to templates/recipe/add.yml diff --git a/templates/recipe/edit.yml b/templates/recipe/edit.yml new file mode 100644 index 0000000..1634a0d --- /dev/null +++ b/templates/recipe/edit.yml @@ -0,0 +1,18 @@ +name: {{ grocy.fields.name }} +description: | + +{{ grocy.fields.description }} + +base_servings: {{ grocy.fields.base_servings | default("1") }} +desired_servings: {{ grocy.fields.desired_servings | default("1") }} +not_check_shoppinglist: {{ grocy.fields.not_check_shoppinglist | default("1") }} +products: {% for ingredient in grocy.fields.ingredientsp%} + - id: {{ ingredient.id }} + name: {{ ingredient.name }} + description: {{ ingredient.description | default(null) }} + note: {{ ingredient.note }} + amount: {{ ingredient.amount }} + qu_id: {{ ingredient.qu_id }} + only_check_single_unit_in_stock: {{ ingredient.only_check_single_unit_in_stock }} + ingredient_group: {{ ingredient.ingredient_group | default(null) }} + not_check_stock_fulfillment: {{ ingredient.not_check_stock_fulfillment }}{% endfor %} diff --git a/templates/recipe/view.yml b/templates/recipe/view.yml new file mode 100644 index 0000000..ed1d1be --- /dev/null +++ b/templates/recipe/view.yml @@ -0,0 +1,20 @@ +name: {{ grocy.fields.name }} +servings: {{ grocy.fields.base_servings }} +costs: {{ grocy.fields.fulfillment.costs }} +ingredients: {% for ingredient in grocy.fields.ingredients %} + - product_id: {{ ingredient.id }} + name: {{ ingredient.name}} + description: {{ ingredient.description | default(null) }} + note: {{ ingredient.note }} + amount: {{ ingredient.amount }} + qu_id: {{ ingredient.qu_id }} + only_check_single_unit_in_stock: {{ ingredient.only_check_single_unit_in_stock }} + ingredient_group: {{ ingredient.ingredient_group | default(null) }} + not_check_stock_fulfillment: {{ ingredient.not_check_stock_fulfillment }}{% endfor %} + +description: |- + {{ grocy.fields.description }} + + + + diff --git a/templates/recipe_edit.yml b/templates/recipe_edit.yml deleted file mode 100644 index 4ddb8e5..0000000 --- a/templates/recipe_edit.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: {{ name }} -description: | - -{{ description }} - -picture_file_name: {% if picture_file_name is not none %} -{{picture_file_name}} -{% else %} - -{% endif %} -base_servings: {{ base_servings | default("1") }} -desired_servings: {{ desired_servings | default("1") }} -not_check_shoppinglist: {{ not_check_shoppinglist | default("1") }} -products: {% for product in products %} - - id: {{ product.id }} - name: {{ product.name }} - description: {{ product.description | default(null) }} - note: {{ recipes_pos[loop.index0].note }} - amount: {{ recipes_pos[loop.index0].amount }} - qu_id: {{ recipes_pos[loop.index0].qu_id }} - only_check_single_unit_in_stock: {{ recipes_pos[loop.index0].only_check_single_unit_in_stock }} - ingredient_group: {{ recipes_pos[loop.index0].ingredient_group | default(null) }} - not_check_stock_fulfillment: {{ recipes_pos[loop.index0].not_check_stock_fulfillment }}{% endfor %} -