From a1bb50087b62ecae12461403b5c4b91e329617b3 Mon Sep 17 00:00:00 2001 From: Niklas Meinzer Date: Thu, 16 Oct 2025 12:11:27 +0200 Subject: [PATCH] Feat: Add script to apply subscriptions --- pyproject.toml | 5 +++ src/meal_manager/models.py | 14 +++++++- src/meal_manager/scripts.py | 65 +++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 src/meal_manager/scripts.py diff --git a/pyproject.toml b/pyproject.toml index 3b7a5fd..4ab8653 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,11 @@ dev = [ "black>=25.1.0", "isort>=6.0.1", ] + +[project.scripts] +apply-subscriptions = "meal_manager.scripts:apply_subscriptions" + + [tool.isort] profile = "black" diff --git a/src/meal_manager/models.py b/src/meal_manager/models.py index c261c99..38ceec9 100644 --- a/src/meal_manager/models.py +++ b/src/meal_manager/models.py @@ -1,5 +1,5 @@ import typing -from datetime import datetime +from datetime import date, datetime from sqlalchemy import ForeignKey from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship @@ -153,3 +153,15 @@ class Subscription(Base): return ", ".join(result) else: return "Alle" + + def valid_on(self, date: date) -> bool: + weekday = date.weekday() + return { + 0: self.monday, + 1: self.tuesday, + 2: self.wednesday, + 3: self.thursday, + 4: self.friday, + 5: self.saturday, + 6: self.sunday, + }[weekday] diff --git a/src/meal_manager/scripts.py b/src/meal_manager/scripts.py new file mode 100644 index 0000000..b663181 --- /dev/null +++ b/src/meal_manager/scripts.py @@ -0,0 +1,65 @@ +import argparse + +from sqlalchemy import select +from sqlalchemy.orm import Session + +from meal_manager.main import engine +from meal_manager.models import Event, Registration, Subscription + + +def apply_subscriptions(): + parser = argparse.ArgumentParser(description="Apply subscriptions for an event") + parser.add_argument("event_id", type=int, help="Event ID (required)") + parser.add_argument( + "--dry-run", action="store_true", help="Run without making changes" + ) + + args = parser.parse_args() + + # Access the arguments + event_id = args.event_id + dry_run = args.dry_run + + with Session(engine) as session: + subscriptions = session.scalars(select(Subscription)).all() + event = session.scalars(select(Event).where(Event.id == event_id)).one() + + if dry_run: + print(f"DRY RUN: Would process event {event_id}") + else: + print(f"Processing event {event_id}") + + print(f"There are {len(subscriptions)} subscriptions to process") + relevant_subscriptions = [ + s for s in subscriptions if s.valid_on(event.event_time.date()) + ] + print(f"{len(relevant_subscriptions)} of them are relevant to this event") + + for subscription in relevant_subscriptions: + existing_registration = session.scalars( + select(Registration).where( + Registration.event_id == event.id, + Registration.household_id == subscription.household_id, + ) + ).one_or_none() + if existing_registration: + print( + f"There is already a registration for {subscription.household.name}. Skipping subscription." + ) + continue + reg = Registration( + event_id=event.id, + household_id=subscription.household_id, + num_adult_meals=subscription.num_adult_meals, + num_children_meals=subscription.num_children_meals, + num_small_children_meals=subscription.num_small_children_meals, + comment="Dauerhafte Anmeldung", + ) + if dry_run: + print(f"DRY RUN: Would register {subscription.household.name}") + else: + session.add(reg) + print(f"Registered {subscription.household.name}") + + if not dry_run: + session.commit()