chorus/backend/app/crud.py

82 lines
2.2 KiB
Python

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