feat: Added add/remove ingredients sub commands to recipes

- feat: Added list recipe commands
   - feat: Added sample add ingredient template for recipe
This commit is contained in:
Aerex 2019-09-25 23:14:11 -05:00
parent 05089108a9
commit 029ba35945
7 changed files with 107 additions and 17 deletions

View File

@ -9,6 +9,7 @@ from grocy.recipe import Recipe
from grocy.table import Table from grocy.table import Table
from grocy.entity import Entity from grocy.entity import Entity
from grocy.stock import Stock from grocy.stock import Stock
from grocy.schema import get_schema
import yaml import yaml
from sys import exit from sys import exit
from os import path from os import path
@ -131,7 +132,7 @@ def edit(product_id, name):
for index, edited_product in enumerate(parsed_edited_products): for index, edited_product in enumerate(parsed_edited_products):
edited_product['id'] = products[index]['id'] edited_product['id'] = products[index]['id']
Util.verify_integrity(edited_product, schema) util.verify_integrity(edited_product, schema)
entity.update(edited_product, id=products[index]['id']) entity.update(edited_product, id=products[index]['id'])
else: else:
raise click.BadParameter('Missing PRODUCT_ID or QUERY') raise click.BadParameter('Missing PRODUCT_ID or QUERY')
@ -332,6 +333,7 @@ def browse(fullscreen, recipe_id):
logger.error(e) logger.error(e)
# TODO: revist this command
@recipe.command() @recipe.command()
@click.option('--name', '-n', 'name') @click.option('--name', '-n', 'name')
@click.argument('recipe_id', required=False) @click.argument('recipe_id', required=False)
@ -342,11 +344,10 @@ def edit(recipe_id, name, template):
cfg = Configuration() cfg = Configuration()
util = Util(cfg=cfg) util = Util(cfg=cfg)
cfg.load() cfg.load()
loaded_template = cfg.templates('recipe/edit')
if template: if template:
loaded_template = cfg.templates(template) loaded_template = cfg.templates(template)
else: else:
loaded_template = cfg.templates('recipe/list') loaded_template = cfg.templates('recipe/edit')
entity = Entity(name='recipes') entity = Entity(name='recipes')
if recipe_id: if recipe_id:
@ -368,6 +369,7 @@ def edit(recipe_id, name, template):
click.echo('Could not find recipe') click.echo('Could not find recipe')
return return
# Build hydrated recipe entity object for editing
data = {'recipes': []} data = {'recipes': []}
for recipe_entity in recipe_entities: for recipe_entity in recipe_entities:
entry = {'fields': recipe_entity, 'meta': []} entry = {'fields': recipe_entity, 'meta': []}
@ -386,17 +388,74 @@ def edit(recipe_id, name, template):
if edited_recipes is None: if edited_recipes is None:
return return
schema = []
schema.append(Entity(name='products').schema)
schema.append(Entity(name='locations').schema)
schema.append(Entity(name='quantity_units').schema)
schema.append(Entity(name='recipes').schema)
parsed_edited_recipes = util.load_yaml(edited_recipes) parsed_edited_recipes = util.load_yaml(edited_recipes)
for index, edited_recipe in enumerate(parsed_edited_recipes): for index, edited_recipe in enumerate(parsed_edited_recipes):
schema = entity.schema
edited_recipe['id'] = recipe_entities[index]['id'] edited_recipe['id'] = recipe_entities[index]['id']
# Util.verify_integrity(edited_recipe, schema) util.verify_integrity(edited_recipe, schema)
entity.update(edited_recipe, id=recipe[index]['id']) entity.update(edited_recipe, id=edited_recipe['id'])
else: else:
raise click.BadParameter('Missing RECIPE_ID or QUERY') raise click.BadParameter('Missing RECIPE_ID or QUERY')
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
raise e raise e
@recipe.command()
@click.argument('recipe_id', required=True)
@click.option('-t', 'template')
def add_ingredient(recipe_id, template):
logger = logging.getLogger('cli.recipe.add_ingredient')
try:
cfg = Configuration()
util = Util(cfg=cfg)
cfg.load()
if template:
loaded_template = cfg.templates(template)
else:
loaded_template = cfg.templates('recipe/add-ingredient')
# Verify that recipe exist
try:
entity = Entity(name='recipes')
entity.get(id=recipe_id)
except Exception:
raise Exception('Could not find recipe {}'.format(recipe_id))
# TODO: Meta has to be added to validate against know fields/properties
# Add quantity_units to meta
ingredient = click.edit(loaded_template.render(), extension='.yml')
if ingredient is None:
return
parsed_new_ingredient = util.load_yaml(ingredient)[0]
parsed_new_ingredient['recipe_id'] = recipe_id
if template == 'debug':
click.echo(parsed_new_ingredient)
return
entity = Entity(name='recipes_pos')
entity.create(parsed_new_ingredient)
except Exception as e:
logger.error(e)
raise e
@recipe.command()
@click.argument('recipe_id', required=True)
@click.argument('ingredient_id', required=True)
def remove_ingredient(recipe_id, ingredient_id):
logger = logging.getLogger('cli.recipe.remove_ingredient')
try:
entity = Entity(name='recipes_pos')
entity.delete(ingredient_id)
except Exception as e:
logger.error(e)
raise e
#@main.command() #@main.command()
#def shopping(): #def shopping():

View File

@ -14,7 +14,8 @@ class Entity(object):
'stock': 'StockEntry', 'stock': 'StockEntry',
'product_groups':'ProductGroup', 'product_groups':'ProductGroup',
'locations': 'Location', 'locations': 'Location',
'quantity_units': 'QuantityUnit' 'quantity_units': 'QuantityUnit',
'recipes': 'Recipe'
} }
def __init__(self, name, **props): def __init__(self, name, **props):
@ -65,8 +66,6 @@ class Entity(object):
if type(value) == bool: if type(value) == bool:
entity[key] = '1' if value else '0' entity[key] = '1' if value else '0'
print('{}'.format(entity))
request = Request('post', url, resource=entity) request = Request('post', url, resource=entity)
try: try:
return request.send() return request.send()
@ -87,6 +86,19 @@ class Entity(object):
logger.error(e) logger.error(e)
raise e raise e
def delete(self, id=None):
if id is None:
raise Exception('id property is required to delete entity')
logger = logging.getLogger('entity.delete')
url = self.RESOURCE_URL_TEMPLATE.format(domain=self.conf.domain, entity=self.name, objectId=id)
request = Request('delete', url)
try:
return request.send()
except Exception as e:
logger.error(e)
raise e
@property @property
def schema(self): def schema(self):
logger = logging.getLogger('entity.schema') logger = logging.getLogger('entity.schema')

View File

@ -11,7 +11,6 @@ class Recipe(object):
GET_RECIPES_FULFILLMENT_URL_TEMPLATE = '{domain}/api/recipes/fulfillment' GET_RECIPES_FULFILLMENT_URL_TEMPLATE = '{domain}/api/recipes/fulfillment'
GET_RECIPE_FULFILLMENT_URL_TEMPLATE = '{domain}/api/recipes/{recipeId}/fulfillment' GET_RECIPE_FULFILLMENT_URL_TEMPLATE = '{domain}/api/recipes/{recipeId}/fulfillment'
GET_RECIPES_POS_FULFILLMENT_URL_TEMPLATE = '{domain}/api/recipes/{recipeId}/pos/fulfillment' GET_RECIPES_POS_FULFILLMENT_URL_TEMPLATE = '{domain}/api/recipes/{recipeId}/pos/fulfillment'
GET_RECIPE_POS_FULFILLMENT_URL_TEMPLATE = '{domain}/api/recipes/{recipeId}/pos/{recipePosId}/fulfillment'
def __init__(self, id=None): def __init__(self, id=None):
self.conf = Configuration() self.conf = Configuration()
@ -104,3 +103,4 @@ class Recipe(object):
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
raise e raise e

View File

@ -10,7 +10,8 @@ SCHEMA_MODEL_MAP = {
'product_groups': 'ProductGroup', 'product_groups': 'ProductGroup',
'locations': 'Location', 'locations': 'Location',
'quantity_units': 'QuantityUnit', 'quantity_units': 'QuantityUnit',
'recipe_fulfillment': 'RecipeFulfillmentResponse' 'recipe_fulfillment': 'RecipeFulfillmentResponse',
'recipe_pos_fulfillment': 'RecipePosFulfillmentResponse'
} }

View File

@ -16,15 +16,24 @@ class Util(object):
data_list = list(generator) data_list = list(generator)
return data_list return data_list
def verify_integrity(self, new_data, schema):
def verify_integrity(new_data, schema):
logger = logging.getLogger('util.verify_integrity') logger = logging.getLogger('util.verify_integrity')
try: try:
# Verify that updated fields exist # Verify that updated fields exist
schema_keys = schema['properties'].keys() if type(schema) != list:
schemas = [schema]
else:
schemas = schema
keys_not_found = []
for current_schema in schemas:
schema_keys = current_schema['properties'].keys()
for prop in new_data.keys(): for prop in new_data.keys():
if prop not in schema_keys: if prop not in schema_keys:
raise Exception('{} is not a valid field'.format(prop)) keys_not_found.append(prop)
print('{}'.format(keys_not_found))
if len(keys_not_found) > 0:
raise Exception('{} is not valid property'.format(keys_not_found.join(', ')))
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
raise e raise e

View File

@ -0,0 +1,8 @@
product_id:
amount:
qu_id:
only_check_single_unit_in_stock:
not_check_stock_fulfilment:
variable_amount:
ingredient_group:
note:

View File

@ -1,7 +1,8 @@
{% from 'recipe/macro.yml' import render_recipe_fulfilment %} {% from 'recipe/macro.yml' import render_recipe_fulfilment %}
{% for recipe in grocy.recipes %} {% for recipe in grocy.recipes %}
id: {{ recipe.fields.id }}
name: {{ recipe.fields.name }} name: {{ recipe.fields.name }}
servings: {{ recipe.fields.base_servings }} base_servings: {{ recipe.fields.base_servings }}
required_fulfilled: {{ render_recipe_fulfilment(recipe.fields.fulfillment, grocy.meta.fa_icons) }} required_fulfilled: {{ render_recipe_fulfilment(recipe.fields.fulfillment, grocy.meta.fa_icons) }}
description: |- description: |-
{{ recipe.fields.description }} {{ recipe.fields.description }}