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:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ test.php
|
||||
**/__pycache__
|
||||
database.db*
|
||||
.idea
|
||||
db_fixtures
|
||||
9
justfile
Normal file
9
justfile
Normal file
@@ -0,0 +1,9 @@
|
||||
lint:
|
||||
uv run isort src
|
||||
uv run black src
|
||||
|
||||
reset_db:
|
||||
rm -f database.db
|
||||
touch database.db
|
||||
alembic upgrade heads
|
||||
bash -c 'shopt -s nullglob; for file in db_fixtures/*.sql; do sqlite3 database.db < "$file"; done'
|
||||
@@ -24,7 +24,7 @@ dev = [
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
apply-subscriptions = "meal_manager.scripts:apply_subscriptions"
|
||||
apply-subscriptions = "meal_manager.scripts:apply_subscriptions_cli"
|
||||
|
||||
|
||||
[tool.isort]
|
||||
@@ -36,7 +36,7 @@ profile = "black"
|
||||
# this is typically a path given in POSIX (e.g. forward slashes)
|
||||
# format, relative to the token %(here)s which refers to the location of this
|
||||
# ini file
|
||||
script_location = "%(here)s/alembic"
|
||||
script_location = "%(here)s/src/meal_manager/alembic"
|
||||
|
||||
# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
|
||||
# Uncomment the line below if you want the files to be prepended with date and time
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 ###
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
|
||||
# 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}")
|
||||
if event is not None:
|
||||
events = [event]
|
||||
else:
|
||||
print(f"Processing event {event_id}")
|
||||
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()
|
||||
|
||||
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.title} ({event.id})")
|
||||
else:
|
||||
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()
|
||||
|
||||
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user