Wed, 15 Jun 2022 10:54:04 +0200
Version 0.2.10 with updated translations and menu's.
/** * db_recipe.cpp is part of bmsapp. * * bmsapp is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * bmsapp is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "global.h" #include "db_recipe.h" bool DB_recipe::load(Recipe *reci, QDialog *dialog, int recno) { QSqlQuery query, yquery; query.prepare("SELECT * FROM recipes WHERE record = :recno"); query.bindValue(":recno", recno); query.exec(); if (! query.first()) { qWarning() << "loadRecipe seek error record" << recno; QMessageBox::warning(dialog, QObject::tr("Database error"), QObject::tr("MySQL error: record %1 not found").arg(recno)); dialog->done(QDialog::Rejected); // At this stage, this doesn't work because the dialog is not yet visible. return false; } // QSqlRecord rec = query.record(); // for (int i = 0; i < rec.count(); i++) // qDebug() << i << rec.fieldName(i) << query.value(i); reci->record = query.value("record").toInt(); reci->uuid = query.value("uuid").toString(); reci->locked = query.value("locked").toInt() ? true:false; reci->st_name = query.value("st_name").toString(); reci->st_letter = query.value("st_letter").toString(); reci->st_guide = query.value("st_guide").toString(); reci->st_category = query.value("st_category").toString(); reci->st_category_number = query.value("st_category_number").toInt(); reci->st_type = query.value("st_type").toInt(); reci->st_og_min = query.value("st_og_min").toDouble(); reci->st_og_max = query.value("st_og_max").toDouble(); reci->st_fg_min = query.value("st_fg_min").toDouble(); reci->st_fg_max = query.value("st_fg_max").toDouble(); reci->st_ibu_min = query.value("st_ibu_min").toDouble(); reci->st_ibu_max = query.value("st_ibu_max").toDouble(); reci->st_color_min = query.value("st_color_min").toDouble(); reci->st_color_max = query.value("st_color_max").toDouble(); reci->st_carb_min = query.value("st_carb_min").toDouble(); reci->st_carb_max = query.value("st_carb_max").toDouble(); reci->st_abv_min = query.value("st_abv_min").toDouble(); reci->st_abv_max = query.value("st_abv_max").toDouble(); reci->name = query.value("name").toString(); reci->notes = query.value("notes").toString(); reci->type = query.value("type").toInt(); reci->batch_size = query.value("batch_size").toDouble(); reci->boil_size = query.value("boil_size").toDouble(); reci->boil_time = query.value("boil_time").toDouble(); reci->efficiency = query.value("efficiency").toDouble(); reci->est_og = query.value("est_og").toDouble(); reci->est_fg = query.value("est_fg").toDouble(); reci->est_abv = query.value("est_abv").toDouble(); reci->est_color = query.value("est_color").toDouble(); reci->color_method = query.value("color_method").toInt(); reci->est_ibu = query.value("est_ibu").toDouble(); reci->ibu_method = query.value("ibu_method").toInt(); reci->est_carb = query.value("est_carb").toDouble(); reci->sparge_temp = query.value("sparge_temp").toDouble(); reci->sparge_ph = query.value("sparge_ph").toDouble(); reci->sparge_volume = query.value("sparge_volume").toDouble(); reci->sparge_source = query.value("sparge_source").toInt(); reci->sparge_acid_type = query.value("sparge_acid_type").toInt(); reci->sparge_acid_perc = query.value("sparge_acid_perc").toDouble(); reci->sparge_acid_amount = query.value("sparge_acid_amount").toDouble(); reci->mash_ph = query.value("mash_ph").toDouble(); reci->mash_name = query.value("mash_name").toString(); reci->calc_acid = query.value("calc_acid").toInt() ? true:false; reci->w1_name = query.value("w1_name").toString(); reci->w1_amount = query.value("w1_amount").toDouble(); reci->w1_calcium = query.value("w1_calcium").toDouble(); reci->w1_sulfate = query.value("w1_sulfate").toDouble(); reci->w1_chloride = query.value("w1_chloride").toDouble(); reci->w1_sodium = query.value("w1_sodium").toDouble(); reci->w1_magnesium = query.value("w1_magnesium").toDouble(); reci->w1_total_alkalinity = query.value("w1_total_alkalinity").toDouble(); reci->w1_ph = query.value("w1_ph").toDouble(); reci->w1_cost = query.value("w1_cost").toDouble(); reci->w2_name = query.value("w2_name").toString(); reci->w2_amount = query.value("w2_amount").toDouble(); reci->w2_calcium = query.value("w2_calcium").toDouble(); reci->w2_sulfate = query.value("w2_sulfate").toDouble(); reci->w2_chloride = query.value("w2_chloride").toDouble(); reci->w2_sodium = query.value("w2_sodium").toDouble(); reci->w2_magnesium = query.value("w2_magnesium").toDouble(); reci->w2_total_alkalinity = query.value("w2_total_alkalinity").toDouble(); reci->w2_ph = query.value("w2_ph").toDouble(); reci->w2_cost = query.value("w2_cost").toDouble(); reci->wg_amount = query.value("wg_amount").toDouble(); reci->wg_calcium = query.value("wg_calcium").toDouble(); reci->wg_sulfate = query.value("wg_sulfate").toDouble(); reci->wg_chloride = query.value("wg_chloride").toDouble(); reci->wg_sodium = query.value("wg_sodium").toDouble(); reci->wg_magnesium = query.value("wg_magnesium").toDouble(); reci->wg_total_alkalinity = query.value("wg_total_alkalinity").toDouble(); reci->wg_ph = query.value("wg_ph").toDouble(); reci->wb_calcium = query.value("wb_calcium").toDouble(); reci->wb_sulfate = query.value("wb_sulfate").toDouble(); reci->wb_chloride = query.value("wb_chloride").toDouble(); reci->wb_sodium = query.value("wb_sodium").toDouble(); reci->wb_magnesium = query.value("wb_magnesium").toDouble(); reci->wb_total_alkalinity = query.value("wb_total_alkalinity").toDouble(); reci->wb_ph = query.value("wb_ph").toDouble(); reci->wa_acid_name = query.value("wa_acid_name").toInt(); reci->wa_acid_perc = query.value("wa_acid_perc").toDouble(); reci->wa_base_name = query.value("wa_base_name").toInt(); QJsonParseError parseError; const auto& f_json = query.value("json_fermentables").toString(); if (!f_json.trimmed().isEmpty()) { const auto& formattedJson = QString("%1").arg(f_json); QJsonDocument fermentables = QJsonDocument::fromJson(formattedJson.toUtf8(), &parseError); if (parseError.error != QJsonParseError::NoError) { qWarning() << "Parse error: " << parseError.errorString() << "at" << parseError.offset ; } else if (fermentables.isArray()) { double percentcheck = 0; for (int i = 0; i < fermentables.array().size(); i++) { QJsonObject obj = fermentables.array().at(i).toObject(); Fermentables f; f.name = obj["f_name"].toString(); f.origin = obj["f_origin"].toString(); f.supplier = obj["f_supplier"].toString(); f.amount = obj["f_amount"].toDouble(); f.cost = obj["f_cost"].toDouble(); f.type = obj["f_type"].toInt(); f.yield = obj["f_yield"].toDouble(); f.color = obj["f_color"].toDouble(); f.coarse_fine_diff = obj["f_coarse_fine_diff"].toDouble(); f.moisture = obj["f_moisture"].toDouble(); f.diastatic_power = obj["f_diastatic_power"].toDouble(); f.protein = obj["f_protein"].toDouble(); f.dissolved_protein = obj["f_dissolved_protein"].toDouble(); f.max_in_batch = obj["f_max_in_batch"].toDouble(); f.graintype = obj["f_graintype"].toInt(); f.added = obj["f_added"].toInt(); f.recommend_mash = obj["f_recommend_mash"].toInt() ? true:false; f.add_after_boil = obj["f_add_after_boil"].toInt() ? true:false; f.adjust_to_total_100 = obj["f_adjust_to_total_100"].toInt() ? true:false; f.percentage = obj["f_percentage"].toDouble(); f.di_ph = obj["f_di_ph"].toDouble(); f.acid_to_ph_57 = obj["f_acid_to_ph_57"].toDouble(); if (f.adjust_to_total_100) reci->fermentables_use100 = true; percentcheck += f.percentage; reci->fermentables.append(f); } if (percentcheck == 0) { /* Missing percentages, fix it. */ double total = 0; for (int i = 0; i < reci->fermentables.size(); i++) { if (reci->fermentables.at(i).added < 4) total += reci->fermentables.at(i).amount; } for (int i = 0; i < reci->fermentables.size(); i++) { if (reci->fermentables.at(i).added < 4) reci->fermentables[i].percentage = round((reci->fermentables.at(i).amount / total) * 10000.0) / 100.0; } qInfo() << "fixed missing percentages"; } } } else { qDebug() << "empty fermentables"; } const auto& h_json = query.value("json_hops").toString(); if (!h_json.trimmed().isEmpty()) { const auto& formattedJson = QString("%1").arg(h_json); QJsonDocument hops = QJsonDocument::fromJson(formattedJson.toUtf8(), &parseError); if (parseError.error != QJsonParseError::NoError) { qWarning() << "Parse error: " << parseError.errorString() << "at" << parseError.offset; } else if (hops.isArray()) { for (int i = 0; i < hops.array().size(); i++) { QJsonObject obj = hops.array().at(i).toObject(); Hops h; h.name = obj["h_name"].toString(); h.origin = obj["h_origin"].toString(); h.amount = obj["h_amount"].toDouble(); h.cost = obj["h_cost"].toDouble(); h.type = obj["h_type"].toInt(); h.form = obj["h_form"].toInt(); h.useat = obj["h_useat"].toInt(); h.time = obj["h_time"].toInt(); h.alpha = obj["h_alpha"].toDouble(); h.beta = obj["h_beta"].toDouble(); h.hsi = obj["h_hsi"].toDouble(); h.humulene = obj["h_humulene"].toDouble(); h.caryophyllene = obj["h_caryophyllene"].toDouble(); h.cohumulone = obj["h_cohumulone"].toDouble(); h.myrcene = obj["h_myrcene"].toDouble(); h.total_oil = obj["h_total_oil"].toDouble(); reci->hops.append(h); } } } else { qDebug() << "empty hops"; } const auto& json = query.value("json_miscs").toString(); if (!json.trimmed().isEmpty()) { const auto& formattedJson = QString("%1").arg(json); QJsonDocument miscs = QJsonDocument::fromJson(formattedJson.toUtf8(), &parseError); if (parseError.error != QJsonParseError::NoError) { qWarning() << "Parse error: " << parseError.errorString() << "at" << parseError.offset; } else if (miscs.isArray()) { for (int i = 0; i < miscs.array().size(); i++) { QJsonObject obj = miscs.array().at(i).toObject(); Miscs m; m.name = obj["name"].toString(); m.amount = obj["amount"].toDouble(); m.type = obj["type"].toInt(); m.use_use = obj["use_use"].toInt(); m.time = obj["time"].toDouble(); m.amount_is_weight = obj["amount_is_weight"].toInt() ? true:false; m.cost = obj["cost"].toDouble(); reci->miscs.append(m); } } } else { qDebug() << "empty miscs"; } const auto& y_json = query.value("json_yeasts").toString(); if (!y_json.trimmed().isEmpty()) { const auto& formattedJson = QString("%1").arg(y_json); QJsonDocument yeasts = QJsonDocument::fromJson(formattedJson.toUtf8(), &parseError); if (parseError.error != QJsonParseError::NoError) { qWarning() << "Parse error: " << parseError.errorString() << "at" << parseError.offset ; } else if (yeasts.isArray()) { for (int i = 0; i < yeasts.array().size(); i++) { QJsonObject obj = yeasts.array().at(i).toObject(); Yeasts y; /* First some defaults for newer fields. */ y.tolerance = y.harvest_time = y.pitch_temperature = y.zymocide = 0; y.sta1 = y.bacteria = y.harvest_top = y.pofpos = false; y.gr_hl_lo = 50; y.sg_lo = 1.04; y.gr_hl_hi = 80; y.sg_hi = 1.08; /* Now get what we have got */ y.name = obj["y_name"].toString(); y.laboratory = obj["y_laboratory"].toString(); y.product_id = obj["y_product_id"].toString(); y.amount = obj["y_amount"].toDouble(); y.type = obj["y_type"].toInt(); y.form = obj["y_form"].toInt(); y.min_temperature = obj["y_min_temperature"].toDouble(); y.max_temperature = obj["y_max_temperature"].toDouble(); y.flocculation = obj["y_flocculation"].toInt(); y.attenuation = obj["y_attenuation"].toDouble(); y.cells = obj["y_cells"].toDouble(); y.tolerance = obj["y_tolerance"].toDouble(); y.inventory = obj["y_inventory"].toDouble(); y.use = obj["y_use"].toInt(); y.sta1 = obj["y_sta1"].toInt() ? true:false; y.bacteria = obj["y_bacteria"].toInt() ? true:false; y.harvest_top = obj["y_harvest_top"].toInt() ? true:false; y.harvest_time = obj["y_harvest_time"].toInt(); y.pitch_temperature = obj["y_pitch_temperature"].toDouble(); y.pofpos = obj["y_pofpos"].toInt() ? true:false; y.zymocide = obj["y_zymocide"].toInt(); y.gr_hl_lo = obj["y_gr_hl_lo"].toInt(); y.sg_lo = obj["y_sg_lo"].toDouble(); y.gr_hl_hi = obj["y_gr_hl_hi"].toInt(); y.sg_hi = obj["y_sg_hi"].toDouble(); y.cost = obj["y_cost"].toDouble(); if (y.tolerance == 0 || y.cells == 0) { // More and better tests? /* * Possible data upgrade needed. */ yquery.prepare("SELECT tolerance,cells,sta1,bacteria,harvest_top,harvest_time,pitch_temperature," "pofpos,zymocide,gr_hl_lo,sg_lo,gr_hl_hi,sg_hi " "FROM inventory_yeasts WHERE name=:name AND laboratory=:laboratory AND product_id=:product_id"); yquery.bindValue(":name", y.name); yquery.bindValue(":laboratory", y.laboratory); yquery.bindValue(":product_id", y.product_id); yquery.exec(); if (yquery.first()) { y.tolerance = yquery.value(0).toDouble(); y.cells = yquery.value(1).toDouble(); y.sta1 = yquery.value(2).toInt() ? true:false; y.bacteria = yquery.value(3).toInt() ? true:false; y.harvest_top = yquery.value(4).toInt() ? true:false; y.harvest_time = yquery.value(5).toInt(); y.pitch_temperature = yquery.value(6).toDouble(); y.pofpos = yquery.value(7).toInt() ? true:false; y.zymocide = yquery.value(8).toInt(); y.gr_hl_lo = yquery.value(9).toInt(); y.sg_lo = yquery.value(10).toDouble(); y.gr_hl_hi = yquery.value(11).toInt(); y.sg_hi = yquery.value(12).toDouble(); } else { qDebug() << y.name << y.product_id << "not found for upgrade"; } } reci->yeasts.append(y); } } } else { qDebug() << "empty yeasts"; } const auto& ma_json = query.value("json_mashs").toString().trimmed(); if (!ma_json.trimmed().isEmpty()) { const auto& formattedJson = QString("%1").arg(ma_json); QJsonDocument mashs = QJsonDocument::fromJson(formattedJson.toUtf8(), &parseError); if (parseError.error != QJsonParseError::NoError) { qWarning() << "Parse error: " << parseError.errorString() << "at" << parseError.offset ; } else if (mashs.isArray()) { for (int i = 0; i < mashs.array().size(); i++) { QJsonObject obj = mashs.array().at(i).toObject(); MashSteps m; m.step_name = obj["step_name"].toString(); m.step_type = obj["step_type"].toInt(); m.step_volume = obj["step_volume"].toDouble(); m.step_infuse_amount = obj["step_infuse_amount"].toDouble(); m.step_infuse_temp = obj["step_infuse_temp"].toDouble(); m.step_temp = obj["step_temp"].toDouble(); m.step_time = obj["step_time"].toDouble(); m.ramp_time = obj["ramp_time"].toDouble(); m.end_temp = obj["end_temp"].toDouble(); m.step_wg_ratio = obj["step_wg_ratio"].toDouble(); reci->mashs.append(m); } } } else { qDebug() << "empty mashs"; } qInfo() << "loadRecipe" << reci->record << "done"; return true; } bool DB_recipe::save(Recipe *reci, QDialog *dialog) { QSqlQuery query; QString sql = ""; if (reci->record == -1) { sql = "INSERT INTO recipes SET "; } else { sql = "UPDATE recipes SET "; } sql.append("locked=:locked, st_name=:st_name, st_letter=:st_letter, " "st_guide=:st_guide, st_category=:st_category, st_category_number=:st_catnr, st_type=:st_type, " "st_og_min=:st_og_min, st_og_max=:st_og_max, st_fg_min=:st_fg_min, st_fg_max=:st_fg_max, " "st_ibu_min=:st_ibu_min, st_ibu_max=:st_ibu_max, st_color_min=:st_color_min, st_color_max=:st_color_max, " "st_carb_min=:st_carb_min, st_carb_max=:st_carb_max, st_abv_min=:st_abv_min, st_abv_max=:st_abv_max, " "name=:name, notes=:notes, type=:type, batch_size=:batch_size, boil_size=:boil_size, " "boil_time=:boil_time, efficiency=:efficiency, est_og=:est_og, est_fg=:est_fg, est_abv=:est_abv, " "est_color=:est_color, color_method=:color_method, est_ibu=:est_ibu, ibu_method=:ibu_method, " "est_carb=:est_carb, sparge_temp=:sparge_temp, sparge_ph=:sparge_ph, " "sparge_volume=:sparge_volume, sparge_source=:sparge_source, sparge_acid_type=:sparge_acid_type, " "sparge_acid_perc=:sparge_acid_perc, sparge_acid_amount=:sparge_acid_amount, mash_ph=:mash_ph, " "mash_name=:mash_name, calc_acid=:calc_acid, " "w1_name=:w1_name, w1_amount=:w1_amount, w1_calcium=:w1_calcium, w1_sulfate=:w1_sulfate, " "w1_chloride=:w1_chloride, w1_sodium=:w1_sodium, w1_magnesium=:w1_magnesium, " "w1_total_alkalinity=:w1_total_alkalinity, w1_ph=:w1_ph, w1_cost=:w1_cost, " "w2_name=:w2_name, w2_amount=:w2_amount, w2_calcium=:w2_calcium, w2_sulfate=:w2_sulfate, " "w2_chloride=:w2_chloride, w2_sodium=:w2_sodium, w2_magnesium=:w2_magnesium, " "w2_total_alkalinity=:w2_total_alkalinity, w2_ph=:w2_ph, w2_cost=:w2_cost, " "wg_amount=:wg_amount, wg_calcium=:wg_calcium, wg_sulfate=:wg_sulfate, " "wg_chloride=:wg_chloride, wg_sodium=:wg_sodium, wg_magnesium=:wg_magnesium, " "wg_total_alkalinity=:wg_total_alkalinity, wg_ph=:wg_ph, " "wb_calcium=:wb_calcium, wb_sulfate=:wb_sulfate, wb_chloride=:wb_chloride, wb_sodium=:wb_sodium, " "wb_magnesium=:wb_magnesium, wb_total_alkalinity=:wb_total_alkalinity, wb_ph=:wb_ph, " "wa_acid_name=:wa_acid_name, wa_acid_perc=:wa_acid_perc, wa_base_name=:wa_base_name, " "json_fermentables=:json_fermentables, json_hops=:json_hops, json_miscs=:json_miscs, " "json_yeasts=:json_yeasts, json_mashs=:json_mashs"); if (reci->record == -1) { sql.append(", uuid=:uuid"); } else { sql.append(" WHERE record = :recno"); } query.prepare(sql); query.bindValue(":locked", reci->locked ? 1:0); query.bindValue(":st_name", reci->st_name); query.bindValue(":st_letter", reci->st_letter); query.bindValue(":st_guide", reci->st_guide); query.bindValue(":st_category", reci->st_category); query.bindValue(":st_catnr", reci->st_category_number); query.bindValue(":st_type", reci->st_type); query.bindValue(":st_og_min", round(reci->st_og_min * 1000) / 1000); query.bindValue(":st_og_max", round(reci->st_og_max * 1000) / 1000); query.bindValue(":st_fg_min", round(reci->st_fg_min * 1000) / 1000); query.bindValue(":st_fg_max", round(reci->st_fg_max * 1000) / 1000); query.bindValue(":st_ibu_min", round(reci->st_ibu_min * 10) / 10); query.bindValue(":st_ibu_max", round(reci->st_ibu_max * 10) / 10); query.bindValue(":st_color_min", round(reci->st_color_min * 10) / 10); query.bindValue(":st_color_max", round(reci->st_color_max * 10) / 10); query.bindValue(":st_carb_min", round(reci->st_carb_min * 10) / 10); query.bindValue(":st_carb_max", round(reci->st_carb_max * 10) / 10); query.bindValue(":st_abv_min", round(reci->st_abv_min * 10) / 10); query.bindValue(":st_abv_max", round(reci->st_abv_max * 10) / 10); query.bindValue(":name", reci->name); query.bindValue(":notes", reci->notes); query.bindValue(":type", reci->type); query.bindValue(":batch_size", round(reci->batch_size * 10) / 10); query.bindValue(":boil_size", round(reci->boil_size * 10) / 10); query.bindValue(":boil_time", round(reci->boil_time * 10) / 10); query.bindValue(":efficiency", round(reci->efficiency * 10) / 10); query.bindValue(":est_og", round(reci->est_og * 1000) / 1000); query.bindValue(":est_fg", round(reci->est_fg * 1000) / 1000); query.bindValue(":est_abv", round(reci->est_abv * 10) / 10); query.bindValue(":est_color", round(reci->est_color * 10) / 10); query.bindValue(":color_method", reci->color_method); query.bindValue(":est_ibu", round(reci->est_ibu * 10) / 10); query.bindValue(":ibu_method", reci->ibu_method); query.bindValue(":est_carb", round(reci->est_carb * 10) / 10); query.bindValue(":sparge_temp", round(reci->sparge_temp * 10) / 10); query.bindValue(":sparge_ph", round(reci->sparge_ph * 100) / 100); query.bindValue(":sparge_volume", round(reci->sparge_volume * 10) / 10); query.bindValue(":sparge_source", reci->sparge_source); query.bindValue(":sparge_acid_type", reci->sparge_acid_type); query.bindValue(":sparge_acid_perc", round(reci->sparge_acid_perc * 10) / 10); query.bindValue(":sparge_acid_amount", round(reci->sparge_acid_amount * 100000) / 100000); query.bindValue(":mash_ph", round(reci->mash_ph * 100) / 100); query.bindValue(":mash_name", reci->mash_name); query.bindValue(":calc_acid", reci->calc_acid ?1:0); query.bindValue(":w1_name", reci->w1_name); query.bindValue(":w1_amount", round(reci->w1_amount * 10) / 10); query.bindValue(":w1_calcium", round(reci->w1_calcium * 100000) / 100000); query.bindValue(":w1_sulfate", round(reci->w1_sulfate * 100000) / 100000); query.bindValue(":w1_chloride", round(reci->w1_chloride * 100000) / 100000); query.bindValue(":w1_sodium", round(reci->w1_sodium * 100000) / 100000); query.bindValue(":w1_magnesium", round(reci->w1_magnesium * 100000) / 100000); query.bindValue(":w1_total_alkalinity", round(reci->w1_total_alkalinity * 100000) / 100000); query.bindValue(":w1_ph", round(reci->w1_ph * 100) / 100); query.bindValue(":w1_cost", round(reci->w1_cost * 100) / 100); query.bindValue(":w2_name", reci->w2_name); query.bindValue(":w2_amount", round(reci->w2_amount * 10) / 10); query.bindValue(":w2_calcium", round(reci->w2_calcium * 100000) / 100000); query.bindValue(":w2_sulfate", round(reci->w2_sulfate * 100000) / 100000); query.bindValue(":w2_chloride", round(reci->w2_chloride * 100000) / 100000); query.bindValue(":w2_sodium", round(reci->w2_sodium * 100000) / 100000); query.bindValue(":w2_magnesium", round(reci->w2_magnesium * 100000) / 100000); query.bindValue(":w2_total_alkalinity", round(reci->w2_total_alkalinity * 100000) / 100000); query.bindValue(":w2_ph", round(reci->w2_ph * 100) / 100); query.bindValue(":w2_cost", round(reci->w2_cost * 100) / 100); query.bindValue(":wg_amount", round(reci->wg_amount * 10) / 10); query.bindValue(":wg_calcium", round(reci->wg_calcium * 100000) / 100000); query.bindValue(":wg_sulfate", round(reci->wg_sulfate * 100000) / 100000); query.bindValue(":wg_chloride", round(reci->wg_chloride * 100000) / 100000); query.bindValue(":wg_sodium", round(reci->wg_sodium * 100000) / 100000); query.bindValue(":wg_magnesium", round(reci->wg_magnesium * 100000) / 100000); query.bindValue(":wg_total_alkalinity", round(reci->wg_total_alkalinity * 100000) / 100000); query.bindValue(":wg_ph", round(reci->wg_ph * 100) / 100); query.bindValue(":wb_calcium", round(reci->wb_calcium * 100000) / 100000); query.bindValue(":wb_sulfate", round(reci->wb_sulfate * 100000) / 100000); query.bindValue(":wb_chloride", round(reci->wb_chloride * 100000) / 100000); query.bindValue(":wb_sodium", round(reci->wb_sodium * 100000) / 100000); query.bindValue(":wb_magnesium", round(reci->wb_magnesium * 100000) / 100000); query.bindValue(":wb_total_alkalinity", round(reci->wb_total_alkalinity * 100000) / 100000); query.bindValue(":wb_ph", round(reci->wb_ph * 100) / 100); query.bindValue(":wa_acid_name", reci->wa_acid_name); query.bindValue(":wa_acid_perc", round(reci->wa_acid_perc * 10) / 10); query.bindValue(":wa_base_name", reci->wa_base_name); if (reci->fermentables.size() == 0) { query.bindValue(":json_fermentables", "[]"); } else { QJsonArray array; for (int i = 0; i < reci->fermentables.size(); i++) { QJsonObject obj; obj.insert("f_name", reci->fermentables.at(i).name); obj.insert("f_origin", reci->fermentables.at(i).origin); obj.insert("f_supplier", reci->fermentables.at(i).supplier); obj.insert("f_amount", round(reci->fermentables.at(i).amount * 10000) / 10000); obj.insert("f_cost", round(reci->fermentables.at(i).cost * 1000) / 1000); obj.insert("f_type", reci->fermentables.at(i).type); obj.insert("f_yield", round(reci->fermentables.at(i).yield * 10) / 10); obj.insert("f_color", round(reci->fermentables.at(i).color * 10) / 10); obj.insert("f_coarse_fine_diff", round(reci->fermentables.at(i).coarse_fine_diff * 10) / 10); obj.insert("f_moisture", round(reci->fermentables.at(i).moisture * 10) / 10); obj.insert("f_diastatic_power", round(reci->fermentables.at(i).diastatic_power * 100000) / 100000); obj.insert("f_protein", round(reci->fermentables.at(i).protein * 10) / 10); obj.insert("f_dissolved_protein", round(reci->fermentables.at(i).dissolved_protein * 10) / 10); obj.insert("f_max_in_batch", reci->fermentables.at(i).max_in_batch); obj.insert("f_graintype", reci->fermentables.at(i).graintype); obj.insert("f_added", reci->fermentables.at(i).added); obj.insert("f_recommend_mash", reci->fermentables.at(i).recommend_mash ? 1:0); obj.insert("f_add_after_boil", reci->fermentables.at(i).add_after_boil ? 1:0); obj.insert("f_adjust_to_total_100", reci->fermentables.at(i).adjust_to_total_100 ? 1:0); obj.insert("f_percentage", round(reci->fermentables.at(i).percentage * 10) / 10); obj.insert("f_di_ph", round(reci->fermentables.at(i).di_ph * 100000) / 100000); obj.insert("f_acid_to_ph_57", round(reci->fermentables.at(i).acid_to_ph_57 * 100000) / 100000); array.append(obj); /* Append this object */ } QJsonDocument doc; doc.setArray(array); query.bindValue(":json_fermentables", doc.toJson(QJsonDocument::Compact)); } if (reci->hops.size() == 0) { query.bindValue(":json_hops", "[]"); } else { QJsonArray array; for (int i = 0; i < reci->hops.size(); i++) { QJsonObject obj; obj.insert("h_name", reci->hops.at(i).name); obj.insert("h_origin", reci->hops.at(i).origin); obj.insert("h_amount", round(reci->hops.at(i).amount * 10000) / 10000); obj.insert("h_cost", round(reci->hops.at(i).cost * 100) / 100); obj.insert("h_type", reci->hops.at(i).type); obj.insert("h_form", reci->hops.at(i).form); obj.insert("h_useat", reci->hops.at(i).useat); obj.insert("h_time", round(reci->hops.at(i).time)); obj.insert("h_alpha", round(reci->hops.at(i).alpha * 100) / 100); obj.insert("h_beta", round(reci->hops.at(i).beta * 100) / 100); obj.insert("h_hsi", round(reci->hops.at(i).hsi * 100) / 100); obj.insert("h_humulene", round(reci->hops.at(i).humulene * 100) / 100); obj.insert("h_caryophyllene", round(reci->hops.at(i).caryophyllene * 100) / 100); obj.insert("h_cohumulone", round(reci->hops.at(i).cohumulone * 100) / 100); obj.insert("h_myrcene", round(reci->hops.at(i).myrcene * 100) / 100); obj.insert("h_total_oil", round(reci->hops.at(i).total_oil * 100) / 100); array.append(obj); /* Append this object */ } QJsonDocument doc; doc.setArray(array); query.bindValue(":json_hops", doc.toJson(QJsonDocument::Compact)); } if (reci->miscs.size() == 0) { query.bindValue(":json_miscs", "[]"); } else { QJsonArray array; for (int i = 0; i < reci->miscs.size(); i++) { QJsonObject obj; obj.insert("name", reci->miscs.at(i).name); obj.insert("amount", round(reci->miscs.at(i).amount * 10000) / 10000); obj.insert("type", reci->miscs.at(i).type); obj.insert("use_use", reci->miscs.at(i).use_use); obj.insert("time", round(reci->miscs.at(i).time)); obj.insert("amount_is_weight", reci->miscs.at(i).amount_is_weight ? 1:0); obj.insert("cost", round(reci->miscs.at(i).cost * 10000) / 10000); array.append(obj); /* Append this object */ } QJsonDocument doc; doc.setArray(array); query.bindValue(":json_miscs", doc.toJson(QJsonDocument::Compact)); } if (reci->yeasts.size() == 0) { query.bindValue(":json_yeasts", "[]"); } else { QJsonArray array; for (int i = 0; i < reci->yeasts.size(); i++) { QJsonObject obj; obj.insert("y_name", reci->yeasts.at(i).name); obj.insert("y_laboratory", reci->yeasts.at(i).laboratory); obj.insert("y_product_id", reci->yeasts.at(i).product_id); obj.insert("y_amount", round(reci->yeasts.at(i).amount * 10000) / 10000); obj.insert("y_type", reci->yeasts.at(i).type); obj.insert("y_form", reci->yeasts.at(i).form); obj.insert("y_min_temperature", round(reci->yeasts.at(i).min_temperature * 10) / 10); obj.insert("y_max_temperature", round(reci->yeasts.at(i).max_temperature * 10) / 10); obj.insert("y_flocculation", reci->yeasts.at(i).flocculation); obj.insert("y_attenuation", round(reci->yeasts.at(i).attenuation * 10) / 10); obj.insert("y_cells", reci->yeasts.at(i).cells); obj.insert("y_tolerance", round(reci->yeasts.at(i).tolerance * 10) / 10); obj.insert("y_inventory", round(reci->yeasts.at(i).inventory * 10000) / 10000); obj.insert("y_use", reci->yeasts.at(i).use); obj.insert("y_sta1", reci->yeasts.at(i).sta1 ? 1:0); obj.insert("y_bacteria", reci->yeasts.at(i).bacteria ? 1:0); obj.insert("y_harvest_top", reci->yeasts.at(i).harvest_top ? 1:0); obj.insert("y_harvest_time", reci->yeasts.at(i).harvest_time); obj.insert("y_pitch_temperature", round(reci->yeasts.at(i).pitch_temperature * 10) / 10); obj.insert("y_pofpos", reci->yeasts.at(i).pofpos ? 1:0); obj.insert("y_zymocide", reci->yeasts.at(i).zymocide); obj.insert("y_gr_hl_lo", reci->yeasts.at(i).gr_hl_lo); obj.insert("y_sg_lo", round(reci->yeasts.at(i).sg_lo * 1000) / 1000); obj.insert("y_gr_hl_hi", reci->yeasts.at(i).gr_hl_hi); obj.insert("y_sg_hi", round(reci->yeasts.at(i).sg_hi * 1000) / 1000); obj.insert("y_cost", round(reci->yeasts.at(i).cost * 1000) / 1000); array.append(obj); /* Append this object */ } QJsonDocument doc; doc.setArray(array); query.bindValue(":json_yeasts", doc.toJson(QJsonDocument::Compact)); } if (reci->mashs.size() == 0) { query.bindValue(":json_mashs", "[]"); } else { QJsonArray array; for (int i = 0; i < reci->mashs.size(); i++) { QJsonObject obj; obj.insert("step_name", reci->mashs.at(i).step_name); obj.insert("step_type", reci->mashs.at(i).step_type); obj.insert("step_volume", round(reci->mashs.at(i).step_volume * 100) / 100); obj.insert("step_infuse_amount", round(reci->mashs.at(i).step_infuse_amount * 100) / 100); obj.insert("step_infuse_temp", round(reci->mashs.at(i).step_infuse_temp * 100) / 100); obj.insert("step_temp", round(reci->mashs.at(i).step_temp * 100) / 100); obj.insert("step_time", round(reci->mashs.at(i).step_time * 100) / 100); obj.insert("ramp_time", round(reci->mashs.at(i).ramp_time * 100) / 100); obj.insert("end_temp", round(reci->mashs.at(i).end_temp * 100) / 100); obj.insert("step_wg_ratio", round(reci->mashs.at(i).step_wg_ratio * 100) / 100); array.append(obj); /* Append this object */ } QJsonDocument doc; doc.setArray(array); query.bindValue(":json_mashs", doc.toJson(QJsonDocument::Compact)); } if (reci->record == -1) { query.bindValue(":uuid", QUuid::createUuid().toString().mid(1, 36)); } else { query.bindValue(":recno", reci->record); } query.exec(); if (query.lastError().isValid()) { qWarning() << "saveRecipe" << query.lastError(); QMessageBox::warning(dialog, QObject::tr("Database error"), QObject::tr("MySQL error: %1\n%2\n%3") .arg(query.lastError().nativeErrorCode()) .arg(query.lastError().driverText()) .arg(query.lastError().databaseText())); return false; } /* * If this was a new recipe, find out what record number we * have got and set it. So when the user saves this record * again, it will be updated instead of inserting a new copy. */ if (reci->record < 0) { QVariant id = query.lastInsertId(); reci->record = id.toInt(); qInfo() << "saveRecipe Inserted record" << reci->record; } else { qInfo() << "saveRecipe Updated record" << reci->record; } return true; } bool DB_recipe::dele(QDialog *dialog, int recno) { QSqlQuery query; query.prepare("DELETE FROM recipes WHERE record = :recno"); query.bindValue(":recno", recno); query.exec(); if (query.lastError().isValid()) { qWarning() << "deleteRecipe" << query.lastError(); QMessageBox::warning(dialog, QObject::tr("Database error"), QObject::tr("MySQL error: %1\n%2\n%3") .arg(query.lastError().nativeErrorCode()) .arg(query.lastError().driverText()) .arg(query.lastError().databaseText())); return false; } qInfo() << "deleteRecipe Deleted" << recno; return true; }