From dd6223f9808a24d4f38d06bf44d24004f133e5e2 Mon Sep 17 00:00:00 2001 From: Aerex Date: Sat, 2 Nov 2019 00:41:09 -0500 Subject: [PATCH] feat: Created chore command - feat: Added list subcommand for chore - feat: Added template for chore/list --- grocy/chore.py | 26 ++++++++++++ grocy/cli.py | 86 +++++++++++++++++++++++++--------------- grocy/entity.py | 13 +++++- grocy/shoppinglist.py | 2 +- templates/chore/list.yml | 7 ++++ 5 files changed, 99 insertions(+), 35 deletions(-) create mode 100644 grocy/chore.py create mode 100644 templates/chore/list.yml diff --git a/grocy/chore.py b/grocy/chore.py new file mode 100644 index 0000000..2ddd2a2 --- /dev/null +++ b/grocy/chore.py @@ -0,0 +1,26 @@ +import logging +from grocy.conf import Configuration +from grocy.request import Request + + +class Chore(object): + GET_CHORES_URL_TEMPLATE = '{domain}/api/chores' + + def __init__(self, id=None): + self.conf = Configuration() + self.conf.load() + self.id = id + + @property + def execution_times(self): + logger = logging.getLogger('chore.execution_times') + try: + if self.id is None: + raise Exception('chore id is required') + url = self.GET_CHORES_URL_TEMPLATE.format(domain=self.conf.domain) + request = Request('get', url) + chores = request.send() + chore = next((c for c in chores if c['chore_id'] == self.id), None) + return chore + except Exception as e: + raise e diff --git a/grocy/cli.py b/grocy/cli.py index 037b194..c49fd66 100644 --- a/grocy/cli.py +++ b/grocy/cli.py @@ -9,6 +9,7 @@ from grocy.util import Util from grocy.recipe import Recipe from grocy.table import Table from grocy.entity import Entity +from grocy.chore import Chore from grocy.stock import Stock from grocy.schema import get_schema from grocy.shoppinglist import ShoppingList @@ -462,6 +463,7 @@ def remove_ingredient(recipe_id, ingredient_id): logger.error(e) raise e + @main.group() @click.pass_context def shopping(ctx): @@ -677,42 +679,60 @@ def remove_product(shopping_id, template): # TODO: Figure out why this command is not working for new shopping lists -@shopping.command() -@click.argument('shopping_id') +#@shopping.command() +#@click.argument('shopping_id') +#@click.option('-t', 'template') +#@click.option('recipe_id', 'r') +#def add_missing_products(shopping_id, recipe_id, template): +# logger = logging.getLogger('cli.shopping.add_missing_products') +# try: +# cfg = Configuration() +# cfg.load() +# util = Util(cfg=cfg) +# +# # Validate that shopping list exists +# entity = Entity(name='shopping_lists') +# found_shopping_list = entity.get(id=shopping_id) +# if found_shopping_list is None: +# raise Exception('Shopping list does not exist') +# +# shopping_list = ShoppingList(id=shopping_id) +# except Exception as e: +# raise e + +@main.group() +def chore(): + pass + + +@chore.command() +@click.option('--name', '-n', 'name') @click.option('-t', 'template') -def add_missing_products(shopping_id, template): - logger = logging.getLogger('cli.shopping.add_missing_products') +def list(name, template): + logger = logging.getLogger('cli.shopping.list') + cfg = Configuration() + cfg.load() try: - cfg = Configuration() - cfg.load() - util = Util(cfg=cfg) + entity = Entity(name='chores') + if name: + chores = entity.find_by_name(name) + if len(chores) == 0: + return + else: + chores = entity.get() - # Validate that shopping list exists - entity = Entity(name='shopping_lists') - found_shopping_list = entity.get(id=shopping_id) - if found_shopping_list is None: - raise Exception('Shopping list does not exist') + data = {'chores': []} + for chore in chores: + chore_details = Chore(chore['id']) + chore.update(chore_details.execution_times) + data['chores'].append({'fields': chore}) - shopping_list = ShoppingList(id=shopping_id) - shopping_list.add_missing_products() + if template: + loaded_template = cfg.templates(template) + else: + loaded_template = cfg.templates('chore/list') + + click.echo(loaded_template.render(grocy=data)) except Exception as e: + logger.error(e) raise e - -#@main.command() -#@click.pass_context -#def chore(ctx): -# cfg = ctx.obj['cfg'] -# -# chore = Chore(**cfg) -# chores = chore.get_list() -# click.echo(chores) -# -#@main.command() -#@click.pass_context -#def task(ctx): -# cfg = ctx.obj['cfg'] -# -# task = Task(**cfg) -# tasks = task.get_list() -# click.echo(tasks) -# click.echo(tasks) diff --git a/grocy/entity.py b/grocy/entity.py index 81c08af..51bd015 100644 --- a/grocy/entity.py +++ b/grocy/entity.py @@ -1,4 +1,5 @@ from grocy.request import Request +from six.moves.urllib.parse import quote as encode_entity import re from copy import deepcopy from grocy.conf import Configuration @@ -7,6 +8,7 @@ import logging class Entity(object): RESOURCE_URL_TEMPLATE = '{domain}/api/objects/{entity}/{objectId}' + FIND_RESOURCE_BY_NAME = '{domain}/api/objects/{entity}/search/{name}' COLLECTION_URL_TEMPLATE = '{domain}/api/objects/{entity}' SCHEMA_URL_TEMPLATE = '{domain}/api/openapi/specification' SCHEMA_MODEL_MAP = { @@ -24,7 +26,6 @@ class Entity(object): self.name = name self.__dict__.update(**props) - def get(self, id=None): logger = logging.getLogger('entity.get') if id: @@ -58,6 +59,16 @@ class Entity(object): logger.error(e) raise e + def find_by_name(self, query): + logger = logging.getLogger('entity.find_by_name') + try: + url = self.FIND_RESOURCE_BY_NAME.format(domain=self.conf.domain, entity=self.name, name=encode_entity(query)) + request = Request('get', url) + return request.send() + except Exception as e: + logger.error(e) + raise e + def create(self, entity): logger = logging.getLogger('entity.add') url = self.COLLECTION_URL_TEMPLATE.format(domain=self.conf.domain, entity=self.name) diff --git a/grocy/shoppinglist.py b/grocy/shoppinglist.py index c4999ea..6ee6272 100644 --- a/grocy/shoppinglist.py +++ b/grocy/shoppinglist.py @@ -64,7 +64,7 @@ class ShoppingList(object): logger.eror(e) raise e - def add_missing_products(self): + def add_missing_products(self, recipe_id=None): logger = logging.getLogger('shoppinglist.add_min_stock') try: if self.id is None: diff --git a/templates/chore/list.yml b/templates/chore/list.yml new file mode 100644 index 0000000..b58a7e1 --- /dev/null +++ b/templates/chore/list.yml @@ -0,0 +1,7 @@ +{{ 'Chore' }} {{ '%15s'|format('') }} {{ 'Next estimated tracking' }} {{ '%15s'|format('') }} {{ 'Last tracked' }} +{%- for chore in grocy.chores %} +{{ chore.fields.name }} {{ '%15s'|format('') }}{%- if '2999-' in chore.fields.next_estimated_execution_time or 'Never' in chore.fields.next_estimated_execution_time %} {{'%10s'|format('---')}} +{%- else %} {{chore.fields.next_estimated_execution_time}} {%endif%} {{'%15s'|format('')}} +{%- if not chore.fields.last_tracked_time %} {{'%20s'|format('None')}} +{%- else %} {{chore.fields.last_tracked_time}}{%endif%} +{%- if loop.nextitem %}{%endif%}{%endfor%}