From 3d49bc044d1eca79ca22b44300fc95f46e623dcc Mon Sep 17 00:00:00 2001 From: Emi Vasilek Date: Fri, 17 Nov 2023 21:36:26 +0100 Subject: [PATCH] currency, settings.yaml and default currency --- recipes.py | 67 ++++++++++++++++++++++++++++++++++------ schemas/ingredients.json | 3 +- schemas/settings.json | 11 +++++++ templates/base.html | 2 +- templates/recipe.html | 2 +- 5 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 schemas/settings.json diff --git a/recipes.py b/recipes.py index 2b1db35..ebaa963 100644 --- a/recipes.py +++ b/recipes.py @@ -49,6 +49,7 @@ class Issues: class Context: def __init__(self) -> None: + self.settings = Settings() self.units: AUnits = FakeUnits(self) self.default_unit = Unit(self, {"name": "piece"}) self.ingredients: AIngredients = FakeIngredients(self) @@ -70,6 +71,20 @@ class Context: jsonschema.validate(instance=ingredientsdct, schema=ingredientsschema) self.ingredients.load(ingredientsdct) + def load_settings( + self, settingsdct: Dict[str, Any], settingsschema: Dict[str, Any] + ) -> None: + jsonschema.validate(instance=settingsdct, schema=settingsschema) + self.settings.load(settingsdct) + + +class Settings: + def __init__(self) -> None: + self.default_currency: Optional[str] = None + + def load(self, settingsdct: Dict[str, Any]) -> None: + self.default_currency = settingsdct["default_currency"] + class Element: def __init__(self, ctx: Context, dct: Dict[str, Any]) -> None: @@ -249,22 +264,33 @@ class Ingredient(Element): oldelem = elem return amount - def getprice(self, amount: float, unit: Unit) -> Optional[float]: + def getprice(self, amount: float, unit: Unit) -> Optional["PriceDB"]: if "prices" not in self.dct: return None - prices: List[float] = [] + prices: List[PriceDB] = [] pricedbs: PriceDBs = self["prices"] for entry in pricedbs.pricedbs: assert isinstance(entry, PriceDB) entryamount: float = entry["amount"] entryprice: float = entry["price"] entryunit: Unit = entry["unit"] + price = 0.0 if entryunit == unit: - prices.append((amount / entryamount) * entryprice) + price = (amount / entryamount) * entryprice else: - newamount = self.convert(amount, unit, entryunit) - if newamount is not None: - prices.append((newamount / entryamount) * entryprice) + pricex = self.convert(amount, unit, entryunit) + if pricex is not None: + price = (pricex / entryamount) * entryprice + newentry = PriceDB( + self.ctx, + { + "price": price, + "amount": amount, + "unit": unit["name"], + "currency": entry["currency"], + }, + ) + prices.append(newentry) if len(prices) == 0: return None assert len(prices) == 1 @@ -334,6 +360,9 @@ class PriceDB(Element): else: self["unit"] = self.ctx.default_unit + if "currency" not in dct: + self["currency"] = self.ctx.settings.default_currency + class IngredientInstance(Element): def load(self, dct: Dict[str, Any]) -> None: @@ -393,15 +422,24 @@ class Recipe(Element): price: Optional[int] = 0 ingswithprice = 0 ingswithoutprice = 0 + currency = None for ing in ingredients: if ing["price"] is None: ingswithoutprice += 1 continue ingswithprice += 1 - price += ing["price"] - if ingswithoutprice != 0 or len(ingredients) == 0: - price = None - self["price"] = price + price += ing["price"]["price"] + cur_currency = ing["price"]["currency"] + if currency is None: + currency = cur_currency + elif currency != cur_currency: + # we don't know how to convert currencies yet + currency = None + break + if currency is None or ingswithoutprice != 0 or len(ingredients) == 0: + self["price"] = None + else: + self["price"] = PriceDB(self.ctx, {"price": price, "currency": currency}) class Builder: @@ -455,6 +493,14 @@ class Builder: self.outfiles.add(file) def load(self, dir: str) -> int: + if os.path.isfile(dir + "/settings.yaml"): + settingsdct = self.load_file(dir + "/settings.yaml") + settingsschema = self.load_file("schemas/settings.json") + self.ctx.load_settings(settingsdct, settingsschema) + retcode = self.ctx.issues.check() + if retcode != 0: + return 1 + if os.path.isfile(dir + "/units.yaml"): unitsschema = self.load_file("schemas/units.json") unitsdct = self.load_file(dir + "/units.yaml") @@ -470,6 +516,7 @@ class Builder: retcode = self.ctx.issues.check() if retcode != 0: return 1 + return 0 def run(self, dir: str) -> int: diff --git a/schemas/ingredients.json b/schemas/ingredients.json index a0257d2..c94c6af 100644 --- a/schemas/ingredients.json +++ b/schemas/ingredients.json @@ -20,7 +20,8 @@ "properties": { "price": { "type": "number" }, "amount": { "type": "integer" }, - "unit": { "type": "string" } + "unit": { "type": "string" }, + "currency": { "type": "string" } } } }, diff --git a/schemas/settings.json b/schemas/settings.json new file mode 100644 index 0000000..59c8db1 --- /dev/null +++ b/schemas/settings.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/settings.json", + "title": "Settings", + "description": "Settings", + "type": "object", + "additionalProperties": false, + "properties": { + "default_currency": { "type": "string" } + } +} diff --git a/templates/base.html b/templates/base.html index f3c4e83..cf3a0b6 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,5 +1,5 @@ {% macro price(price) -%} -{% if price == None %}?{%else%}{{price|round(1)|numprint}}{% endif %} CZK +{% if price != None and price is defined and price.price is defined %}{{price.price|round(1)|numprint}}{%else%}?{% endif %} {{price.currency}} {%- endmacro %} diff --git a/templates/recipe.html b/templates/recipe.html index da71735..01d3c57 100644 --- a/templates/recipe.html +++ b/templates/recipe.html @@ -22,7 +22,7 @@ {% for ing in rec.ingredients %}
  • {{ingredient(ing)}}
  • {% endfor %} -{% if recipe.price != None %}price: {{price(rec.price)}}{%endif%} +{% if rec.price != None %}price: {{price(rec.price)}}{%endif%} {% endif %} {% if rec.steps|length != 0 %}

    Steps