Improve apply_subscriptions

Events now have a subscriptions_applied flag. Using apply_subscriptions without passing an event now processes all events in the next week, which have not yet been processed
This commit is contained in:
2025-10-27 15:32:00 +01:00
parent a2722d5f9f
commit b687a260c5
8 changed files with 95 additions and 22 deletions

View File

@@ -1,43 +0,0 @@
# A generic, single database configuration.
[alembic]
# database URL. This is consumed by the user-maintained env.py script only.
# other means of configuring database URLs may be customized within the env.py
# file.
sqlalchemy.url = sqlite:///database.db
# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = WARNING
handlers = console
qualname =
[logger_sqlalchemy]
level = WARNING
handlers =
qualname = sqlalchemy.engine
[logger_alembic]
level = INFO
handlers =
qualname = alembic
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S

View File

@@ -84,7 +84,7 @@ def upgrade() -> None:
sa.PrimaryKeyConstraint("household_id"),
)
op.create_table(
"team_registration",
"teamregistration",
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
sa.Column("event_id", sa.Integer(), nullable=False),
sa.Column("person_name", sa.String(), nullable=False),

View File

@@ -0,0 +1,34 @@
"""Add subscriptions_applied column to Event
Revision ID: 13084c5c1f68
Revises: 299a83240036
Create Date: 2025-10-27 12:25:14.633641
"""
from typing import Sequence, Union
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision: str = "13084c5c1f68"
down_revision: Union[str, Sequence[str], None] = "299a83240036"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"event", sa.Column("subscriptions_applied", sa.Boolean(), nullable=False)
)
# ### end Alembic commands ###
def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("event", "subscriptions_applied")
# ### end Alembic commands ###

View File

@@ -33,6 +33,8 @@ class Event(Base):
team_prep_min: Mapped[int] = mapped_column(default=1, nullable=False)
team_prep_max: Mapped[int] = mapped_column(default=1, nullable=False)
subscriptions_applied: Mapped[bool] = mapped_column(default=False, nullable=False)
registrations: Mapped[list["Registration"]] = relationship(
"Registration", cascade="all, delete"
)

View File

@@ -1,33 +1,38 @@
import argparse
import datetime
from sqlalchemy import select
from sqlalchemy import Date, cast, func, 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"
)
def apply_subscriptions(session: Session, event: Event = None, dry_run: bool = False):
args = parser.parse_args()
subscriptions = session.scalars(select(Subscription)).all()
# Access the arguments
event_id = args.event_id
dry_run = args.dry_run
if event is not None:
events = [event]
else:
today = datetime.date.today()
query = select(Event).where(
~Event.subscriptions_applied,
func.strftime("%Y-%m-%d %H:%M:%S", Event.event_time) >= today.isoformat(),
func.strftime("%Y-%m-%d %H:%M:%S", Event.event_time)
<= (today + datetime.timedelta(days=7)).isoformat(),
)
events = session.scalars(query).all()
with Session(engine) as session:
subscriptions = session.scalars(select(Subscription)).all()
event = session.scalars(select(Event).where(Event.id == event_id)).one()
if len(events) == 0:
print("No events to process")
return
for event in events:
if dry_run:
print(f"DRY RUN: Would process event {event_id}")
print(f"DRY RUN: Would process event {event.title} ({event.id})")
else:
print(f"Processing event {event_id}")
print(f"Processing event {event.title} ({event.id})")
print(f"There are {len(subscriptions)} subscriptions to process")
relevant_subscriptions = [
@@ -60,6 +65,28 @@ def apply_subscriptions():
else:
session.add(reg)
print(f"Registered {subscription.household.name}")
event.subscriptions_applied = True
if not dry_run:
session.commit()
if not dry_run:
session.commit()
def apply_subscriptions_cli():
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:
if event_id is not None:
event = session.scalars(select(Event).where(Event.id == event_id)).one()
apply_subscriptions(session, event, dry_run)
else:
apply_subscriptions(session, dry_run=dry_run)