style(src-tauri): cargo fmt
Pure mechanical rustfmt reformat (default config, no rustfmt.toml).
This commit is contained in:
+189
-50
@@ -482,7 +482,10 @@ pub(crate) fn seed_test_fixture(conn: &Connection) -> rusqlite::Result<()> {
|
||||
[],
|
||||
)?;
|
||||
let bank_id = conn.last_insert_rowid();
|
||||
conn.execute("UPDATE app_settings SET default_bank_id = ?1 WHERE id = 1", params![bank_id])?;
|
||||
conn.execute(
|
||||
"UPDATE app_settings SET default_bank_id = ?1 WHERE id = 1",
|
||||
params![bank_id],
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -542,8 +545,9 @@ pub fn relativize_asset_paths(conn: &Connection, data_dir: &Path) -> rusqlite::R
|
||||
}
|
||||
|
||||
let snapshots: Vec<(i64, String)> = {
|
||||
let mut stmt =
|
||||
tx.prepare("SELECT id, vendor_snapshot FROM invoices WHERE vendor_snapshot IS NOT NULL")?;
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT id, vendor_snapshot FROM invoices WHERE vendor_snapshot IS NOT NULL",
|
||||
)?;
|
||||
let rows = stmt.query_map([], |r| Ok((r.get(0)?, r.get(1)?)))?;
|
||||
rows.collect::<rusqlite::Result<_>>()?
|
||||
};
|
||||
@@ -574,7 +578,12 @@ pub fn relativize_asset_paths(conn: &Connection, data_dir: &Path) -> rusqlite::R
|
||||
|
||||
/// Format an invoice number from a series definition, e.g. "INV/2026-" + 1 -> "INV/2026-001".
|
||||
pub fn format_number(prefix: &str, padding: i64, number: i64) -> String {
|
||||
format!("{}{:0width$}", prefix, number, width = padding.max(1) as usize)
|
||||
format!(
|
||||
"{}{:0width$}",
|
||||
prefix,
|
||||
number,
|
||||
width = padding.max(1) as usize
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -682,7 +691,8 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
"#;
|
||||
|
||||
fn user_version(conn: &Connection) -> i64 {
|
||||
conn.pragma_query_value(None, "user_version", |r| r.get(0)).unwrap()
|
||||
conn.pragma_query_value(None, "user_version", |r| r.get(0))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn backups_in(dir: &Path) -> Vec<PathBuf> {
|
||||
@@ -724,7 +734,11 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
fn m4_adds_archive_and_export_dir_columns() {
|
||||
let conn = open_in_memory().unwrap();
|
||||
let dir: String = conn
|
||||
.query_row("SELECT last_export_dir FROM app_settings WHERE id = 1", [], |r| r.get(0))
|
||||
.query_row(
|
||||
"SELECT last_export_dir FROM app_settings WHERE id = 1",
|
||||
[],
|
||||
|r| r.get(0),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(dir, "");
|
||||
// The columns exist and are nullable on invoices (no rows needed to prove it).
|
||||
@@ -745,14 +759,26 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
fn render_prefs_column_defaults_to_empty_and_round_trips() {
|
||||
let conn = open_in_memory().unwrap();
|
||||
let initial: String = conn
|
||||
.query_row("SELECT render_prefs FROM app_settings WHERE id = 1", [], |r| r.get(0))
|
||||
.query_row(
|
||||
"SELECT render_prefs FROM app_settings WHERE id = 1",
|
||||
[],
|
||||
|r| r.get(0),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(initial, "");
|
||||
|
||||
let json = r#"{"version":1,"templateId":"classic","pageSize":"LETTER","margins":"narrow"}"#;
|
||||
conn.execute("UPDATE app_settings SET render_prefs = ?1 WHERE id = 1", [json]).unwrap();
|
||||
conn.execute(
|
||||
"UPDATE app_settings SET render_prefs = ?1 WHERE id = 1",
|
||||
[json],
|
||||
)
|
||||
.unwrap();
|
||||
let stored: String = conn
|
||||
.query_row("SELECT render_prefs FROM app_settings WHERE id = 1", [], |r| r.get(0))
|
||||
.query_row(
|
||||
"SELECT render_prefs FROM app_settings WHERE id = 1",
|
||||
[],
|
||||
|r| r.get(0),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(stored, json);
|
||||
}
|
||||
@@ -779,15 +805,21 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
.to_latest(&mut old)
|
||||
.unwrap();
|
||||
seed(&old).unwrap();
|
||||
old.execute("UPDATE app_settings SET logo_path = 'assets/logo-old.png'", []).unwrap();
|
||||
old.execute(
|
||||
"UPDATE app_settings SET logo_path = 'assets/logo-old.png'",
|
||||
[],
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(user_version(&old), 4);
|
||||
}
|
||||
let conn = open(&path, &dir.path().join("backups")).unwrap();
|
||||
assert_eq!(user_version(&conn), LATEST_VERSION);
|
||||
let (logo, meta): (String, String) = conn
|
||||
.query_row("SELECT logo_path, logo_meta FROM app_settings WHERE id = 1", [], |r| {
|
||||
Ok((r.get(0)?, r.get(1)?))
|
||||
})
|
||||
.query_row(
|
||||
"SELECT logo_path, logo_meta FROM app_settings WHERE id = 1",
|
||||
[],
|
||||
|r| Ok((r.get(0)?, r.get(1)?)),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!((logo.as_str(), meta.as_str()), ("assets/logo-old.png", ""));
|
||||
assert_eq!(backups_in(&dir.path().join("backups")).len(), 1);
|
||||
@@ -808,7 +840,11 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
)
|
||||
.unwrap();
|
||||
let (cat, terms): (String, Option<i64>) = conn
|
||||
.query_row("SELECT gst_category, payment_terms_days FROM clients", [], |r| Ok((r.get(0)?, r.get(1)?)))
|
||||
.query_row(
|
||||
"SELECT gst_category, payment_terms_days FROM clients",
|
||||
[],
|
||||
|r| Ok((r.get(0)?, r.get(1)?)),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!((cat.as_str(), terms), ("unregistered", None));
|
||||
// The category CHECK rejects unknown values.
|
||||
@@ -820,7 +856,14 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
#[test]
|
||||
fn m7_upgrade_from_v6_keeps_client_data_and_backfills_category() {
|
||||
let mut conn = Connection::open_in_memory().unwrap();
|
||||
let all = vec![M::up(SCHEMA), M::up(M2), M::up(M3), M::up(M4), M::up(M5), M::up(M6)];
|
||||
let all = vec![
|
||||
M::up(SCHEMA),
|
||||
M::up(M2),
|
||||
M::up(M3),
|
||||
M::up(M4),
|
||||
M::up(M5),
|
||||
M::up(M6),
|
||||
];
|
||||
Migrations::new(all).to_latest(&mut conn).unwrap();
|
||||
assert_eq!(user_version(&conn), 6);
|
||||
conn.execute(
|
||||
@@ -846,7 +889,10 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
.collect::<Result<_, _>>()
|
||||
.unwrap();
|
||||
assert_eq!(rows[0].1, "Line one\nLine two");
|
||||
assert_eq!((rows[0].2.as_str(), rows[0].3.as_str(), rows[0].4.as_str()), ("29ABCDE1234F1Z5", "29", "PO-1"));
|
||||
assert_eq!(
|
||||
(rows[0].2.as_str(), rows[0].3.as_str(), rows[0].4.as_str()),
|
||||
("29ABCDE1234F1Z5", "29", "PO-1")
|
||||
);
|
||||
assert_eq!(rows[0].5, "registered_regular");
|
||||
assert_eq!(rows[0].6, "");
|
||||
assert_eq!(rows[1].5, "unregistered");
|
||||
@@ -864,25 +910,43 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
|r| Ok((r.get(0)?, r.get(1)?, r.get(2)?, r.get(3)?, r.get(4)?, r.get(5)?, r.get(6)?)),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!((naming.as_str(), submit, attach, auto_push, create_customers), ("mirror", 0, 1, 0, 1));
|
||||
assert_eq!(
|
||||
(naming.as_str(), submit, attach, auto_push, create_customers),
|
||||
("mirror", 0, 1, 0, 1)
|
||||
);
|
||||
assert_eq!(secret, "");
|
||||
assert!(serde_json::from_str::<serde_json::Value>(&uom).is_ok());
|
||||
let rows: i64 = conn.query_row("SELECT COUNT(*) FROM erpnext_config", [], |r| r.get(0)).unwrap();
|
||||
let rows: i64 = conn
|
||||
.query_row("SELECT COUNT(*) FROM erpnext_config", [], |r| r.get(0))
|
||||
.unwrap();
|
||||
assert_eq!(rows, 1);
|
||||
// Single row only.
|
||||
assert!(conn.execute("INSERT INTO erpnext_config (id) VALUES (2)", []).is_err());
|
||||
assert!(conn
|
||||
.execute("INSERT INTO erpnext_config (id) VALUES (2)", [])
|
||||
.is_err());
|
||||
conn.prepare("SELECT invoice_id, remote_name, remote_docstatus, status, last_error, payload_hash, synced_at FROM erpnext_sync")
|
||||
.unwrap();
|
||||
conn.prepare("SELECT erpnext_customer, erpnext_address FROM clients").unwrap();
|
||||
conn.prepare("SELECT erpnext_payment_entry FROM payments").unwrap();
|
||||
conn.prepare("SELECT erpnext_item_code FROM item_presets").unwrap();
|
||||
conn.prepare("SELECT erpnext_customer, erpnext_address FROM clients")
|
||||
.unwrap();
|
||||
conn.prepare("SELECT erpnext_payment_entry FROM payments")
|
||||
.unwrap();
|
||||
conn.prepare("SELECT erpnext_item_code FROM item_presets")
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn m10_upgrade_from_v9_keeps_existing_data_and_new_columns_are_null() {
|
||||
let mut conn = Connection::open_in_memory().unwrap();
|
||||
let v9 = vec![
|
||||
M::up(SCHEMA), M::up(M2), M::up(M3), M::up(M4), M::up(M5), M::up(M6), M::up(M7), M::up(M8), M::up(M9),
|
||||
M::up(SCHEMA),
|
||||
M::up(M2),
|
||||
M::up(M3),
|
||||
M::up(M4),
|
||||
M::up(M5),
|
||||
M::up(M6),
|
||||
M::up(M7),
|
||||
M::up(M8),
|
||||
M::up(M9),
|
||||
];
|
||||
Migrations::new(v9).to_latest(&mut conn).unwrap();
|
||||
assert_eq!(user_version(&conn), 9);
|
||||
@@ -902,37 +966,70 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
migrations().to_latest(&mut conn).unwrap();
|
||||
assert_eq!(user_version(&conn), LATEST_VERSION);
|
||||
|
||||
let (name, gstin, customer, address): (String, String, Option<String>, Option<String>) = conn
|
||||
.query_row("SELECT name, gstin, erpnext_customer, erpnext_address FROM clients", [], |r| {
|
||||
Ok((r.get(0)?, r.get(1)?, r.get(2)?, r.get(3)?))
|
||||
})
|
||||
let (name, gstin, customer, address): (String, String, Option<String>, Option<String>) =
|
||||
conn.query_row(
|
||||
"SELECT name, gstin, erpnext_customer, erpnext_address FROM clients",
|
||||
[],
|
||||
|r| Ok((r.get(0)?, r.get(1)?, r.get(2)?, r.get(3)?)),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!((name.as_str(), gstin.as_str(), customer, address), ("Acme", "29ABCDE1234F1Z5", None, None));
|
||||
assert_eq!(
|
||||
(name.as_str(), gstin.as_str(), customer, address),
|
||||
("Acme", "29ABCDE1234F1Z5", None, None)
|
||||
);
|
||||
let (desc, rate, code): (String, i64, Option<String>) = conn
|
||||
.query_row("SELECT description, rate_paise, erpnext_item_code FROM item_presets", [], |r| {
|
||||
Ok((r.get(0)?, r.get(1)?, r.get(2)?))
|
||||
})
|
||||
.query_row(
|
||||
"SELECT description, rate_paise, erpnext_item_code FROM item_presets",
|
||||
[],
|
||||
|r| Ok((r.get(0)?, r.get(1)?, r.get(2)?)),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!((desc.as_str(), rate, code), ("Design", 500000, None));
|
||||
let (paid, entry): (i64, Option<String>) = conn
|
||||
.query_row("SELECT amount_paise, erpnext_payment_entry FROM payments", [], |r| Ok((r.get(0)?, r.get(1)?)))
|
||||
.query_row(
|
||||
"SELECT amount_paise, erpnext_payment_entry FROM payments",
|
||||
[],
|
||||
|r| Ok((r.get(0)?, r.get(1)?)),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!((paid, entry), (12345, None));
|
||||
let number: String = conn.query_row("SELECT number FROM invoices", [], |r| r.get(0)).unwrap();
|
||||
let number: String = conn
|
||||
.query_row("SELECT number FROM invoices", [], |r| r.get(0))
|
||||
.unwrap();
|
||||
assert_eq!(number, "INV/2026-001");
|
||||
|
||||
// The config row exists with defaults, and a sync row can reference the invoice.
|
||||
let enabled: i64 = conn.query_row("SELECT COUNT(*) FROM erpnext_config WHERE id = 1", [], |r| r.get(0)).unwrap();
|
||||
let enabled: i64 = conn
|
||||
.query_row(
|
||||
"SELECT COUNT(*) FROM erpnext_config WHERE id = 1",
|
||||
[],
|
||||
|r| r.get(0),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(enabled, 1);
|
||||
conn.execute("INSERT INTO erpnext_sync (invoice_id, remote_name, status) VALUES (1, 'INV/2026-001', 'synced')", []).unwrap();
|
||||
assert!(conn.execute("INSERT INTO erpnext_sync (invoice_id, status) VALUES (1, 'bogus')", []).is_err());
|
||||
assert!(conn
|
||||
.execute(
|
||||
"INSERT INTO erpnext_sync (invoice_id, status) VALUES (1, 'bogus')",
|
||||
[]
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn m11_rebuilds_the_sync_table_keeping_rows_and_allowing_conflict() {
|
||||
let mut conn = Connection::open_in_memory().unwrap();
|
||||
let v10 = vec![
|
||||
M::up(SCHEMA), M::up(M2), M::up(M3), M::up(M4), M::up(M5), M::up(M6), M::up(M7), M::up(M8), M::up(M9), M::up(M10),
|
||||
M::up(SCHEMA),
|
||||
M::up(M2),
|
||||
M::up(M3),
|
||||
M::up(M4),
|
||||
M::up(M5),
|
||||
M::up(M6),
|
||||
M::up(M7),
|
||||
M::up(M8),
|
||||
M::up(M9),
|
||||
M::up(M10),
|
||||
];
|
||||
Migrations::new(v10).to_latest(&mut conn).unwrap();
|
||||
assert_eq!(user_version(&conn), 10);
|
||||
@@ -947,7 +1044,9 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
[],
|
||||
)
|
||||
.unwrap();
|
||||
assert!(conn.execute("UPDATE erpnext_sync SET status = 'conflict'", []).is_err());
|
||||
assert!(conn
|
||||
.execute("UPDATE erpnext_sync SET status = 'conflict'", [])
|
||||
.is_err());
|
||||
|
||||
migrations().to_latest(&mut conn).unwrap();
|
||||
assert_eq!(user_version(&conn), 11);
|
||||
@@ -960,12 +1059,27 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
row,
|
||||
("INV/2026-001".into(), 1, "synced".into(), "abc".into(), String::new(), Some("2026-04-02T00:00:00Z".into()))
|
||||
(
|
||||
"INV/2026-001".into(),
|
||||
1,
|
||||
"synced".into(),
|
||||
"abc".into(),
|
||||
String::new(),
|
||||
Some("2026-04-02T00:00:00Z".into())
|
||||
)
|
||||
);
|
||||
conn.execute("UPDATE erpnext_sync SET status = 'conflict'", []).unwrap();
|
||||
assert!(conn.execute("UPDATE erpnext_sync SET status = 'bogus'", []).is_err());
|
||||
conn.execute("UPDATE erpnext_sync SET status = 'conflict'", [])
|
||||
.unwrap();
|
||||
assert!(conn
|
||||
.execute("UPDATE erpnext_sync SET status = 'bogus'", [])
|
||||
.is_err());
|
||||
// The unique key still guards one row per invoice.
|
||||
assert!(conn.execute("INSERT INTO erpnext_sync (invoice_id, status) VALUES (1, 'error')", []).is_err());
|
||||
assert!(conn
|
||||
.execute(
|
||||
"INSERT INTO erpnext_sync (invoice_id, status) VALUES (1, 'error')",
|
||||
[]
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
fn build_v1_database(path: &Path) {
|
||||
@@ -1018,7 +1132,10 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
let files = backups_in(&backups);
|
||||
assert_eq!(files.len(), 1);
|
||||
let name = files[0].file_name().unwrap().to_str().unwrap();
|
||||
assert!(name.starts_with("voiced-pre-v0-") && name.ends_with(".db"), "{name}");
|
||||
assert!(
|
||||
name.starts_with("voiced-pre-v0-") && name.ends_with(".db"),
|
||||
"{name}"
|
||||
);
|
||||
let backup = Connection::open(&files[0]).unwrap();
|
||||
assert_eq!(user_version(&backup), 0);
|
||||
let n: i64 = backup
|
||||
@@ -1039,7 +1156,13 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
assert_eq!(vendor, "Acme Studio");
|
||||
|
||||
// Invoice backfill.
|
||||
let (origin, snapshot, doc_type, number, total): (String, Option<String>, String, String, f64) = conn
|
||||
let (origin, snapshot, doc_type, number, total): (
|
||||
String,
|
||||
Option<String>,
|
||||
String,
|
||||
String,
|
||||
f64,
|
||||
) = conn
|
||||
.query_row(
|
||||
"SELECT snapshot_origin, vendor_snapshot, doc_type, number, total FROM invoices",
|
||||
[],
|
||||
@@ -1107,7 +1230,9 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
.collect();
|
||||
names.sort();
|
||||
assert_eq!(names.len(), MAX_BACKUPS);
|
||||
assert!(names.iter().all(|n| !n.contains("20260101") && !n.contains("20260104")));
|
||||
assert!(names
|
||||
.iter()
|
||||
.all(|n| !n.contains("20260101") && !n.contains("20260104")));
|
||||
assert!(dir.path().join("unrelated.db").exists());
|
||||
}
|
||||
|
||||
@@ -1116,8 +1241,16 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
let dir = tempdir().unwrap();
|
||||
let data = dir.path();
|
||||
let conn = open(&data.join("voiced.db"), &data.join("backups")).unwrap();
|
||||
let abs_logo = data.join("assets").join("logo-1.png").to_string_lossy().into_owned();
|
||||
let abs_sig = data.join("assets").join("signature-2.jpg").to_string_lossy().into_owned();
|
||||
let abs_logo = data
|
||||
.join("assets")
|
||||
.join("logo-1.png")
|
||||
.to_string_lossy()
|
||||
.into_owned();
|
||||
let abs_sig = data
|
||||
.join("assets")
|
||||
.join("signature-2.jpg")
|
||||
.to_string_lossy()
|
||||
.into_owned();
|
||||
let foreign = "/somewhere/else/logo.png";
|
||||
conn.execute(
|
||||
"UPDATE app_settings SET logo_path = ?1, signature_path = ?2",
|
||||
@@ -1146,9 +1279,11 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
for _ in 0..2 {
|
||||
relativize_asset_paths(&conn, data).unwrap();
|
||||
let (logo, sig): (String, String) = conn
|
||||
.query_row("SELECT logo_path, signature_path FROM app_settings", [], |r| {
|
||||
Ok((r.get(0)?, r.get(1)?))
|
||||
})
|
||||
.query_row(
|
||||
"SELECT logo_path, signature_path FROM app_settings",
|
||||
[],
|
||||
|r| Ok((r.get(0)?, r.get(1)?)),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(logo, "assets/logo-1.png");
|
||||
assert_eq!(sig, foreign);
|
||||
@@ -1165,7 +1300,11 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
|
||||
assert_eq!(json["signaturePath"], "assets/signature-2.jpg");
|
||||
assert_eq!(json["vendorName"], "Acme");
|
||||
let bad: String = conn
|
||||
.query_row("SELECT vendor_snapshot FROM invoices WHERE number = 'A-2'", [], |r| r.get(0))
|
||||
.query_row(
|
||||
"SELECT vendor_snapshot FROM invoices WHERE number = 'A-2'",
|
||||
[],
|
||||
|r| r.get(0),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(bad, "not json");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user