feat: add template_id column to invoices table and update_invoice_template command
This commit is contained in:
@@ -62,6 +62,7 @@ pub struct Invoice {
|
||||
pub total: f64,
|
||||
pub notes: Option<String>,
|
||||
pub status: String,
|
||||
pub template_id: Option<String>,
|
||||
}
|
||||
|
||||
// Client commands
|
||||
@@ -317,11 +318,11 @@ pub fn get_reports(state: State<AppState>, start_date: String, end_date: String)
|
||||
pub fn create_invoice(state: State<AppState>, invoice: Invoice) -> Result<i64, String> {
|
||||
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||
conn.execute(
|
||||
"INSERT INTO invoices (client_id, invoice_number, date, due_date, subtotal, tax_rate, tax_amount, discount, total, notes, status)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)",
|
||||
"INSERT INTO invoices (client_id, invoice_number, date, due_date, subtotal, tax_rate, tax_amount, discount, total, notes, status, template_id)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)",
|
||||
params![invoice.client_id, invoice.invoice_number, invoice.date, invoice.due_date,
|
||||
invoice.subtotal, invoice.tax_rate, invoice.tax_amount, invoice.discount,
|
||||
invoice.total, invoice.notes, invoice.status],
|
||||
invoice.total, invoice.notes, invoice.status, invoice.template_id],
|
||||
).map_err(|e| e.to_string())?;
|
||||
Ok(conn.last_insert_rowid())
|
||||
}
|
||||
@@ -330,7 +331,7 @@ pub fn create_invoice(state: State<AppState>, invoice: Invoice) -> Result<i64, S
|
||||
pub fn get_invoices(state: State<AppState>) -> Result<Vec<Invoice>, String> {
|
||||
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT id, client_id, invoice_number, date, due_date, subtotal, tax_rate, tax_amount, discount, total, notes, status
|
||||
"SELECT id, client_id, invoice_number, date, due_date, subtotal, tax_rate, tax_amount, discount, total, notes, status, template_id
|
||||
FROM invoices ORDER BY date DESC"
|
||||
).map_err(|e| e.to_string())?;
|
||||
let invoices = stmt.query_map([], |row| {
|
||||
@@ -347,6 +348,7 @@ pub fn get_invoices(state: State<AppState>) -> Result<Vec<Invoice>, String> {
|
||||
total: row.get(9)?,
|
||||
notes: row.get(10)?,
|
||||
status: row.get(11)?,
|
||||
template_id: row.get(12)?,
|
||||
})
|
||||
}).map_err(|e| e.to_string())?;
|
||||
invoices.collect::<Result<Vec<_>, _>>().map_err(|e| e.to_string())
|
||||
@@ -357,11 +359,11 @@ pub fn update_invoice(state: State<AppState>, invoice: Invoice) -> Result<(), St
|
||||
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||
conn.execute(
|
||||
"UPDATE invoices SET client_id = ?1, invoice_number = ?2, date = ?3, due_date = ?4,
|
||||
subtotal = ?5, tax_rate = ?6, tax_amount = ?7, discount = ?8, total = ?9, notes = ?10, status = ?11
|
||||
WHERE id = ?12",
|
||||
subtotal = ?5, tax_rate = ?6, tax_amount = ?7, discount = ?8, total = ?9, notes = ?10, status = ?11, template_id = ?12
|
||||
WHERE id = ?13",
|
||||
params![invoice.client_id, invoice.invoice_number, invoice.date, invoice.due_date,
|
||||
invoice.subtotal, invoice.tax_rate, invoice.tax_amount, invoice.discount,
|
||||
invoice.total, invoice.notes, invoice.status, invoice.id],
|
||||
invoice.total, invoice.notes, invoice.status, invoice.template_id, invoice.id],
|
||||
).map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -373,6 +375,67 @@ pub fn delete_invoice(state: State<AppState>, id: i64) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn update_invoice_template(state: State<AppState>, id: i64, template_id: String) -> Result<(), String> {
|
||||
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||
conn.execute(
|
||||
"UPDATE invoices SET template_id = ?1 WHERE id = ?2",
|
||||
params![template_id, id],
|
||||
).map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Invoice items
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct InvoiceItem {
|
||||
pub id: Option<i64>,
|
||||
pub invoice_id: i64,
|
||||
pub description: String,
|
||||
pub quantity: f64,
|
||||
pub rate: f64,
|
||||
pub amount: f64,
|
||||
pub time_entry_id: Option<i64>,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_invoice_items(state: State<AppState>, invoice_id: i64) -> Result<Vec<InvoiceItem>, String> {
|
||||
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT id, invoice_id, description, quantity, rate, amount, time_entry_id
|
||||
FROM invoice_items WHERE invoice_id = ?1 ORDER BY id"
|
||||
).map_err(|e| e.to_string())?;
|
||||
let items = stmt.query_map(params![invoice_id], |row| {
|
||||
Ok(InvoiceItem {
|
||||
id: Some(row.get(0)?),
|
||||
invoice_id: row.get(1)?,
|
||||
description: row.get(2)?,
|
||||
quantity: row.get(3)?,
|
||||
rate: row.get(4)?,
|
||||
amount: row.get(5)?,
|
||||
time_entry_id: row.get(6)?,
|
||||
})
|
||||
}).map_err(|e| e.to_string())?;
|
||||
items.collect::<Result<Vec<_>, _>>().map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn create_invoice_item(state: State<AppState>, item: InvoiceItem) -> Result<i64, String> {
|
||||
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||
conn.execute(
|
||||
"INSERT INTO invoice_items (invoice_id, description, quantity, rate, amount, time_entry_id)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6)",
|
||||
params![item.invoice_id, item.description, item.quantity, item.rate, item.amount, item.time_entry_id],
|
||||
).map_err(|e| e.to_string())?;
|
||||
Ok(conn.last_insert_rowid())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn delete_invoice_items(state: State<AppState>, invoice_id: i64) -> Result<(), String> {
|
||||
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||
conn.execute("DELETE FROM invoice_items WHERE invoice_id = ?1", params![invoice_id]).map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Settings commands
|
||||
#[tauri::command]
|
||||
pub fn get_settings(state: State<AppState>) -> Result<std::collections::HashMap<String, String>, String> {
|
||||
@@ -1053,6 +1116,12 @@ pub fn import_json_data(state: State<AppState>, data: serde_json::Value) -> Resu
|
||||
Ok(counts)
|
||||
}
|
||||
|
||||
// File save command (bypasses fs plugin scope for user-selected paths)
|
||||
#[tauri::command]
|
||||
pub fn save_binary_file(path: String, data: Vec<u8>) -> Result<(), String> {
|
||||
std::fs::write(&path, &data).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
// Mini timer window commands
|
||||
#[tauri::command]
|
||||
pub fn open_mini_timer(app: tauri::AppHandle) -> Result<(), String> {
|
||||
|
||||
Reference in New Issue
Block a user