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:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,4 +3,5 @@ test.php
|
|||||||
.env
|
.env
|
||||||
**/__pycache__
|
**/__pycache__
|
||||||
database.db*
|
database.db*
|
||||||
.idea
|
.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]
|
[project.scripts]
|
||||||
apply-subscriptions = "meal_manager.scripts:apply_subscriptions"
|
apply-subscriptions = "meal_manager.scripts:apply_subscriptions_cli"
|
||||||
|
|
||||||
|
|
||||||
[tool.isort]
|
[tool.isort]
|
||||||
@@ -36,7 +36,7 @@ profile = "black"
|
|||||||
# this is typically a path given in POSIX (e.g. forward slashes)
|
# 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
|
# format, relative to the token %(here)s which refers to the location of this
|
||||||
# ini file
|
# 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
|
# 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
|
# 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"),
|
sa.PrimaryKeyConstraint("household_id"),
|
||||||
)
|
)
|
||||||
op.create_table(
|
op.create_table(
|
||||||
"team_registration",
|
"teamregistration",
|
||||||
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
|
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
|
||||||
sa.Column("event_id", sa.Integer(), nullable=False),
|
sa.Column("event_id", sa.Integer(), nullable=False),
|
||||||
sa.Column("person_name", sa.String(), 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_min: Mapped[int] = mapped_column(default=1, nullable=False)
|
||||||
team_prep_max: 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(
|
registrations: Mapped[list["Registration"]] = relationship(
|
||||||
"Registration", cascade="all, delete"
|
"Registration", cascade="all, delete"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,33 +1,38 @@
|
|||||||
import argparse
|
import argparse
|
||||||
|
import datetime
|
||||||
|
|
||||||
from sqlalchemy import select
|
from sqlalchemy import Date, cast, func, select
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from meal_manager.main import engine
|
from meal_manager.main import engine
|
||||||
from meal_manager.models import Event, Registration, Subscription
|
from meal_manager.models import Event, Registration, Subscription
|
||||||
|
|
||||||
|
|
||||||
def apply_subscriptions():
|
def apply_subscriptions(session: Session, event: Event = None, dry_run: bool = False):
|
||||||
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()
|
subscriptions = session.scalars(select(Subscription)).all()
|
||||||
|
|
||||||
# Access the arguments
|
if event is not None:
|
||||||
event_id = args.event_id
|
events = [event]
|
||||||
dry_run = args.dry_run
|
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:
|
if len(events) == 0:
|
||||||
subscriptions = session.scalars(select(Subscription)).all()
|
print("No events to process")
|
||||||
event = session.scalars(select(Event).where(Event.id == event_id)).one()
|
return
|
||||||
|
|
||||||
|
for event in events:
|
||||||
if dry_run:
|
if dry_run:
|
||||||
print(f"DRY RUN: Would process event {event_id}")
|
print(f"DRY RUN: Would process event {event.title} ({event.id})")
|
||||||
else:
|
else:
|
||||||
print(f"Processing event {event_id}")
|
print(f"Processing event {event.title} ({event.id})")
|
||||||
|
|
||||||
print(f"There are {len(subscriptions)} subscriptions to process")
|
print(f"There are {len(subscriptions)} subscriptions to process")
|
||||||
relevant_subscriptions = [
|
relevant_subscriptions = [
|
||||||
@@ -60,6 +65,28 @@ def apply_subscriptions():
|
|||||||
else:
|
else:
|
||||||
session.add(reg)
|
session.add(reg)
|
||||||
print(f"Registered {subscription.household.name}")
|
print(f"Registered {subscription.household.name}")
|
||||||
|
event.subscriptions_applied = True
|
||||||
|
|
||||||
if not dry_run:
|
if not dry_run:
|
||||||
session.commit()
|
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