complete_contract
Finalize a teaching contract by recording a completion note once every covered course is completion-ready, preventing invalid completions and ensuring idempotent replay.
Instructions
把一份合约收作结业 (State 2.0 文书三幕剧: 立约 → 履约 → 结业, 迁移 0030) —— completed_at/completion_note 是与 established(签约)/voided(作废)并列的第三种终态, 不是覆盖关系。completion_note 是结业词——给这段学习旅程的证词, 认真写, 不是流程按钮上敷衍一句"完成了"。前置校验, 任一条不满足即结构化拒绝并附差额: ① 合约现役(经 lib/currentContract 判定路径——未签/已作废/已过终态一律拒绝); ② covered_course_ids 非空(先 update_contract_coverage 或建课时带 contract_id 把教过的课挂上); ③ 覆盖单里每门课须 goal_completion_ready (见 get_context 的 contract_progress) —— 全部已发布课 learning 状态 ∈ {completed_declared, closed} (未发布的课不计入), 且课程定过 planned_lesson_count 并已发布节数够数——没定过计划节数的课不再放行。不满足则回执附结构化差额, 分两种: 缺 planned_lesson_count (missing_planned_count) 或已发布节数不足计划 (below_planned_count), 外加"哪门课还差几节未读完"的清单, 不是一句"没教完"。幂等: 已结业的合约重复调用原样返回既有结业词, 不报错、不二次写入。
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| contract_id | Yes | 必须是已存在的 teaching_contracts id. | |
| completion_note | Yes | 结业词(必填非空)——这段学习旅程的证词, 认真写. | |
| idempotency_key | No | 可选。幂等键 (建议 uuid) —— 同一 key 重放此调用返回首次结果, 不重复写入. 网络重试/断线重连时带上同一个 key, 而不是猜"上次到底写没写". |