feat: timesheet row persistence backend
This commit is contained in:
@@ -2407,6 +2407,73 @@ pub fn delete_entry_template(state: State<AppState>, id: i64) -> Result<(), Stri
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_timesheet_rows(state: State<AppState>, week_start: String) -> Result<Vec<serde_json::Value>, String> {
|
||||
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT id, week_start, project_id, task_id, sort_order FROM timesheet_rows WHERE week_start = ?1 ORDER BY sort_order"
|
||||
).map_err(|e| e.to_string())?;
|
||||
let rows = stmt.query_map(params![week_start], |row| {
|
||||
Ok(serde_json::json!({
|
||||
"id": row.get::<_, i64>(0)?,
|
||||
"week_start": row.get::<_, String>(1)?,
|
||||
"project_id": row.get::<_, i64>(2)?,
|
||||
"task_id": row.get::<_, Option<i64>>(3)?,
|
||||
"sort_order": row.get::<_, i64>(4)?,
|
||||
}))
|
||||
}).map_err(|e| e.to_string())?;
|
||||
Ok(rows.filter_map(|r| r.ok()).collect())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn save_timesheet_rows(state: State<AppState>, week_start: String, rows: Vec<serde_json::Value>) -> Result<(), String> {
|
||||
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||
conn.execute("BEGIN TRANSACTION", []).map_err(|e| e.to_string())?;
|
||||
|
||||
if let Err(e) = conn.execute("DELETE FROM timesheet_rows WHERE week_start = ?1", params![week_start]) {
|
||||
let _ = conn.execute("ROLLBACK", []);
|
||||
return Err(e.to_string());
|
||||
}
|
||||
|
||||
for (i, row) in rows.iter().enumerate() {
|
||||
let project_id = row.get("project_id").and_then(|v| v.as_i64()).unwrap_or(0);
|
||||
let task_id = row.get("task_id").and_then(|v| v.as_i64());
|
||||
if let Err(e) = conn.execute(
|
||||
"INSERT INTO timesheet_rows (week_start, project_id, task_id, sort_order) VALUES (?1, ?2, ?3, ?4)",
|
||||
params![week_start, project_id, task_id, i as i64],
|
||||
) {
|
||||
let _ = conn.execute("ROLLBACK", []);
|
||||
return Err(e.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
conn.execute("COMMIT", []).map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_previous_week_structure(state: State<AppState>, current_week_start: String) -> Result<Vec<serde_json::Value>, String> {
|
||||
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||
let current = chrono::NaiveDate::parse_from_str(¤t_week_start, "%Y-%m-%d")
|
||||
.map_err(|e| e.to_string())?;
|
||||
let prev = current - chrono::Duration::days(7);
|
||||
let prev_str = prev.format("%Y-%m-%d").to_string();
|
||||
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT id, week_start, project_id, task_id, sort_order FROM timesheet_rows WHERE week_start = ?1 ORDER BY sort_order"
|
||||
).map_err(|e| e.to_string())?;
|
||||
let rows = stmt.query_map(params![prev_str], |row| {
|
||||
Ok(serde_json::json!({
|
||||
"id": row.get::<_, i64>(0)?,
|
||||
"week_start": row.get::<_, String>(1)?,
|
||||
"project_id": row.get::<_, i64>(2)?,
|
||||
"task_id": row.get::<_, Option<i64>>(3)?,
|
||||
"sort_order": row.get::<_, i64>(4)?,
|
||||
}))
|
||||
}).map_err(|e| e.to_string())?;
|
||||
Ok(rows.filter_map(|r| r.ok()).collect())
|
||||
}
|
||||
|
||||
fn format_seconds_as_time(secs: i64) -> String {
|
||||
let h = secs / 3600;
|
||||
let m = (secs % 3600) / 60;
|
||||
|
||||
@@ -326,6 +326,17 @@ pub fn init_db(conn: &Connection) -> Result<(), rusqlite::Error> {
|
||||
[],
|
||||
)?;
|
||||
|
||||
conn.execute(
|
||||
"CREATE TABLE IF NOT EXISTS timesheet_rows (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
week_start TEXT NOT NULL,
|
||||
project_id INTEGER NOT NULL REFERENCES projects(id),
|
||||
task_id INTEGER REFERENCES tasks(id),
|
||||
sort_order INTEGER NOT NULL DEFAULT 0
|
||||
)",
|
||||
[],
|
||||
)?;
|
||||
|
||||
conn.execute(
|
||||
"CREATE TABLE IF NOT EXISTS settings (
|
||||
key TEXT PRIMARY KEY,
|
||||
|
||||
@@ -135,6 +135,9 @@ pub fn run() {
|
||||
commands::get_entry_templates,
|
||||
commands::create_entry_template,
|
||||
commands::delete_entry_template,
|
||||
commands::get_timesheet_rows,
|
||||
commands::save_timesheet_rows,
|
||||
commands::get_previous_week_structure,
|
||||
])
|
||||
.setup(|app| {
|
||||
#[cfg(desktop)]
|
||||
|
||||
Reference in New Issue
Block a user