from datetime import datetime from sqlalchemy import select from sqlalchemy.orm import Session from app.models import Item from app.stages import is_valid_stage DONE_STAGES = {"done", "logged_in_bookmark"} def create_item( session: Session, *, modality: str, raw_content: str, captured_at: datetime, discord_message_id: str | None, sender_id: str | None = None, direction: str = "inbound", ) -> tuple[Item, bool]: if discord_message_id is not None: existing = session.scalar( select(Item).where(Item.discord_message_id == discord_message_id) ) if existing is not None: return existing, False item = Item( modality=modality, raw_content=raw_content, captured_at=captured_at, discord_message_id=discord_message_id, sender_id=sender_id, direction=direction, stage="new", ) session.add(item) session.commit() session.refresh(item) return item, True def list_items( session: Session, *, stage: str | None = None, modality: str | None = None, include_done: bool = False, ) -> list[Item]: stmt = select(Item) if stage is not None: stmt = stmt.where(Item.stage == stage) if modality is not None: stmt = stmt.where(Item.modality == modality) if not include_done: stmt = stmt.where(Item.stage.not_in(DONE_STAGES)) stmt = stmt.order_by(Item.captured_at.desc()) return list(session.scalars(stmt)) def get_item(session: Session, item_id: int) -> Item | None: return session.get(Item, item_id) def update_item(session: Session, item_id: int, **fields) -> Item | None: item = session.get(Item, item_id) if item is None: return None new_type = fields.get("type", item.type) new_stage = fields.get("stage", item.stage) new_direction = fields.get("direction", item.direction) if "stage" in fields and not is_valid_stage(new_type, new_stage, new_direction): raise ValueError( f"'{new_stage}' is not a valid stage for type '{new_type}' direction '{new_direction}'" ) for key, value in fields.items(): setattr(item, key, value) session.commit() session.refresh(item) return item