You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
3.8 KiB
Python

# backend/app/routers/trip.py
from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import Session, select
from ..agents.travel_agent import run_planner
from ..auth.deps import current_user
from ..auth.scope import scoped
from ..db import get_session
from ..models import (
Person,
SavedTrip,
Trip,
TripChecklist,
TripDay,
TripPrep,
TripRoute,
TripStay,
)
from ..schemas import (
PlanRequest,
PlanResultOut,
SavedTripOut,
UpcomingTripOut,
WatchToggleRequest,
)
router = APIRouter()
def _saved_out(r: SavedTrip) -> SavedTripOut:
return SavedTripOut(
id=r.id,
title=r.title,
tag=r.tag,
note=r.note,
now=r.now,
delta=r.delta,
down=r.down,
watch=r.watch,
hint=r.hint,
spark=r.spark,
)
@router.get("/trip/upcoming", response_model=UpcomingTripOut)
def upcoming(s: Session = Depends(get_session), user: Person = Depends(current_user)):
trip = s.exec(scoped(select(Trip), Trip, user.id)).first()
if not trip:
raise HTTPException(404, "no trip")
routes = {
r.dir: {
"mode": r.mode,
"from": r.from_st,
"ft": r.ft,
"to": r.to_st,
"tt": r.tt,
"seat": r.seat,
"note": r.note,
}
for r in s.exec(select(TripRoute).where(TripRoute.trip_id == trip.id)).all()
}
stay = s.exec(select(TripStay).where(TripStay.trip_id == trip.id)).first()
preps = s.exec(
select(TripPrep).where(TripPrep.trip_id == trip.id).order_by(TripPrep.sort_order)
).all()
days = s.exec(
select(TripDay).where(TripDay.trip_id == trip.id).order_by(TripDay.sort_order)
).all()
checks = s.exec(
select(TripChecklist)
.where(TripChecklist.trip_id == trip.id)
.order_by(TripChecklist.sort_order)
).all()
# check 그룹화 (group → items[])
groups: list[dict] = []
gindex: dict[str, int] = {}
for c in checks:
if c.group not in gindex:
gindex[c.group] = len(groups)
groups.append({"name": c.group, "items": []})
item = {"id": c.id, "text": c.text}
if c.auto:
item["auto"] = c.auto
groups[gindex[c.group]]["items"].append(item)
return UpcomingTripOut(
trip={
"id": trip.id,
"dday": trip.dday,
"title": trip.title,
"dates": trip.dates,
"purpose": trip.purpose,
"brief": trip.brief,
"weather": trip.weather,
},
route=routes,
stay=({"name": stay.name, "desc": stay.desc, "conf": stay.conf} if stay else {}),
prep=[{"text": p.text, "state": p.state} for p in preps],
days=[{"id": d.id, "tab": d.tab, "items": d.items} for d in days],
check=groups,
expense={
"budget": trip.expense_budget,
"planned": trip.expense_planned,
"rows": trip.expense_rows,
"note": trip.expense_note,
},
)
@router.get("/trip/saved", response_model=list[SavedTripOut])
def saved(s: Session = Depends(get_session)):
rows = s.exec(select(SavedTrip).order_by(SavedTrip.sort_order)).all()
return [_saved_out(r) for r in rows]
@router.post("/trip/saved/{sid}/watch", response_model=SavedTripOut)
def toggle_watch(sid: str, req: WatchToggleRequest, s: Session = Depends(get_session)):
r = s.get(SavedTrip, sid)
if not r:
raise HTTPException(404, "no saved trip")
r.watch = req.watch if req.watch is not None else (not r.watch)
s.add(r)
s.commit()
s.refresh(r)
return _saved_out(r)
@router.post("/trip/plan", response_model=PlanResultOut)
def plan(req: PlanRequest, s: Session = Depends(get_session)):
return run_planner(s, req.text)