Fix product save: add name_lower, product-only micro fields, strawberry
Root cause: addProduct INSERT didn't include name_lower column. Search uses WHERE name_lower LIKE — products with NULL name_lower never found. User entered 20 min of strawberry data for nothing. Fixes: - addProduct: includes name_lower = name.toLowerCase() - Added phosphorus_mg and carotene_mcg to addProduct INSERT - PRODUCT_MICRO_FIELDS: subset of MICRO_FIELDS for product forms (excludes supplement-only fields: omega, EPA/DHA, fish oil etc.) - showAddProductModal and showEditProductModal use PRODUCT_MICRO_FIELDS - Rust: removed stale inserted+=1 line - Seed DB v8: added "Клубника свежая" (alias for "Земляника садовая")
This commit is contained in:
parent
f20d45aa18
commit
2df5908fca
4 changed files with 50 additions and 50 deletions
Binary file not shown.
|
|
@ -133,17 +133,18 @@ async function getProduct(id) {
|
|||
}
|
||||
|
||||
async function addProduct(p) {
|
||||
const r = await execute(
|
||||
await execute(
|
||||
`INSERT INTO products
|
||||
(name, brand, category, weight_g, kcal_per_100g, protein_per_100g,
|
||||
(name, name_lower, brand, category, weight_g, kcal_per_100g, protein_per_100g,
|
||||
fat_per_100g, carbs_per_100g, fiber_per_100g,
|
||||
vit_a_mcg, vit_c_mg, vit_d_mcg, vit_e_mg, vit_k_mcg,
|
||||
vit_b1_mg, vit_b2_mg, vit_b3_mg, vit_b6_mg, vit_b12_mcg, folate_mcg,
|
||||
calcium_mg, iron_mg, magnesium_mg, zinc_mg, copper_mg,
|
||||
selenium_mcg, potassium_mg, sodium_mg, source)
|
||||
VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12,?13,?14,?15,?16,?17,?18,?19,?20,?21,?22,?23,?24,?25,?26,?27,?28,?29)`,
|
||||
selenium_mcg, potassium_mg, sodium_mg, phosphorus_mg, carotene_mcg, source)
|
||||
VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12,?13,?14,?15,?16,?17,?18,?19,?20,?21,?22,?23,?24,?25,?26,?27,?28,?29,?30,?31,?32)`,
|
||||
[
|
||||
p.name, p.brand ?? null, p.category ?? null, p.weight_g ?? null,
|
||||
p.name, p.name?.toLowerCase() ?? null,
|
||||
p.brand ?? null, p.category ?? null, p.weight_g ?? null,
|
||||
p.kcal_per_100g ?? null, p.protein_per_100g ?? null,
|
||||
p.fat_per_100g ?? null, p.carbs_per_100g ?? null, p.fiber_per_100g ?? null,
|
||||
p.vit_a_mcg ?? null, p.vit_c_mg ?? null, p.vit_d_mcg ?? null,
|
||||
|
|
@ -153,6 +154,7 @@ async function addProduct(p) {
|
|||
p.calcium_mg ?? null, p.iron_mg ?? null, p.magnesium_mg ?? null,
|
||||
p.zinc_mg ?? null, p.copper_mg ?? null,
|
||||
p.selenium_mcg ?? null, p.potassium_mg ?? null, p.sodium_mg ?? null,
|
||||
p.phosphorus_mg ?? null, p.carotene_mcg ?? null,
|
||||
p.source ?? "manual",
|
||||
]
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1359,7 +1359,7 @@ async function renderProducts(container) {
|
|||
}
|
||||
|
||||
function showAddProductModal(onSaved) {
|
||||
const microHtml = MICRO_FIELDS.map(f => {
|
||||
const microHtml = PRODUCT_MICRO_FIELDS.map(f => {
|
||||
return `<div class="form-group micro-field">
|
||||
<label>${f.label}</label>
|
||||
<input id="np-${f.key}" type="number" inputmode="decimal" step="any" placeholder="—" />
|
||||
|
|
@ -1403,7 +1403,7 @@ function showAddProductModal(onSaved) {
|
|||
carbs_per_100g: parseFloat(overlay.querySelector("#np-carbs").value) || null,
|
||||
source: "manual",
|
||||
};
|
||||
for (const f of MICRO_FIELDS) {
|
||||
for (const f of PRODUCT_MICRO_FIELDS) {
|
||||
let val = parseFloat(overlay.querySelector(`#np-${f.key}`).value) || null;
|
||||
if (val && f.mult) val *= f.mult;
|
||||
data[f.key] = val;
|
||||
|
|
@ -1414,7 +1414,7 @@ function showAddProductModal(onSaved) {
|
|||
}
|
||||
|
||||
function showEditProductModal(p, onSaved) {
|
||||
const microHtml = MICRO_FIELDS.map(f => {
|
||||
const microHtml = PRODUCT_MICRO_FIELDS.map(f => {
|
||||
let val = p[f.key] ?? "";
|
||||
if (val && f.mult) val = Math.round(val / f.mult * 1000) / 1000;
|
||||
return `<div class="form-group micro-field">
|
||||
|
|
@ -1461,7 +1461,7 @@ function showEditProductModal(p, onSaved) {
|
|||
parseFloat(overlay.querySelector("#ep-carbs").value) || null,
|
||||
];
|
||||
let idx = 6;
|
||||
for (const f of MICRO_FIELDS) {
|
||||
for (const f of PRODUCT_MICRO_FIELDS) {
|
||||
let val = parseFloat(overlay.querySelector(`#ep-${f.key}`).value) || null;
|
||||
if (val && f.mult) val *= f.mult;
|
||||
sets.push(`${f.key}=?${idx}`);
|
||||
|
|
@ -3492,6 +3492,14 @@ const MICRO_FIELDS = [
|
|||
{ key: "lycopene_mg", label: "Ликопин (мг)" },
|
||||
];
|
||||
|
||||
// Subset of MICRO_FIELDS that exist as columns in the products table
|
||||
const PRODUCT_MICRO_FIELDS = MICRO_FIELDS.filter(f => [
|
||||
"vit_a_mcg", "vit_c_mg", "vit_d_mcg", "vit_e_mg", "vit_k_mcg",
|
||||
"vit_b1_mg", "vit_b2_mg", "vit_b3_mg", "vit_b6_mg", "vit_b12_mcg", "folate_mcg",
|
||||
"calcium_mg", "iron_mg", "magnesium_mg", "zinc_mg", "copper_mg",
|
||||
"selenium_mcg", "potassium_mg", "sodium_mg", "phosphorus_mg", "carotene_mcg",
|
||||
].includes(f.key));
|
||||
|
||||
async function renderSupplements(container) {
|
||||
const supps = await DB.getSupplements();
|
||||
|
||||
|
|
|
|||
|
|
@ -105,9 +105,7 @@ fn import_seed_products(app: tauri::AppHandle) -> Result<String, String> {
|
|||
|
||||
let seed_db = rusqlite::Connection::open(&seed_path).map_err(|e| e.to_string())?;
|
||||
|
||||
let seed_version: i64 = seed_db.query_row(
|
||||
"SELECT version FROM seed_meta LIMIT 1", [], |r| r.get(0)
|
||||
).map_err(|e| e.to_string())?;
|
||||
let seed_version: i64 = seed_db.query_row("SELECT version FROM seed_meta LIMIT 1", [], |r| r.get(0)).map_err(|e| e.to_string())?;
|
||||
|
||||
// tauri-plugin-sql may store DB in app_config_dir (desktop: ~/.config/...)
|
||||
// or app_data_dir (desktop: ~/.local/share/...). Check both.
|
||||
|
|
@ -123,17 +121,13 @@ fn import_seed_products(app: tauri::AppHandle) -> Result<String, String> {
|
|||
};
|
||||
let main_db = rusqlite::Connection::open(&main_path).map_err(|e| e.to_string())?;
|
||||
|
||||
let current_version: i64 = main_db.query_row(
|
||||
"SELECT COALESCE((SELECT value FROM profile WHERE key='seed_version'), '0')",
|
||||
[], |r| {
|
||||
let current_version: i64 = main_db.query_row("SELECT COALESCE((SELECT value FROM profile WHERE key='seed_version'), '0')", [], |r| {
|
||||
let s: String = r.get(0)?;
|
||||
Ok(s.parse::<i64>().unwrap_or(0))
|
||||
}
|
||||
).unwrap_or(0);
|
||||
|
||||
if current_version >= seed_version {
|
||||
return Ok(format!("up-to-date:v{}", current_version));
|
||||
}
|
||||
if current_version >= seed_version {return Ok(format!("up-to-date:v{}", current_version));}
|
||||
|
||||
let total: usize = seed_db.query_row("SELECT COUNT(*) FROM products", [], |r| r.get(0))
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
|
@ -157,8 +151,7 @@ fn import_seed_products(app: tauri::AppHandle) -> Result<String, String> {
|
|||
|
||||
// ATTACH seed DB to main DB and do bulk INSERT + UPDATE in SQL (no per-row loop)
|
||||
let seed_str = seed_path.to_str().unwrap_or_default().to_string();
|
||||
main_db.execute("ATTACH DATABASE ?1 AS seed", rusqlite::params![seed_str])
|
||||
.map_err(|e| e.to_string())?;
|
||||
main_db.execute("ATTACH DATABASE ?1 AS seed", rusqlite::params![seed_str]).map_err(|e| e.to_string())?;
|
||||
|
||||
let mut inserted = 0usize;
|
||||
|
||||
|
|
@ -180,11 +173,8 @@ fn import_seed_products(app: tauri::AppHandle) -> Result<String, String> {
|
|||
iron_mg, vit_a_mcg, vit_b1_mg, vit_b2_mg, vit_b3_mg, vit_c_mg,
|
||||
vit_e_mg, carotene_mcg, COALESCE(nutrients_guessed, 0)
|
||||
FROM seed.products",
|
||||
[],
|
||||
).map_err(|e| e.to_string())?;
|
||||
[]
|
||||
).map_err(|e| e.to_string())?;
|
||||
inserted += 1;
|
||||
processed += 1;
|
||||
|
||||
// Update KBJU + micronutrients for existing store products (seed already attached above)
|
||||
// Sync nutrients_guessed flag
|
||||
|
|
@ -193,32 +183,32 @@ fn import_seed_products(app: tauri::AppHandle) -> Result<String, String> {
|
|||
WHERE (nutrients_guessed IS NULL OR nutrients_guessed = 0)
|
||||
AND name_lower IN (SELECT s.name_lower FROM seed.products s WHERE s.nutrients_guessed = 1)"
|
||||
);
|
||||
// Update KBJU + micronutrients for store products that user hasn't manually edited.
|
||||
// This ensures seed corrections (e.g. bread 268→243) flow through to app DB.
|
||||
let _ = main_db.execute_batch(
|
||||
"UPDATE main.products SET
|
||||
kcal_per_100g = (SELECT s.kcal_per_100g FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1),
|
||||
protein_per_100g = (SELECT s.protein_per_100g FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1),
|
||||
fat_per_100g = (SELECT s.fat_per_100g FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1),
|
||||
carbs_per_100g = (SELECT s.carbs_per_100g FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1),
|
||||
fiber_per_100g = (SELECT s.fiber_per_100g FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1),
|
||||
nutrients_guessed= COALESCE((SELECT s.nutrients_guessed FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), nutrients_guessed),
|
||||
sodium_mg = COALESCE((SELECT s.sodium_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), sodium_mg),
|
||||
potassium_mg = COALESCE((SELECT s.potassium_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), potassium_mg),
|
||||
calcium_mg = COALESCE((SELECT s.calcium_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), calcium_mg),
|
||||
magnesium_mg = COALESCE((SELECT s.magnesium_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), magnesium_mg),
|
||||
phosphorus_mg = COALESCE((SELECT s.phosphorus_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), phosphorus_mg),
|
||||
iron_mg = COALESCE((SELECT s.iron_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), iron_mg),
|
||||
vit_a_mcg = COALESCE((SELECT s.vit_a_mcg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), vit_a_mcg),
|
||||
vit_b1_mg = COALESCE((SELECT s.vit_b1_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), vit_b1_mg),
|
||||
vit_b2_mg = COALESCE((SELECT s.vit_b2_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), vit_b2_mg),
|
||||
vit_b3_mg = COALESCE((SELECT s.vit_b3_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), vit_b3_mg),
|
||||
vit_c_mg = COALESCE((SELECT s.vit_c_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), vit_c_mg),
|
||||
vit_e_mg = COALESCE((SELECT s.vit_e_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), vit_e_mg),
|
||||
carotene_mcg = COALESCE((SELECT s.carotene_mcg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), carotene_mcg)
|
||||
WHERE (main.products.user_edited IS NULL OR main.products.user_edited = 0)
|
||||
AND main.products.source IN ('magnit', '5ka', 'kdv', 'ion')
|
||||
AND main.products.name_lower IN (SELECT s2.name_lower FROM seed.products s2)"
|
||||
// Update KBJU + micronutrients for store products that user hasn't manually edited.
|
||||
// This ensures seed corrections (e.g. bread 268→243) flow through to app DB.
|
||||
let _ = main_db.execute_batch(
|
||||
"UPDATE main.products SET
|
||||
kcal_per_100g = (SELECT s.kcal_per_100g FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1),
|
||||
protein_per_100g = (SELECT s.protein_per_100g FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1),
|
||||
fat_per_100g = (SELECT s.fat_per_100g FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1),
|
||||
carbs_per_100g = (SELECT s.carbs_per_100g FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1),
|
||||
fiber_per_100g = (SELECT s.fiber_per_100g FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1),
|
||||
nutrients_guessed= COALESCE((SELECT s.nutrients_guessed FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), nutrients_guessed),
|
||||
sodium_mg = COALESCE((SELECT s.sodium_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), sodium_mg),
|
||||
potassium_mg = COALESCE((SELECT s.potassium_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), potassium_mg),
|
||||
calcium_mg = COALESCE((SELECT s.calcium_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), calcium_mg),
|
||||
magnesium_mg = COALESCE((SELECT s.magnesium_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), magnesium_mg),
|
||||
phosphorus_mg = COALESCE((SELECT s.phosphorus_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), phosphorus_mg),
|
||||
iron_mg = COALESCE((SELECT s.iron_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), iron_mg),
|
||||
vit_a_mcg = COALESCE((SELECT s.vit_a_mcg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), vit_a_mcg),
|
||||
vit_b1_mg = COALESCE((SELECT s.vit_b1_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), vit_b1_mg),
|
||||
vit_b2_mg = COALESCE((SELECT s.vit_b2_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), vit_b2_mg),
|
||||
vit_b3_mg = COALESCE((SELECT s.vit_b3_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), vit_b3_mg),
|
||||
vit_c_mg = COALESCE((SELECT s.vit_c_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), vit_c_mg),
|
||||
vit_e_mg = COALESCE((SELECT s.vit_e_mg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), vit_e_mg),
|
||||
carotene_mcg = COALESCE((SELECT s.carotene_mcg FROM seed.products s WHERE s.name_lower = main.products.name_lower LIMIT 1), carotene_mcg)
|
||||
WHERE (main.products.user_edited IS NULL OR main.products.user_edited = 0)
|
||||
AND main.products.source IN ('magnit', '5ka', 'kdv', 'ion')
|
||||
AND main.products.name_lower IN (SELECT s2.name_lower FROM seed.products s2)"
|
||||
);
|
||||
|
||||
// Update seed version AFTER all inserts+updates succeed
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue