Production:->Batch Log Print... 0) { searchClause = " WHERE (person ~* :p1 OR rname ~* :p2 OR mname ~* :p3 OR greens ~* :p4 OR annotation ~* :p5 OR array_to_string(files, ',') ~* :p6)"; } var q = "WITH qq AS (SELECT roasting_log.time, array_to_string(files, ','), person, (SELECT name || ' (' || id || ')' FROM items WHERE id = roasted_id) AS rname, duration, (SELECT name FROM machine WHERE id = machine) AS mname, array_to_string(ARRAY(SELECT name || ' (' || id || ')' FROM items WHERE id IN (SELECT unnest(unroasted_id))), ',') AS greens, (unroasted_total_quantity/:c1)::numeric(12,2), (roasted_quantity/:c2)::numeric(12,2), loss, annotation, approval, spec_loss::numeric(12,2) || '±' || spec_tolerance::numeric(12,2) AS lspec, notes, loss_match, machine || '@' || roasting_log.time AS link, files, additional_data, spec FROM roasting_log, LATERAL (SELECT CASE WHEN (unroasted_total_quantity = 0) THEN NULL ELSE (((unroasted_total_quantity - roasted_quantity)/unroasted_total_quantity)*100)::numeric(12,2) END AS loss) lc, LATERAL (WITH q AS (SELECT (SELECT min(time) - interval '10 years' FROM roasting_log) AS time, NULL::numeric AS loss, NULL::numeric AS tolerance, NULL::text AS notes, NULL::jsonb AS spec) SELECT time, (loss*100)::numeric(12,2) AS spec_loss, (tolerance*100)::numeric(12,2) AS spec_tolerance, notes, spec FROM roasting_specification WHERE item = roasted_id AND time = (SELECT max(time) FROM roasting_specification WHERE time <= roasting_log.time AND item = roasted_id) UNION (SELECT * FROM q) ORDER BY time DESC LIMIT 1) rspec, LATERAL (SELECT loss >= spec_loss - spec_tolerance AND loss <= spec_loss + spec_tolerance AS loss_match) m WHERE roasting_log.time >= :sd AND roasting_log.time < :ed::date + interval '1 day'" + approvalClause + batchClause + ") SELECT * FROM qq" + searchClause + " ORDER BY time DESC"; var query = new QSqlQuery(); query.prepare(q); query.bind(":c1", conversion); query.bind(":c2", conversion); query.bind(":sd", startDate); query.bind(":ed", endDate); if(searchClause.length > 0) { var pattern = ".*" + search.text + ".*"; query.bind(":p1", pattern); query.bind(":p2", pattern); query.bind(":p3", pattern); query.bind(":p4", pattern); query.bind(":p5", pattern); query.bind(":p6", pattern); } query.exec(); var buffer = new QBuffer; buffer.open(3); var output = new XmlWriter(buffer); output.writeStartDocument("1.0"); output.writeDTD(''); output.writeStartElement("html"); output.writeAttribute("xmlns", "http://www.w3.org/1999/xhtml"); output.writeStartElement("head"); output.writeTextElement("title", TTR("batchreport", "Batch Log")); output.writeEndElement(); output.writeStartElement("body"); var cdt = new Date(Date.now()); output.writeTextElement("p", cdt.toLocaleDateString(TTR("reports", "en-US")) + " " + cdt.toLocaleTimeString(TTR("reports", "en-US"))); output.writeStartElement("table"); output.writeAttribute("style", "page-break-after: auto; text-align: left"); output.writeAttribute("rules", "groups"); output.writeAttribute("cellpadding", "3px"); output.writeStartElement("thead"); output.writeStartElement("tr"); output.writeAttribute("valign", "bottom"); output.writeTextElement("th", TTR("batchreport", "Time")); output.writeTextElement("th", TTR("batchreport", "File Numbers")); output.writeTextElement("th", TTR("batchreport", "Operator")); output.writeTextElement("th", TTR("batchreport", "Roasted Coffee")); output.writeEndElement(); output.writeStartElement("tr"); output.writeAttribute("valign", "bottom"); output.writeEmptyElement("td"); output.writeTextElement("th", TTR("batchreport", "Duration")); output.writeTextElement("th", TTR("batchreport", "Machine")); output.writeTextElement("th", TTR("batchreport", "Green Coffees")); output.writeEndElement(); output.writeStartElement("tr"); output.writeAttribute("valign", "bottom"); output.writeEmptyElement("td"); output.writeTextElement("th", TTR("batchreport", "Green Weight")); output.writeTextElement("th", TTR("batchreport", "Roasted Weight")); output.writeTextElement("th", TTR("batchreport", "% Weight Loss")); output.writeEndElement(); output.writeStartElement("tr"); output.writeAttribute("valign", "bottom"); output.writeEmptyElement("td"); output.writeTextElement("th", TTR("batchreport", "Degree of Roast")); output.writeEndElement(); output.writeStartElement("tr"); output.writeAttribute("valign", "bottom"); output.writeEmptyElement("td"); output.writeStartElement("th"); output.writeAttribute("colspan", "2"); output.writeCharacters(TTR("batchreport", "Batch Notes")); output.writeEndElement(); output.writeTextElement("th", TTR("batchreport", "Specification Notes")); output.writeEndElement(); output.writeEndElement(); output.writeStartElement("tbody"); while(query.next()) { output.writeStartElement("tr"); output.writeAttribute("valign", "top"); output.writeStartElement("td"); output.writeStartElement("a"); output.writeAttribute("href", "typica://script/b/" + query.value(15)); output.writeCharacters(query.value(0).replace("T", " ")); output.writeEndElement(); output.writeEndElement(); output.writeStartElement("td"); output.writeStartElement("a"); output.writeAttribute("href", "typica://script/b/" + query.value(15)); output.writeCharacters(query.value(1)); output.writeEndElement(); output.writeEndElement(); output.writeTextElement("td", query.value(2)); output.writeStartElement("td"); output.writeStartElement("span"); if(query.value(11) == "false") { output.writeAttribute("style", "color:#FF0000"); } output.writeCharacters(query.value(3)); output.writeEndElement(); output.writeEndElement(); output.writeEndElement(); output.writeStartElement("tr"); output.writeAttribute("valign", "top"); output.writeEmptyElement("td"); output.writeTextElement("td", query.value(4)); output.writeTextElement("td", query.value(5)); output.writeTextElement("td", query.value(6)); output.writeEndElement(); output.writeStartElement("tr"); output.writeAttribute("valign", "top"); output.writeEmptyElement("td"); output.writeTextElement("td", query.value(7)); output.writeTextElement("td", query.value(8)); output.writeStartElement("td"); output.writeStartElement("span"); if(query.value(14) == "false" && query.value(12).length > 0) { output.writeAttribute("style", "color:#FF0000"); } else if (query.value(14) === "true") { output.writeAttribute("style", "color:#00FF00"); } output.writeAttribute("title", query.value(12)); output.writeCharacters(query.value(9)); output.writeEndElement(); output.writeEndElement(); output.writeEndElement(); output.writeStartElement("tr"); output.writeAttribute("valign", "top"); output.writeEmptyElement("td"); if(query.value(17).length > 0) { extradata = JSON.parse(query.value(17)); if(extradata.color) { wcolor = "#000000"; gcolor = "#000000"; wtitle = ""; gtitle = ""; if(query.value(18).length > 0) { specdata = JSON.parse(query.value(18)); if(extradata.color.whole && specdata.color.whole.expected) { wmin = Number(specdata.color.whole.expected); wmax = wmin; wtitle += specdata.color.whole.expected; if(specdata.color.whole.tolerance) { wmin -= Number(specdata.color.whole.tolerance); wmax += Number(specdata.color.whole.tolerance); wtitle += "±"; wtitle += specdata.color.whole.tolerance; } if(Number(extradata.color.whole) < wmin || Number(extradata.color.whole) > wmax) { wcolor = "#FF0000"; } else { wcolor = "#00FF00"; } } if(extradata.color.ground && specdata.color.ground.expected) { gmin = Number(specdata.color.ground.expected); gmax = gmin; gtitle += specdata.color.ground.expected; if(specdata.color.ground.tolerance) { gmin -= Number(specdata.color.ground.tolerance); gmax += Number(specdata.color.ground.tolerance); gtitle += "±"; gtitle += specdata.color.ground.tolerance; } if(Number(extradata.color.ground) < gmin || Number(extradata.color.ground) > gmax) { gcolor = "#FF0000"; } else { gcolor = "#00FF00"; } } } output.writeStartElement("td"); if(extradata.color.whole) { output.writeStartElement("span"); output.writeAttribute("style", "color:"+wcolor); output.writeAttribute("title", wtitle); output.writeCharacters(extradata.color.whole); output.writeEndElement(); } output.writeStartElement("span"); if(wcolor === gcolor) { output.writeAttribute("style", "color:"+wcolor); } output.writeCharacters("/"); output.writeEndElement(); if(extradata.color.ground) { output.writeStartElement("span"); output.writeAttribute("style", "color:"+gcolor); output.writeAttribute("title", gtitle); output.writeCharacters(extradata.color.ground); output.writeEndElement(); } output.writeEndElement(); } } output.writeEndElement(); output.writeStartElement("tr"); output.writeAttribute("valign", "top"); output.writeEmptyElement("td"); output.writeStartElement("td"); output.writeAttribute("colspan", "2"); output.writeAttribute("style", "max-width: 400px"); var noteArray = query.value(10).split("\n"); for(var i = 0; i < noteArray.length; i++) { output.writeStartElement("p"); output.writeAttribute("style", "margin-top: 0; margin-bottom: 0"); output.writeCharacters(noteArray[i]); output.writeEndElement(); } output.writeEndElement(); output.writeStartElement("td"); output.writeAttribute("style", "max-width: 400px"); var specArray = query.value(13).split("\n"); for(var i = 0; i < specArray.length; i++) { output.writeStartElement("p", specArray[i]); output.writeAttribute("style", "margin-top: 0; margin-bottom: 0"); output.writeCharacters(specArray[i]); output.writeEndElement(); } output.writeEndElement(); output.writeEndElement(); } output.writeEndElement(); output.writeStartElement("tfoot"); output.writeStartElement("tr"); output.writeAttribute("valign", "bottom"); output.writeTextElement("th", TTR("batchreport", "Total Batches")); output.writeTextElement("th", TTR("batchreport", "Total Duration")); output.writeTextElement("th", TTR("batchreport", "Total Green Weight")); output.writeTextElement("th", TTR("batchreport", "Total Roasted Weight")); output.writeEndElement(); output.writeStartElement("tr"); output.writeAttribute("valign", "top"); q = "WITH qq AS (SELECT roasting_log.time, array_to_string(files, ','), person, (SELECT name || ' (' || id || ')' FROM items WHERE id = roasted_id) AS rname, duration, (SELECT name FROM machine WHERE id = machine) AS mname, array_to_string(ARRAY(SELECT name || ' (' || id || ')' FROM items WHERE id IN (SELECT unnest(unroasted_id))), ',') AS greens, (unroasted_total_quantity/:c1)::numeric(12,2) AS uq, (roasted_quantity/:c2)::numeric(12,2) AS rq, annotation, approval, files FROM roasting_log WHERE roasting_log.time >= :sd AND roasting_log.time < :ed::date + interval '1 day'" + approvalClause + batchClause + ") SELECT count(1), sum(duration), sum(uq), sum(rq) FROM qq" + searchClause; var query = new QSqlQuery(); query.prepare(q); query.bind(":c1", conversion); query.bind(":c2", conversion); query.bind(":sd", startDate); query.bind(":ed", endDate); if(searchClause.length > 0) { var pattern = ".*" + search.text + ".*"; query.bind(":p1", pattern); query.bind(":p2", pattern); query.bind(":p3", pattern); query.bind(":p4", pattern); query.bind(":p5", pattern); query.bind(":p6", pattern); } query.exec(); query.next(); for(var i = 0; i < 4; i++) { output.writeTextElement("td", query.value(i)); } output.writeEndElement(); output.writeEndElement(); query = query.invalidate(); output.writeEndElement(); output.writeEndElement(); output.writeEndDocument(); view.setContent(buffer); buffer.close(); }; refresh(); var notifier = Application.subscribe("roastinglogchange"); notifier.notify.connect(function() { refresh(); }); ]]>