사례개념화 워크시트 저장 추가
This commit is contained in:
parent
7f4a2d90c7
commit
bd389a97cc
15 changed files with 614 additions and 42 deletions
|
|
@ -204,10 +204,16 @@ class ReviewWorksheetSection(BaseModel):
|
|||
|
||||
|
||||
class ReviewCaseWorksheet(BaseModel):
|
||||
status: Literal["empty", "draft_from_transcript"] = "empty"
|
||||
status: Literal["empty", "draft_from_transcript", "saved_by_learner"] = "empty"
|
||||
generatedBy: str = "rule-based transcript extractor"
|
||||
sections: list[ReviewWorksheetSection] = Field(default_factory=list)
|
||||
limitations: list[str] = Field(default_factory=list)
|
||||
savedAt: Optional[str] = None
|
||||
|
||||
|
||||
class ReviewCaseWorksheetSaveRequest(BaseModel):
|
||||
sections: list[ReviewWorksheetSection] = Field(default_factory=list)
|
||||
limitations: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class SessionReviewResponse(BaseModel):
|
||||
|
|
@ -851,6 +857,16 @@ def _case_worksheet_from_turns(turns: list[ReviewTurn]) -> ReviewCaseWorksheet:
|
|||
)
|
||||
|
||||
|
||||
def _saved_case_worksheet_from_payload(payload: dict[str, object] | None) -> ReviewCaseWorksheet | None:
|
||||
if not payload:
|
||||
return None
|
||||
try:
|
||||
worksheet = ReviewCaseWorksheet.model_validate(payload)
|
||||
except Exception:
|
||||
return None
|
||||
return worksheet.model_copy(update={"status": "saved_by_learner"})
|
||||
|
||||
|
||||
def _evaluation_payload(record: dict[str, object] | None) -> dict[str, object]:
|
||||
if not record:
|
||||
return {}
|
||||
|
|
@ -1105,7 +1121,7 @@ def _session_detail(
|
|||
SessionDetailTurn(
|
||||
turn_seq=turn.turn_seq,
|
||||
speaker="learner" if turn.speaker == "counselor" else "client",
|
||||
stage=turn.stage,
|
||||
stage=_stage_label(turn.stage),
|
||||
text=turn.text_masked,
|
||||
created_at=_iso(turn.created_at) or "",
|
||||
)
|
||||
|
|
@ -1249,7 +1265,7 @@ async def get_session_review(
|
|||
client_initial = client_name[:1] or "내"
|
||||
|
||||
reached_phase = _stage_label(sess.state.stage)
|
||||
stage_labels = [turn.stage for turn in visible_turns] or [reached_phase]
|
||||
stage_labels = [_stage_label(turn.stage) for turn in visible_turns] or [reached_phase]
|
||||
axis = ["0:00"]
|
||||
if duration_seconds > 0:
|
||||
axis.append(_offset_label(duration_seconds))
|
||||
|
|
@ -1335,6 +1351,13 @@ async def get_session_review(
|
|||
if evaluation_record and not hidden_turns and not evaluation_durable:
|
||||
summary += " 현재 평가는 런타임 캐시에서 복원되었습니다."
|
||||
|
||||
generated_worksheet = _case_worksheet_from_turns(turns)
|
||||
saved_worksheet_payload, _ = await session_persistence.load_case_worksheet(
|
||||
session_id,
|
||||
principal,
|
||||
)
|
||||
case_worksheet = _saved_case_worksheet_from_payload(saved_worksheet_payload) or generated_worksheet
|
||||
|
||||
return SessionReviewResponse(
|
||||
session_id=session_id,
|
||||
client=ReviewClient(
|
||||
|
|
@ -1359,7 +1382,7 @@ async def get_session_review(
|
|||
rubric=rubric,
|
||||
goodMoments=good_moments,
|
||||
growthPoints=growth_points,
|
||||
caseWorksheet=_case_worksheet_from_turns(turns),
|
||||
caseWorksheet=case_worksheet,
|
||||
nextLine=next_line,
|
||||
clientFeedback=client_feedback,
|
||||
audioUrl=None,
|
||||
|
|
@ -1369,6 +1392,39 @@ async def get_session_review(
|
|||
)
|
||||
|
||||
|
||||
@router.put("/{session_id}/review/worksheet", response_model=ReviewCaseWorksheet)
|
||||
async def save_session_review_worksheet(
|
||||
session_id: str,
|
||||
body: ReviewCaseWorksheetSaveRequest,
|
||||
principal: CurrentPrincipal,
|
||||
) -> ReviewCaseWorksheet:
|
||||
"""Persist the learner's edited case formulation worksheet for this session."""
|
||||
_ensure_learner(principal)
|
||||
await _load_session_or_404(
|
||||
session_id,
|
||||
principal,
|
||||
allow_ended=True,
|
||||
include_turn_evaluation=False,
|
||||
)
|
||||
worksheet = ReviewCaseWorksheet(
|
||||
status="saved_by_learner",
|
||||
generatedBy="learner-edited worksheet",
|
||||
sections=body.sections,
|
||||
limitations=body.limitations,
|
||||
)
|
||||
ok = await session_persistence.save_case_worksheet(
|
||||
session_id=session_id,
|
||||
learner_id=principal.user_id,
|
||||
payload=worksheet.model_dump(mode="json"),
|
||||
)
|
||||
if not ok:
|
||||
raise HTTPException(
|
||||
status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
detail="case worksheet persistence unavailable",
|
||||
)
|
||||
return worksheet
|
||||
|
||||
|
||||
@router.post("/{session_id}/turn", response_model=TurnResponse)
|
||||
async def submit_turn(
|
||||
session_id: str,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue