Skip to content

Commit c06d78d

Browse files
committed
refactor(db_goals): 拆毕业报告域收敛至 88 行门面
1 parent 6c33318 commit c06d78d

3 files changed

Lines changed: 64 additions & 45 deletions

File tree

‎app/src-tauri/src/db_goals.rs‎

Lines changed: 4 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@
88
//! goal_groups 随组删除级联清除,goal_milestones.ref_group_id
99
//! SET NULL(绑定组被删 → 里程碑降级手动判定,提示 UI 属 M2)。
1010
11-
use rusqlite::{params, Connection};
11+
use rusqlite::Connection;
1212

13-
use crate::db::{unix_seconds, Db};
1413
use crate::error::Result;
1514

1615
// 子模块声明(AGENTS.md §3 单文件 ≤300 行;#[path] 使兄弟文件平铺在同目录,各自带 @ai-context)。
@@ -29,6 +28,9 @@ mod retro;
2928
/// 绑定域:目标↔组绑定 + 组结算钩子。
3029
#[path = "db_goals_binding.rs"]
3130
mod binding;
31+
/// 毕业报告域:goal_graduation_reports 快照表读写。
32+
#[path = "db_goals_graduation.rs"]
33+
mod graduation;
3234

3335
/// 三表 DDL + 索引(幂等:CREATE TABLE IF NOT EXISTS;旧库升级自动补表)。
3436
pub(crate) fn init(conn: &Connection) -> Result<()> {
@@ -81,48 +83,6 @@ pub(crate) fn init(conn: &Connection) -> Result<()> {
8183
Ok(())
8284
}
8385

84-
impl Db {
85-
86-
// ─────────────────────── v0.18.1 毕业报告(REQ-255/256) ───────────────────────
87-
88-
/// 写毕业报告快照(目标删除后保留;goal_id SET NULL——报告独立于 goals 行)。
89-
pub fn create_graduation_report(&self, goal_id: i64, goal_name: &str, report_json: &str) -> Result<i64> {
90-
self.with_conn(|conn| {
91-
conn.execute(
92-
"INSERT INTO goal_graduation_reports (goal_id, goal_name, report_json, created_at)
93-
VALUES (?1, ?2, ?3, ?4)",
94-
params![goal_id, goal_name, report_json, unix_seconds()],
95-
)?;
96-
Ok(conn.last_insert_rowid())
97-
})
98-
}
99-
100-
/// 目标的毕业报告 JSON(无 → None——毕业仪式只发一次,防重复确认;
101-
/// 解析在命令层——AppError 无 serde 变体,存储态原样返回)。
102-
pub fn get_graduation_report_json(&self, goal_id: i64) -> Result<Option<String>> {
103-
self.with_conn(|conn| {
104-
let mut stmt = conn.prepare(
105-
"SELECT report_json FROM goal_graduation_reports WHERE goal_id = ?1 ORDER BY id DESC LIMIT 1",
106-
)?;
107-
let mut rows = stmt.query_map(params![goal_id], |r| r.get::<_, String>(0))?;
108-
match rows.next() {
109-
Some(Ok(json)) => Ok(Some(json)),
110-
Some(Err(e)) => Err(e.into()),
111-
None => Ok(None),
112-
}
113-
})
114-
}
115-
116-
/// 全部毕业报告 JSON(档案区;已删目标的报告仍列出——解析在命令层)。
117-
pub fn list_graduation_reports_json(&self) -> Result<Vec<String>> {
118-
self.with_conn(|conn| {
119-
let mut stmt = conn.prepare("SELECT report_json FROM goal_graduation_reports ORDER BY id ASC")?;
120-
let rows = stmt.query_map([], |r| r.get::<_, String>(0))?;
121-
rows.collect::<rusqlite::Result<Vec<_>>>().map_err(Into::into)
122-
})
123-
}
124-
}
125-
12686
#[cfg(test)]
12787
#[path = "db_goals_tests.rs"]
12888
mod tests;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//! 毕业报告域:goal_graduation_reports 快照表读写(v0.18.1 REQ-255/256)。
2+
//!
3+
//! @ai-context: 由 db_goals.rs 按域拆出(AGENTS.md §3 单文件 ≤300 行)。快照表 FK
4+
//! goal_id ON DELETE SET NULL ⇒ 目标删除后报告仍可读(毕业档案区);
5+
//! goal_name 冗余列即为此保留(同 notes_versions「回滚不破坏历史」哲学)。
6+
//! @ai-context: 报告 JSON 的解析在命令层(AppError 无 serde 变体)——本文件只存取
7+
//! 字符串;单份读 ORDER BY id DESC LIMIT 1 与全量读 ORDER BY id ASC 的
8+
//! 不对称是既有口径(勿顺手统一)。
9+
10+
use rusqlite::params;
11+
12+
use crate::db::{unix_seconds, Db};
13+
use crate::error::Result;
14+
15+
impl Db {
16+
// ─────────────────────── v0.18.1 毕业报告(REQ-255/256) ───────────────────────
17+
18+
/// 写毕业报告快照(目标删除后保留;goal_id SET NULL——报告独立于 goals 行)。
19+
pub fn create_graduation_report(&self, goal_id: i64, goal_name: &str, report_json: &str) -> Result<i64> {
20+
self.with_conn(|conn| {
21+
conn.execute(
22+
"INSERT INTO goal_graduation_reports (goal_id, goal_name, report_json, created_at)
23+
VALUES (?1, ?2, ?3, ?4)",
24+
params![goal_id, goal_name, report_json, unix_seconds()],
25+
)?;
26+
Ok(conn.last_insert_rowid())
27+
})
28+
}
29+
30+
/// 目标的毕业报告 JSON(无 → None——毕业仪式只发一次,防重复确认;
31+
/// 解析在命令层——AppError 无 serde 变体,存储态原样返回)。
32+
pub fn get_graduation_report_json(&self, goal_id: i64) -> Result<Option<String>> {
33+
self.with_conn(|conn| {
34+
let mut stmt = conn.prepare(
35+
"SELECT report_json FROM goal_graduation_reports WHERE goal_id = ?1 ORDER BY id DESC LIMIT 1",
36+
)?;
37+
let mut rows = stmt.query_map(params![goal_id], |r| r.get::<_, String>(0))?;
38+
match rows.next() {
39+
Some(Ok(json)) => Ok(Some(json)),
40+
Some(Err(e)) => Err(e.into()),
41+
None => Ok(None),
42+
}
43+
})
44+
}
45+
46+
/// 全部毕业报告 JSON(档案区;已删目标的报告仍列出——解析在命令层)。
47+
pub fn list_graduation_reports_json(&self) -> Result<Vec<String>> {
48+
self.with_conn(|conn| {
49+
let mut stmt = conn.prepare("SELECT report_json FROM goal_graduation_reports ORDER BY id ASC")?;
50+
let rows = stmt.query_map([], |r| r.get::<_, String>(0))?;
51+
rows.collect::<rusqlite::Result<Vec<_>>>().map_err(Into::into)
52+
})
53+
}
54+
}

0 commit comments

Comments
 (0)