use crate::db::format_number; use crate::models::InvoiceSeries; use crate::AppState; use rusqlite::{params, Row}; use tauri::State; fn map_series(row: &Row) -> rusqlite::Result { let prefix: String = row.get(1)?; let padding: i64 = row.get(2)?; let next_number: i64 = row.get(3)?; Ok(InvoiceSeries { id: row.get(0)?, next_invoice_number: format_number(&prefix, padding, next_number), prefix, padding, next_number, is_active: row.get::<_, i64>(4)? != 0, created_at: row.get(5)?, }) } const SERIES_SELECT: &str = "SELECT id, prefix, padding, next_number, is_active, created_at FROM invoice_series"; #[tauri::command] pub fn get_active_series(state: State) -> Result, String> { let conn = state.db.lock().map_err(|e| e.to_string())?; let mut stmt = conn .prepare(&format!( "{} WHERE is_active = 1 ORDER BY id DESC LIMIT 1", SERIES_SELECT )) .map_err(|e| e.to_string())?; let mut rows = stmt.query_map([], map_series).map_err(|e| e.to_string())?; match rows.next() { Some(r) => Ok(Some(r.map_err(|e| e.to_string())?)), None => Ok(None), } } #[tauri::command] pub fn list_series(state: State) -> Result, String> { let conn = state.db.lock().map_err(|e| e.to_string())?; let mut stmt = conn .prepare(&format!("{} ORDER BY id DESC", SERIES_SELECT)) .map_err(|e| e.to_string())?; let rows = stmt .query_map([], map_series) .map_err(|e| e.to_string())? .collect::>>() .map_err(|e| e.to_string())?; Ok(rows) } /// Deactivates the current series and starts a fresh one, resetting the counter to 1. #[tauri::command] pub fn start_new_series( state: State, prefix: String, padding: i64, ) -> Result { let prefix = prefix.trim().to_string(); if prefix.is_empty() { return Err("Series prefix cannot be empty".into()); } let padding = padding.clamp(1, 8); let conn = state.db.lock().map_err(|e| e.to_string())?; conn.execute("UPDATE invoice_series SET is_active = 0", []) .map_err(|e| e.to_string())?; conn.execute( "INSERT INTO invoice_series (prefix, padding, next_number, is_active, created_at) VALUES (?1, ?2, 1, 1, ?3)", params![prefix, padding, chrono::Utc::now().to_rfc3339()], ) .map_err(|e| e.to_string())?; let id = conn.last_insert_rowid(); conn.query_row( &format!("{} WHERE id = ?1", SERIES_SELECT), params![id], map_series, ) .map_err(|e| e.to_string()) }