Typica is a free program for professional coffee roasters. https://typica.us
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

auco.xml 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. <window id="useandcostreport">
  2. <reporttitle>Production:->Average Use and Cost by Origin</reporttitle>
  3. <layout type="vertical">
  4. <layout type="horizontal">
  5. <daterange id="dates" initial="23" /><!-- Lifetime -->
  6. <label>Sort Order:</label>
  7. <sqldrop id="sort" />
  8. <label>Weight Unit:</label>
  9. <sqldrop id="unit" />
  10. <stretch />
  11. </layout>
  12. <webview id="report" />
  13. </layout>
  14. <menu name="File">
  15. <item id="print" shortcut="Ctrl+P">Print...</item>
  16. </menu>
  17. <program>
  18. <![CDATA[
  19. this.windowTitle = TTR("useandcostreport", "Typica - Average Use and Cost by Origin");
  20. var report = findChildObject(this, 'report');
  21. var printMenu = findChildObject(this, 'print');
  22. printMenu.triggered.connect(function() {
  23. report.print();
  24. });
  25. var sortBox = findChildObject(this, 'sort');
  26. sortBox.addItem(TTR("useandcostreport","Origin A-Z"));
  27. sortBox.addItem(TTR("useandcostreport", "Origin Z-A"));
  28. sortBox.addItem(TTR("useandcostreport", "Avg. Rate Ascending"));
  29. sortBox.addItem(TTR("useandcostreport", "Avg. Rate Descending"));
  30. sortBox.addItem(TTR("useandcostreport", "Avg. Cost Ascending"));
  31. sortBox.addItem(TTR("useandcostreport", "Avg. Cost Descending"));
  32. sortBox.currentIndex = QSettings.value("auco_sort", 0);
  33. var unitBox = findChildObject(this, 'unit');
  34. unitBox.addItem(TTR("useandcostreport", "Kg"));
  35. unitBox.addItem(TTR("useandcostreport", "Lb"));
  36. unitBox.currentIndex = QSettings.value("script/report_unit", 1);
  37. unitBox['currentIndexChanged(int)'].connect(function() {
  38. QSettings.setValue("script/report_unit", unitBox.currentIndex);
  39. refresh();
  40. });
  41. var dateSelect = findChildObject(this, 'dates');
  42. var dateQuery = new QSqlQuery;
  43. dateQuery.exec("SELECT time::date FROM transactions WHERE time = (SELECT min(time) FROM transactions) OR time = (SELECT max(time) FROM transactions) ORDER BY time ASC");
  44. dateQuery.next();
  45. var lifetimeStartDate = dateQuery.value(0);
  46. var lifetimeEndDate;
  47. if(dateQuery.next()) {
  48. lifetimeEndDate = dateQuery.value(0);
  49. } else {
  50. lifetimeEndDate = lifetimeStartDate;
  51. }
  52. dateSelect.setLifetimeRange(lifetimeStartDate, lifetimeEndDate);
  53. dateQuery = dateQuery.invalidate();
  54. dateSelect.rangeUpdated.connect(refresh);
  55. var rowData = new Array();
  56. var rowIndex;
  57. function refresh() {
  58. rowData.length = 0;
  59. var dateRange = dateSelect.currentRange();
  60. var startDate = dateRange[0];
  61. var endDate = dateRange[dateRange.length - 1];
  62. rowIndex = 0;
  63. var buffer = new QBuffer;
  64. buffer.open(3);
  65. var output = new XmlWriter(buffer);
  66. output.writeStartDocument("1.0");
  67. output.writeDTD('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg.dtd">');
  68. output.writeStartElement("html");
  69. output.writeAttribute("xmlns", "http://www.w3.org/1999/xhtml");
  70. output.writeStartElement("head");
  71. output.writeTextElement("title", TTR("useandcostreport", "Recent Use and Cost by Origin"));
  72. output.writeEndElement();
  73. output.writeStartElement("body");
  74. output.writeTextElement("h1", TTR("useandcostreport", "Average Use and Cost by Origin ") + startDate + " - " + endDate);
  75. switch(unitBox.currentIndex)
  76. {
  77. case 0:
  78. output.writeTextElement("p", TTR("useandcostreport", "This is a report of average rate of use in kilograms per day and cost of unroasted coffee."));
  79. break;
  80. case 1:
  81. output.writeTextElement("p", TTR("useandcostreport", "This is a report of average rate of use in pounds per day and cost of unroasted coffee."));
  82. break;
  83. }
  84. output.writeStartElement("table");
  85. output.writeAttribute("rules", "groups");
  86. output.writeAttribute("cellpadding", "3px");
  87. output.writeStartElement("thead");
  88. output.writeStartElement("tr");
  89. output.writeStartElement("th");
  90. output.writeAttribute("colspan", "9");
  91. output.writeCharacters(TTR("useandcostreport", "Regular Coffees"));
  92. output.writeEndElement();
  93. output.writeEndElement();
  94. output.writeStartElement("tr");
  95. output.writeTextElement("th", TTR("useandcostreport", "Origin"));
  96. output.writeTextElement("th", TTR("useandcostreport", "Avg. Rate"));
  97. output.writeTextElement("th", TTR("useandcostreport", "Avg. Cost"));
  98. output.writeTextElement("th", TTR("useandcostreport", "Last Cost"));
  99. output.writeTextElement("th", TTR("useandcostreport", "Last Purchase Date"));
  100. output.writeTextElement("th", TTR("useandcostreport", "Bag Size (min)"));
  101. output.writeTextElement("th", TTR("useandcostreport", "Bag Size (max)"));
  102. output.writeTextElement("th", TTR("useandcostreport", "Bag Size (mean)"));
  103. output.writeTextElement("th", TTR("useandcostreport", "Purchases"));
  104. output.writeEndElement();
  105. output.writeEndElement();
  106. output.writeStartElement("tbody");
  107. var query = new QSqlQuery();
  108. var conversion = 1;
  109. if(unitBox.currentIndex == 0) {
  110. conversion = 2.2;
  111. }
  112. var orderClause;
  113. switch(sortBox.currentIndex)
  114. {
  115. case 0:
  116. orderClause = "origin ASC";
  117. break;
  118. case 1:
  119. orderClause = "origin DESC";
  120. break;
  121. case 2:
  122. orderClause = "rate ASC";
  123. break;
  124. case 3:
  125. orderClause = "rate DESC";
  126. break;
  127. case 4:
  128. orderClause = "cost ASC";
  129. break;
  130. case 5:
  131. orderClause = "cost DESC";
  132. break;
  133. }
  134. query.prepare("WITH q AS (SELECT id, origin, rate/:c1 AS rate, (SELECT cost*:c2 FROM purchase WHERE item = id) AS cost, (SELECT min(time) FROM purchase WHERE item = id) AS purchase_time, (SELECT conversion/:c3 FROM lb_bag_conversion WHERE item = id) AS bag_weight FROM coffee_history WHERE id IN (SELECT id FROM regular_coffees) AND id IN (SELECT item FROM transactions WHERE time >= :startDate AND time < :endDate::date + interval '1 day')) SELECT DISTINCT origin, avg(rate)::numeric(10,2) AS rate, avg(cost)::numeric(10,2) AS cost, (SELECT (cost*:c4)::numeric(10,2) FROM purchase WHERE item = max(q.id)) AS last_cost, max(purchase_time)::date AS last_purchase, min(bag_weight)::numeric(10,2) AS min_weight, max(bag_weight)::numeric(10,2) AS max_weight, avg(bag_weight)::numeric(10,2) AS mean_weight, count(1) AS n FROM q GROUP BY origin ORDER BY " + orderClause);
  135. query.bind(":c1", conversion);
  136. query.bind(":c2", conversion);
  137. query.bind(":c3", conversion);
  138. query.bind(":c4", conversion);
  139. query.bind(":startDate", startDate);
  140. query.bind(":endDate", endDate);
  141. query.exec();
  142. while(query.next())
  143. {
  144. output.writeStartElement("tr");
  145. output.writeAttribute("id", "r" + rowIndex);
  146. output.writeStartElement("td");
  147. output.writeStartElement("a");
  148. output.writeAttribute("href", "typica://script/r" + rowIndex);
  149. rowIndex++;
  150. rowData.push(query.value(0));
  151. output.writeCharacters(query.value(0));
  152. output.writeEndElement();
  153. output.writeEndElement();
  154. output.writeTextElement("td", query.value(1));
  155. output.writeTextElement("td", query.value(2));
  156. output.writeTextElement("td", query.value(3));
  157. output.writeTextElement("td", query.value(4));
  158. output.writeTextElement("td", query.value(5));
  159. output.writeTextElement("td", query.value(6));
  160. output.writeTextElement("td", query.value(7));
  161. output.writeTextElement("td", query.value(8));
  162. output.writeEndElement();
  163. }
  164. output.writeStartElement("tr");
  165. output.writeStartElement("th");
  166. output.writeAttribute("colspan", "9");
  167. output.writeCharacters(TTR("useandcostreport", "Decaffeinated Coffees"));
  168. output.writeEndElement();
  169. output.writeEndElement();
  170. query.prepare("WITH q AS (SELECT id, origin, rate/:c1 AS rate, (SELECT cost*:c2 FROM purchase WHERE item = id) AS cost, (SELECT min(time) FROM purchase WHERE item = id) AS purchase_time, (SELECT conversion/:c3 FROM lb_bag_conversion WHERE item = id) AS bag_weight FROM coffee_history WHERE id IN (SELECT id FROM decaf_coffees) AND id IN (SELECT item FROM transactions WHERE time >= :startDate AND time < :endDate::date + interval '1 day')) SELECT DISTINCT origin, avg(rate)::numeric(10,2) AS rate, avg(cost)::numeric(10,2) AS cost, (SELECT (cost*:c4)::numeric(10,2) FROM purchase WHERE item = max(q.id)) AS last_cost, max(purchase_time)::date AS last_purchase, min(bag_weight)::numeric(10,2) AS min_weight, max(bag_weight)::numeric(10,2) AS max_weight, avg(bag_weight)::numeric(10,2) AS mean_weight, count(1) AS n FROM q GROUP BY origin ORDER BY " + orderClause);
  171. query.bind(":c1", conversion);
  172. query.bind(":c2", conversion);
  173. query.bind(":c3", conversion);
  174. query.bind(":c4", conversion);
  175. query.bind(":startDate", startDate);
  176. query.bind(":endDate", endDate);
  177. query.exec();
  178. while(query.next())
  179. {
  180. output.writeStartElement("tr");
  181. output.writeAttribute("id", "d" + rowIndex);
  182. output.writeStartElement("td");
  183. output.writeStartElement("a");
  184. output.writeAttribute("href", "typica://script/d" + rowIndex);
  185. rowIndex++;
  186. rowData.push(query.value(0));
  187. output.writeCharacters(query.value(0));
  188. output.writeEndElement();
  189. output.writeEndElement();
  190. output.writeTextElement("td", query.value(1));
  191. output.writeTextElement("td", query.value(2));
  192. output.writeTextElement("td", query.value(3));
  193. output.writeTextElement("td", query.value(4));
  194. output.writeTextElement("td", query.value(5));
  195. output.writeTextElement("td", query.value(6));
  196. output.writeTextElement("td", query.value(7));
  197. output.writeTextElement("td", query.value(8));
  198. output.writeEndElement();
  199. }
  200. query = query.invalidate();
  201. output.writeEndElement();
  202. output.writeEndElement();
  203. output.writeEndElement();
  204. output.writeEndElement();
  205. output.writeEndDocument();
  206. report.setContent(buffer);
  207. buffer.close();
  208. }
  209. refresh();
  210. sortBox['currentIndexChanged(int)'].connect(function() {
  211. QSettings.setValue("auco_sort", sortBox.currentIndex);
  212. refresh();
  213. });
  214. report.scriptLinkClicked.connect(function(url) {
  215. if(url[0] == 'i') {
  216. url = url.slice(1, url.length);
  217. var itemReport = createReport("itemtransactions.xml");
  218. var sIB = findChildObject(itemReport, 'item');
  219. sIB.currentIndex = sIB.findData(url);
  220. return;
  221. }
  222. var element = new WebElement(report.findFirstElement("#" + url));
  223. var regular = url[0] == 'r';
  224. var index = url.slice(1, url.length);
  225. var tableref;
  226. if(regular) {
  227. tableref = "regular_coffees";
  228. } else {
  229. tableref = "decaf_coffees";
  230. }
  231. var origin = rowData[Number(url.slice(1, url.length))];
  232. var details = '<tr><td /><td colspan="6"><table><tr><th>' +
  233. TTR("useandcostreport", "Id") + '</th><th>' +
  234. TTR("useandcostreport", "Name") + '</th><th>' +
  235. TTR("useandcostreport", "Rate") + '</th><th>' +
  236. TTR("useandcostreport", "Cost") + '</th><th>' +
  237. TTR("useandcostreport", "Inventory") + '</th><th>' +
  238. TTR("useandcostreport", "First Use") + '</th><th>' +
  239. TTR("useandcostreport", "Last Use") + '</th></tr>';
  240. var query = new QSqlQuery();
  241. query.prepare("SELECT id, name, (rate/:conversion1)::numeric(12,3), (SELECT (cost*:conversion2)::numeric(12,2) FROM purchase WHERE item = id), (stock/:conversion3)::numeric(12,3), (SELECT min(time)::date FROM use WHERE item = id) AS first_use, (SELECT max(time)::date FROM use WHERE item = id) AS last_use FROM coffee_history WHERE origin = :origin AND id IN (SELECT id FROM " + tableref + ") AND id IN (SELECT item FROM transactions WHERE time >= :startDate AND time < :endDate::date + interval '1 day') ORDER BY first_use DESC");
  242. var conversion = 1;
  243. if(unitBox.currentIndex == 0) {
  244. conversion = 2.2;
  245. }
  246. var dateRange = dateSelect.currentRange();
  247. var startDate = dateRange[0];
  248. var endDate = dateRange[dateRange.length - 1];
  249. query.bind(":conversion1", conversion);
  250. query.bind(":conversion2", conversion);
  251. query.bind(":conversion3", conversion);
  252. query.bind(":origin", origin);
  253. query.bind(":startDate", startDate);
  254. query.bind(":endDate", endDate);
  255. query.exec();
  256. while(query.next()) {
  257. details += "<tr>";
  258. details += '<td><a href="typica://script/i' + query.value(0) + '">' + query.value(0) + "</a></td>";
  259. for(var i = 1; i < 7; i++) {
  260. details += "<td>" + query.value(i) + "</td>";
  261. }
  262. details += "</tr>";
  263. }
  264. query = query.invalidate();
  265. details += "</table></td></tr>";
  266. element.appendOutside(details);
  267. });
  268. ]]>
  269. </program>
  270. </window>