feat: client cascade delete with dependency counts
This commit is contained in:
@@ -110,11 +110,66 @@ pub fn update_client(state: State<AppState>, client: Client) -> Result<(), Strin
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_client_dependents(state: State<AppState>, client_id: i64) -> Result<serde_json::Value, String> {
|
||||
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||
let project_count: i64 = conn.query_row(
|
||||
"SELECT COUNT(*) FROM projects WHERE client_id = ?1", params![client_id], |row| row.get(0)
|
||||
).map_err(|e| e.to_string())?;
|
||||
let invoice_count: i64 = conn.query_row(
|
||||
"SELECT COUNT(*) FROM invoices WHERE client_id = ?1", params![client_id], |row| row.get(0)
|
||||
).map_err(|e| e.to_string())?;
|
||||
let expense_count: i64 = conn.query_row(
|
||||
"SELECT COUNT(*) FROM expenses WHERE client_id = ?1", params![client_id], |row| row.get(0)
|
||||
).map_err(|e| e.to_string())?;
|
||||
Ok(serde_json::json!({
|
||||
"projects": project_count,
|
||||
"invoices": invoice_count,
|
||||
"expenses": expense_count
|
||||
}))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn delete_client(state: State<AppState>, id: i64) -> Result<(), String> {
|
||||
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||
conn.execute("DELETE FROM clients WHERE id = ?1", params![id]).map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
|
||||
conn.execute_batch("BEGIN TRANSACTION").map_err(|e| e.to_string())?;
|
||||
|
||||
let result = (|| -> Result<(), rusqlite::Error> {
|
||||
let project_ids: Vec<i64> = {
|
||||
let mut stmt = conn.prepare("SELECT id FROM projects WHERE client_id = ?1")?;
|
||||
let rows = stmt.query_map(params![id], |row| row.get(0))?;
|
||||
rows.filter_map(|r| r.ok()).collect()
|
||||
};
|
||||
|
||||
for pid in &project_ids {
|
||||
conn.execute("DELETE FROM entry_tags WHERE entry_id IN (SELECT id FROM time_entries WHERE project_id = ?1)", params![pid])?;
|
||||
conn.execute("DELETE FROM time_entries WHERE project_id = ?1", params![pid])?;
|
||||
conn.execute("DELETE FROM tasks WHERE project_id = ?1", params![pid])?;
|
||||
conn.execute("DELETE FROM tracked_apps WHERE project_id = ?1", params![pid])?;
|
||||
conn.execute("DELETE FROM favorites WHERE project_id = ?1", params![pid])?;
|
||||
conn.execute("DELETE FROM recurring_entries WHERE project_id = ?1", params![pid])?;
|
||||
conn.execute("DELETE FROM timeline_events WHERE project_id = ?1", params![pid])?;
|
||||
}
|
||||
|
||||
conn.execute("DELETE FROM expenses WHERE client_id = ?1", params![id])?;
|
||||
conn.execute("DELETE FROM invoice_items WHERE invoice_id IN (SELECT id FROM invoices WHERE client_id = ?1)", params![id])?;
|
||||
conn.execute("DELETE FROM invoices WHERE client_id = ?1", params![id])?;
|
||||
conn.execute("DELETE FROM projects WHERE client_id = ?1", params![id])?;
|
||||
conn.execute("DELETE FROM clients WHERE id = ?1", params![id])?;
|
||||
Ok(())
|
||||
})();
|
||||
|
||||
match result {
|
||||
Ok(()) => {
|
||||
conn.execute_batch("COMMIT").map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
conn.execute_batch("ROLLBACK").ok();
|
||||
Err(e.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Project commands
|
||||
|
||||
@@ -45,6 +45,7 @@ pub fn run() {
|
||||
commands::create_client,
|
||||
commands::update_client,
|
||||
commands::delete_client,
|
||||
commands::get_client_dependents,
|
||||
commands::get_projects,
|
||||
commands::create_project,
|
||||
commands::update_project,
|
||||
|
||||
Reference in New Issue
Block a user