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.

purchase.xml 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. <window id="purchase">
  2. <layout type="vertical">
  3. <layout type="horizontal">
  4. <button name="Add Item" type="push" id="newForm" />
  5. <label>Date:</label>
  6. <calendar id="date"/>
  7. <label>Vendor:</label>
  8. <sqldrop data="0" display="0" showdata="false" editable="true" id="vendor">
  9. <query>SELECT DISTINCT vendor FROM purchase UNION SELECT '' ORDER BY vendor ASC</query>
  10. </sqldrop>
  11. <label>Invoice:</label>
  12. <line id="invoice" />
  13. </layout>
  14. <formarray id="form">
  15. <layout type="grid">
  16. <row>
  17. <column><label>Item:</label></column>
  18. <column>
  19. <sqldrop data="0" display="0" showdata="false" editable="true" id="name">
  20. <query>SELECT DISTINCT name FROM coffees UNION SELECT '' ORDER BY name ASC</query>
  21. </sqldrop>
  22. </column>
  23. <column />
  24. <column><label>Reference:</label></column>
  25. <column>
  26. <sqldrop data="0" display="0" showdata="false" editable="true" id="reference">
  27. <query>SELECT DISTINCT reference FROM coffees UNION SELECT '' ORDER BY reference ASC</query>
  28. </sqldrop>
  29. </column>
  30. </row>
  31. <row>
  32. <column><label>Quantity:</label></column>
  33. <column>
  34. <line validator="numeric" id="quantity" />
  35. </column>
  36. <column />
  37. <column><label>Unit:</label></column>
  38. <column>
  39. <sqldrop data="0" display="0" showdata="false" editable="false" id="units">
  40. <query>SELECT * FROM (VALUES('Lb'),('Kg')) AS q (unit)</query>
  41. </sqldrop>
  42. </column>
  43. </row>
  44. <row>
  45. <column><label>Cost:</label></column>
  46. <column>
  47. <line validator="numeric" id="cost" />
  48. </column>
  49. <column>
  50. <sqldrop data="0" display="0" showdata="false" editable="false" id="costModifier">
  51. <query>SELECT 'per unit' UNION SELECT 'total'</query>
  52. </sqldrop>
  53. </column>
  54. </row>
  55. <row>
  56. <column><label>Origin:</label></column>
  57. <column>
  58. <sqldrop data="0" display="0" showdata="false" editable="true" id="origin">
  59. <query>SELECT DISTINCT origin FROM coffees UNION SELECT '' ORDER BY origin ASC</query>
  60. </sqldrop>
  61. </column>
  62. <column />
  63. <column><label>Region:</label></column>
  64. <column>
  65. <sqldrop data="0" display="0" showdata="false" editable="true" id="region">
  66. <query>SELECT DISTINCT region FROM coffees UNION SELECT '' ORDER BY region ASC</query>
  67. </sqldrop>
  68. </column>
  69. </row>
  70. <row>
  71. <column><label>Producer</label></column>
  72. <column>
  73. <sqldrop data="0" display="0" showdata="false" editable="true" id="producer">
  74. <query>SELECT DISTINCT producer FROM coffees UNION SELECT '' ORDER BY producer ASC</query>
  75. </sqldrop>
  76. </column>
  77. <column />
  78. <column><label>Grade:</label></column>
  79. <column>
  80. <sqldrop data="0" display="0" showdata="false" editable="true" id="grade">
  81. <query>SELECT DISTINCT grade FROM coffees UNION SELECT '' ORDER BY grade ASC</query>
  82. </sqldrop>
  83. </column>
  84. </row>
  85. <row>
  86. <column><label>Milling:</label></column>
  87. <column>
  88. <sqldrop data="0" display="0" showdata="false" editable="true" id="milling">
  89. <query>SELECT DISTINCT milling FROM coffees UNION SELECT '' ORDER BY milling ASC</query>
  90. </sqldrop>
  91. </column>
  92. <column />
  93. <column><label>Drying:</label></column>
  94. <column>
  95. <sqldrop data="0" display="0" showdata="false" editable="true" id="drying">
  96. <query>SELECT DISTINCT drying FROM coffees UNION SELECT '' ORDER BY drying ASC</query>
  97. </sqldrop>
  98. </column>
  99. </row>
  100. <row>
  101. <column><label>Bags:</label></column>
  102. <column>
  103. <line validator="numeric" id="bags" />
  104. </column>
  105. <column>
  106. <button type="check" id="isDecaf" name="Decaffeinated" />
  107. </column>
  108. <column><label>by method:</label></column>
  109. <column>
  110. <sqldrop data="0" display="0" showdata="false" editable="true" id="decafMethod">
  111. <query>SELECT DISTINCT decaf_method FROM decaf_coffees UNION SELECT '' ORDER BY decaf_method ASC</query>
  112. </sqldrop>
  113. </column>
  114. </row>
  115. <row>
  116. <column colspan="2">
  117. <line id="certdisplay" writable="false" />
  118. </column>
  119. <column column="2">
  120. <button type="push" name="Add Certification" id="addcert" />
  121. </column>
  122. <column colspan="2">
  123. <line id="certification" />
  124. </column>
  125. </row>
  126. </layout>
  127. </formarray>
  128. <layout type="horizontal">
  129. <layout type="vertical">
  130. <label>Fees:</label>
  131. <sqltablearray columns="2" id="fees">
  132. <column name="Fee Description" />
  133. <column name="Amount" />
  134. </sqltablearray>
  135. </layout>
  136. <button name="Submit" type="push" id="submit" />
  137. </layout>
  138. </layout>
  139. <program>
  140. <![CDATA[
  141. var window = this;
  142. var convertToPounds = function(w, u) {
  143. switch(u) {
  144. case "g":
  145. return w * 0.0022;
  146. case "oz":
  147. return w * 0.0625;
  148. case "Kg":
  149. return w * 2.2;
  150. }
  151. return w;
  152. };
  153. var convertToPerPounds = function(w, u) {
  154. switch(u) {
  155. case "g":
  156. return w / 0.0022;
  157. case "oz":
  158. return w / 0.0625;
  159. case "Kg":
  160. return w / 2.2;
  161. }
  162. return w;
  163. };
  164. this.windowTitle = 'Typica - Coffee Purchase';
  165. var form = findChildObject(this, 'form');
  166. form.setMaximumElementHeight(320);
  167. var appendForm = function() {
  168. form.addElements(1);
  169. var thisCoffee = form.elementAt(form.elements() - 1);
  170. var decafButton = findChildObject(thisCoffee, 'isDecaf');
  171. var methodField = findChildObject(thisCoffee, 'decafMethod');
  172. methodField.enabled = false;
  173. decafButton.stateChanged.connect(function(state) {
  174. if(state == 0)
  175. {
  176. methodField.enabled = false;
  177. }
  178. else
  179. {
  180. methodField.enabled = true;
  181. }
  182. });
  183. var certificationButton = findChildObject(thisCoffee, 'addcert');
  184. var certSource = findChildObject(thisCoffee, 'certification');
  185. var certTarget = findChildObject(thisCoffee, 'certdisplay');
  186. certificationButton.clicked.connect(function() {
  187. if(thisCoffee.certificationArray === undefined)
  188. {
  189. thisCoffee.certificationArray = new Array();
  190. }
  191. thisCoffee.certificationArray.push(certSource.text);
  192. certTarget.text = thisCoffee.certificationArray.toString();
  193. certSource.text = '';
  194. });
  195. };
  196. appendForm();
  197. var itemButton = findChildObject(this, 'newForm');
  198. itemButton.clicked.connect(function() {
  199. appendForm();
  200. });
  201. var invoiceField = findChildObject(this, 'invoice');
  202. var vendorField = findChildObject(this, 'vendor');
  203. var feesTable = findChildObject(this, 'fees');
  204. var submitButton = findChildObject(this, 'submit');
  205. var dateField = findChildObject(this, 'date');
  206. submitButton.clicked.connect(function() {
  207. var query = new QSqlQuery;
  208. var q = "INSERT INTO invoices VALUES (default, :invoice, :vendor, :date) RETURNING id";
  209. query.prepare(q);
  210. query.bind(":invoice", invoiceField.text);
  211. query.bind(":vendor", vendorField.currentText);
  212. query.bind(":date", dateField.date);
  213. query.exec();
  214. query.next();
  215. var invoiceNumber = query.value(0);
  216. for(var i = 0; i < form.elements(); i++)
  217. {
  218. var current = form.elementAt(i);
  219. var nameEntry = findChildObject(current, 'name');
  220. var quantityEntry = findChildObject(current, 'quantity');
  221. var unitEntry = findChildObject(current, 'units');
  222. var costEntry = findChildObject(current, 'cost');
  223. var originEntry = findChildObject(current, 'origin');
  224. var decafSelection = findChildObject(current, 'isDecaf');
  225. var decafEntry = findChildObject(current, 'decafMethod');
  226. if(nameEntry.currentText == '')
  227. {
  228. continue;
  229. }
  230. if(quantityEntry.text == '')
  231. {
  232. continue;
  233. }
  234. if(costEntry.text == '')
  235. {
  236. continue;
  237. }
  238. if(originEntry.currentText == '')
  239. {
  240. continue;
  241. }
  242. if(decafSelection.checked)
  243. {
  244. if(decafEntry.currentText == '')
  245. {
  246. continue;
  247. }
  248. }
  249. if(decafSelection.checked)
  250. {
  251. q = "INSERT INTO decaf_coffees VALUES (default, :name, :reference, :unit, 0, 'Coffee: Unroasted', :origin, :region, :producer, :grade, :milling, :drying, :decafMethod) RETURNING id";
  252. }
  253. else
  254. {
  255. q = "INSERT INTO coffees VALUES (default, :name, :reference, :unit, 0, 'Coffee: Unroasted', :origin, :region, :producer, :grade, :milling, :drying) RETURNING id";
  256. }
  257. query.prepare(q);
  258. query.bind(":name", nameEntry.currentText);
  259. var referenceEntry = findChildObject(current, 'reference');
  260. if(referenceEntry.currentText == '')
  261. {
  262. query.bind(":reference", null);
  263. }
  264. else
  265. {
  266. query.bind(":reference", referenceEntry.currentText);
  267. }
  268. query.bind(":unit", 'lb');
  269. query.bind(":origin", originEntry.currentText);
  270. var regionEntry = findChildObject(current, 'region');
  271. if(regionEntry.currentText == '')
  272. {
  273. query.bind(":region", null);
  274. }
  275. else
  276. {
  277. query.bind(":region", regionEntry.currentText);
  278. }
  279. var producerEntry = findChildObject(current, 'producer');
  280. if(producerEntry.currentText == '')
  281. {
  282. query.bind(":producer", null);
  283. }
  284. else
  285. {
  286. query.bind(":producer", producerEntry.currentText);
  287. }
  288. var gradeEntry = findChildObject(current, 'grade');
  289. if(gradeEntry.currentText == '')
  290. {
  291. query.bind(":grade", null);
  292. }
  293. else
  294. {
  295. query.bind(":grade", gradeEntry.currentText);
  296. }
  297. var millingEntry = findChildObject(current, 'milling');
  298. if(millingEntry.currentText == '')
  299. {
  300. query.bind(":milling", null);
  301. }
  302. else
  303. {
  304. query.bind(":milling", millingEntry.currentText);
  305. }
  306. var dryingEntry = findChildObject(current, 'drying');
  307. if(dryingEntry.currentText == '')
  308. {
  309. query.bind(":drying", null);
  310. }
  311. else
  312. {
  313. query.bind(":drying", dryingEntry.currentText);
  314. }
  315. if(decafSelection.checked)
  316. {
  317. query.bind(":decafMethod", decafEntry.currentText);
  318. }
  319. query.exec();
  320. query.next();
  321. var item_id = query.value(0);
  322. q = "INSERT INTO purchase VALUES(:time, :item, :quantity, :cost, :vendor)";
  323. query.prepare(q);
  324. query.bind(":time", dateField.date);
  325. query.bind(":item", item_id);
  326. query.bind(":quantity", convertToPounds(parseFloat(quantityEntry.text), unitEntry.currentText));
  327. var costModifier = findChildObject(current, 'costModifier');
  328. if(costModifier.currentText == 'per unit')
  329. {
  330. query.bind(":cost", convertToPerPounds(parseFloat(costEntry.text), unitEntry.currentText));
  331. }
  332. else
  333. {
  334. query.bind(":cost", Number(costEntry.text) / convertToPounds(parseFloat(quantityEntry.text), unitEntry.currentText));
  335. }
  336. query.bind(":vendor", vendorField.currentText);
  337. query.exec();
  338. q = "INSERT INTO lb_bag_conversion VALUES(:item, :conversion)";
  339. query.prepare(q);
  340. query.bind(":item", item_id);
  341. var bagsEntry = findChildObject(current, 'bags');
  342. var conversion = convertToPounds(parseFloat(quantityEntry.text), unitEntry.currentText) / Number(bagsEntry.text);
  343. query.bind(":conversion", conversion);
  344. query.exec();
  345. q = "INSERT INTO invoice_items VALUES(:id, 'PURCHASE', :item, :description, :cost)";
  346. query.prepare(q);
  347. query.bind(":id", invoiceNumber);
  348. query.bind(":item", item_id);
  349. query.bind(":description", nameEntry.currentText);
  350. if(costModifier.currentText == 'per unit')
  351. {
  352. query.bind(":cost", Number(costEntry.text) * Number(quantityEntry.text));
  353. }
  354. else
  355. {
  356. query.bind(":cost", Number(costEntry.text));
  357. }
  358. query.exec();
  359. var certifications = findChildObject(current, 'certdisplay');
  360. var certlist = certifications.text.split(",");
  361. q = "INSERT INTO certifications VALUES (:item, :certification)";
  362. query.prepare(q);
  363. query.bind(":item", item_id);
  364. for(var j = 0; j < certlist.length; j++)
  365. {
  366. query.bind(":certification", certlist[j]);
  367. query.exec();
  368. }
  369. }
  370. var descriptionArray = sqlToArray(feesTable.columnArray(0, 0));
  371. var q = "INSERT INTO invoice_items VALUES (:id, 'FEE', NULL, :description, :cost)";
  372. query.prepare(q);
  373. query.bind(":id", invoiceNumber);
  374. if(descriptionArray.length > 0)
  375. {
  376. for(var i = 0; i < descriptionArray.length; i++)
  377. {
  378. if(feesTable.data(i, 0, 0).value == '')
  379. {
  380. continue;
  381. }
  382. if(feesTable.data(i, 1, 0).value == '')
  383. {
  384. continue;
  385. }
  386. query.bind(":description", feesTable.data(i, 0, 0).value);
  387. query.bind(":cost", Number(feesTable.data(i, 1, 0).value));
  388. query.exec();
  389. }
  390. }
  391. window.close();
  392. });
  393. this.showMaximized();
  394. ]]>
  395. </program>
  396. </window>