fixed salattheke prices
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
import logging
|
||||
import re
|
||||
from datetime import datetime, date
|
||||
from stw_potsdam.xml_types.canteen_xml import CanteenMeta, CanteenXML
|
||||
from stw_potsdam.xml_types.times_xml import CanteenOpenTimespec, TimesXML
|
||||
from stw_potsdam.xml_types.meal_xml import MealXML
|
||||
|
||||
|
||||
EURO_PRICE_PATTERN = re.compile(r"(\d+(?:[,.]\d{1,2})?)\s*€")
|
||||
|
||||
|
||||
class SWPWebspeiseplanParser:
|
||||
"""Class method to parse SWP_Webspeiseplan."""
|
||||
|
||||
@@ -56,6 +60,42 @@ class SWPWebspeiseplanParser:
|
||||
canteen = CanteenXML(canteen_meta, canteen_times)
|
||||
return canteen
|
||||
|
||||
def _parse_price(self, value):
|
||||
if value in (None, "", {}):
|
||||
return None
|
||||
return float(str(value).replace(",", "."))
|
||||
|
||||
def _parse_embedded_prices(
|
||||
self, name: str, price: dict[str, float | None]
|
||||
) -> tuple[str, dict[str, float | None]]:
|
||||
if any(price.values()):
|
||||
return name, price
|
||||
|
||||
matches = EURO_PRICE_PATTERN.findall(name)
|
||||
if len(matches) < 2:
|
||||
return name, price
|
||||
|
||||
parsed = [self._parse_price(match) for match in matches]
|
||||
if len(parsed) >= 3:
|
||||
price = {
|
||||
"student": parsed[0],
|
||||
"employee": parsed[1],
|
||||
"other": parsed[2],
|
||||
}
|
||||
elif "Stud" in name and ("Gäste" in name or "Gaeste" in name):
|
||||
price = {
|
||||
"student": parsed[0],
|
||||
"employee": price["employee"],
|
||||
"other": parsed[1],
|
||||
}
|
||||
else:
|
||||
return name, price
|
||||
|
||||
name = EURO_PRICE_PATTERN.sub("", name)
|
||||
name = re.sub(r"\s*/\s*", " ", name)
|
||||
name = re.sub(r"\s+", " ", name).strip()
|
||||
return name, price
|
||||
|
||||
def parse_meals(
|
||||
self, menu_data, meal_categories
|
||||
) -> list[tuple[date, str, MealXML]]:
|
||||
@@ -66,11 +106,20 @@ class SWPWebspeiseplanParser:
|
||||
info = meal_data["speiseplanAdvancedGericht"]
|
||||
additional_info = meal_data["zusatzinformationen"]
|
||||
price = {
|
||||
"student": additional_info["mitarbeiterpreisDecimal2"],
|
||||
"employee": additional_info["price3Decimal2"],
|
||||
"other": additional_info["gaestepreisDecimal2"],
|
||||
"student": self._parse_price(
|
||||
additional_info["mitarbeiterpreisDecimal2"]
|
||||
),
|
||||
"employee": self._parse_price(
|
||||
additional_info["price3Decimal2"]
|
||||
),
|
||||
"other": self._parse_price(
|
||||
additional_info["gaestepreisDecimal2"]
|
||||
),
|
||||
}
|
||||
meal = MealXML(name=info["gerichtname"], price=price)
|
||||
name, price = self._parse_embedded_prices(
|
||||
info["gerichtname"], price
|
||||
)
|
||||
meal = MealXML(name=name, price=price)
|
||||
day = datetime.fromisoformat(info["datum"]).date()
|
||||
category = meal_categories[info["gerichtkategorieID"]]["name"]
|
||||
meals.append(
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
from stw_potsdam.swp_webspeiseplan_parser import SWPWebspeiseplanParser
|
||||
|
||||
|
||||
def _menu_item(name):
|
||||
return [
|
||||
{
|
||||
"speiseplanGerichtData": [
|
||||
{
|
||||
"speiseplanAdvancedGericht": {
|
||||
"datum": "2026-05-01T00:00:00",
|
||||
"gerichtkategorieID": 1,
|
||||
"gerichtname": name,
|
||||
},
|
||||
"zusatzinformationen": {
|
||||
"mitarbeiterpreisDecimal2": 0,
|
||||
"price3Decimal2": 0,
|
||||
"gaestepreisDecimal2": 0,
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def _parse_meal(name):
|
||||
parser = SWPWebspeiseplanParser()
|
||||
meals = parser.parse_meals(_menu_item(name), {1: {"name": "Salattheke"}})
|
||||
return meals[0]["meal"]
|
||||
|
||||
|
||||
def test_parse_salad_bar_three_embedded_prices():
|
||||
meal = _parse_meal(
|
||||
"große Schale kleine Schale Relevo Schale 100g "
|
||||
"1,10 €/ 1,70 €/ 1,90€"
|
||||
)
|
||||
|
||||
assert meal.name == "große Schale kleine Schale Relevo Schale 100g"
|
||||
assert meal.price == {
|
||||
"student": 1.10,
|
||||
"employee": 1.70,
|
||||
"other": 1.90,
|
||||
}
|
||||
|
||||
|
||||
def test_parse_salad_bar_student_guest_embedded_prices():
|
||||
meal = _parse_meal(
|
||||
"große Schale\nkleine Schale\nRelevo Schale\n"
|
||||
"100g Stud. 1,00€/ Gäste 1,45€"
|
||||
)
|
||||
|
||||
assert meal.name == (
|
||||
"große Schale kleine Schale Relevo Schale 100g Stud. Gäste"
|
||||
)
|
||||
assert meal.price == {
|
||||
"student": 1.00,
|
||||
"employee": 0.0,
|
||||
"other": 1.45,
|
||||
}
|
||||
Reference in New Issue
Block a user