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(())
|
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 {
|
fn format_seconds_as_time(secs: i64) -> String {
|
||||||
let h = secs / 3600;
|
let h = secs / 3600;
|
||||||
let m = (secs % 3600) / 60;
|
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(
|
conn.execute(
|
||||||
"CREATE TABLE IF NOT EXISTS settings (
|
"CREATE TABLE IF NOT EXISTS settings (
|
||||||
key TEXT PRIMARY KEY,
|
key TEXT PRIMARY KEY,
|
||||||
|
|||||||
@@ -135,6 +135,9 @@ pub fn run() {
|
|||||||
commands::get_entry_templates,
|
commands::get_entry_templates,
|
||||||
commands::create_entry_template,
|
commands::create_entry_template,
|
||||||
commands::delete_entry_template,
|
commands::delete_entry_template,
|
||||||
|
commands::get_timesheet_rows,
|
||||||
|
commands::save_timesheet_rows,
|
||||||
|
commands::get_previous_week_structure,
|
||||||
])
|
])
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
#[cfg(desktop)]
|
#[cfg(desktop)]
|
||||||
|
|||||||
Reference in New Issue
Block a user