Browse Source

Merge branch 'development' into configtr

Neal Wilson 8 years ago
parent
commit
7ddcf98107

+ 14
- 2
config/Reports/dailyproductiondetail.xml View File

@@ -216,7 +216,13 @@
216 216
 						output.writeEmptyElement("td");
217 217
 						output.writeStartElement("td");
218 218
 						output.writeAttribute("colspan", "8");
219
-						output.writeTextElement("em", query.value(9));
219
+                                                var noteArray = query.value(9).split("\n");
220
+                                                for(var i = 0; i < noteArray.length; i++) {
221
+                                                    output.writeStartElement("p");
222
+                                                    output.writeAttribute("style", "margin-top: 0; margin-bottom: 0");
223
+                                                    output.writeCharacters(noteArray[i]);
224
+                                                    output.writeEndElement();
225
+                                                }
220 226
 						output.writeEndElement();
221 227
 						output.writeEndElement();
222 228
 					}
@@ -305,7 +311,13 @@
305 311
                                         output.writeAttribute("colspan", "4");
306 312
                                         if(query.value(14)) {
307 313
                                             output.writeTextElement("strong", "Roast Specification Notes");
308
-                                            output.writeTextElement("p", query.value(14));
314
+                                            var specArray = query.value(14).split("\n");
315
+                                            for(var i = 0; i < noteArray.length; i++) {
316
+                                                output.writeStartElement("p");
317
+                                                output.writeAttribute("style", "margin-top: 0; margin-bottom: 0");
318
+                                                output.writeCharacters(specArray[i]);
319
+                                                output.writeEndElement();
320
+                                            }                                            
309 321
                                         }
310 322
                                         output.writeEndElement();
311 323
 					output.writeEndElement();

+ 1
- 1
config/Reports/fypurchase.xml View File

@@ -117,7 +117,7 @@
117 117
 				output.writeEndElement(); //tbody
118 118
 				output.writeStartElement("tfoot");
119 119
 				output.writeTextElement("th", "Totals:");
120
-				output.writeTextElement("td", sacktotal);
120
+				output.writeTextElement("td", sacktotal.toFixed(2));
121 121
 				output.writeTextElement("td", unittotal.toFixed(2));
122 122
 				output.writeTextElement("td", costtotal.toFixed(2));
123 123
 				output.writeEndElement(); //tfoot

+ 16
- 1
config/Reports/greensales.xml View File

@@ -46,7 +46,6 @@
46 46
 				var buffer = new QBuffer;
47 47
 				buffer.open(3);
48 48
 				var output = new XmlWriter(buffer);
49
-				var output = new XmlWriter(buffer);
50 49
 				output.writeStartDocument("1.0");
51 50
 				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">');
52 51
 				output.writeStartElement("html");
@@ -96,6 +95,22 @@
96 95
 					output.writeEndElement();
97 96
 				}
98 97
 				output.writeEndElement();
98
+                                output.writeStartElement("tfoot");
99
+                                query.prepare("SELECT (sum(quantity)/:conversion)::numeric(12,3) FROM sale WHERE time < :ed ::date + interval '1 day' AND time >= :sd");
100
+                                query.bind(":conversion", conversion);
101
+                                query.bind(":ed", endDate);
102
+                                query.bind(":sd", startDate);
103
+                                query.exec();
104
+                                if(query.next()) {
105
+                                    output.writeStartElement("tr");
106
+                                    output.writeEmptyElement("td");
107
+                                    output.writeEmptyElement("td");
108
+                                    output.writeEmptyElement("td");
109
+                                    output.writeTextElement("th", "Total:");
110
+                                    output.writeTextElement("td", query.value(0));
111
+                                    output.writeEndElement();
112
+                                }
113
+                                output.writeEndElement();
99 114
 				output.writeEndElement();
100 115
 				output.writeEndElement();
101 116
 				output.writeEndElement();

+ 2
- 1
config/Reports/historyreport.xml View File

@@ -91,7 +91,7 @@
91 91
                     conversion = 2.2;
92 92
                 }
93 93
                 var query = new QSqlQuery();
94
-                var q = "SELECT to_char(time, 'Dy Mon DD YYYY HH24:MI:SS'), machine, (SELECT name FROM items WHERE id = roasted_id) AS name, unroasted_total_quantity / " + conversion + " AS green, roasted_quantity  / " + conversion + " AS roasted, CASE WHEN unroasted_total_quantity = 0 THEN NULL ELSE ((unroasted_total_quantity - roasted_quantity) / unroasted_total_quantity * 100::numeric)::numeric(12,2) END AS weight_loss, duration, annotation FROM roasting_log WHERE machine = :machine AND time = :time";
94
+                var q = "SELECT time, machine, (SELECT name FROM items WHERE id = roasted_id) AS name, unroasted_total_quantity / " + conversion + " AS green, roasted_quantity  / " + conversion + " AS roasted, CASE WHEN unroasted_total_quantity = 0 THEN NULL ELSE ((unroasted_total_quantity - roasted_quantity) / unroasted_total_quantity * 100::numeric)::numeric(12,2) END AS weight_loss, duration, annotation FROM roasting_log WHERE machine = :machine AND time = :time";
95 95
                 query.prepare(q);
96 96
                 query.bind(":machine", key[0]);
97 97
                 query.bind(":time", key[1]);
@@ -101,6 +101,7 @@
101 101
                     print("Constructing row with " + query.value(i));
102 102
                     fakeTable.holding[i] = query.value(i);
103 103
                 }
104
+                fakeTable.holding[0] = key[1];
104 105
                 query = query.invalidate();
105 106
                 details.loadData(fakeTable, 0);
106 107
             });

+ 95
- 50
config/Reports/rwacp.xml View File

@@ -1,11 +1,17 @@
1 1
 <window id="productionreport">
2
-	<reporttitle>Production:->Recent Average Weekly Coffee Production</reporttitle>
2
+	<reporttitle>Production:->Recent Average Coffee Production</reporttitle>
3 3
     <layout type="vertical">
4 4
         <layout type="horizontal">
5 5
             <label>Sort Order:</label>
6 6
             <sqldrop id="sort" />
7
-			<label>Weight Unit:</label>
8
-			<sqldrop id="unit" />
7
+            <label>Weight Unit:</label>
8
+            <sqldrop id="unit" />
9
+            <label>Batch Type: </label>
10
+            <sqldrop id="batchtype" />
11
+            <label>Days to Average: </label>
12
+            <line id="days" />
13
+            <label>Days to Scale: </label>
14
+            <line id="scale" />
9 15
             <stretch />
10 16
         </layout>
11 17
         <webview id="report" />
@@ -15,7 +21,7 @@
15 21
     </menu>
16 22
     <program>
17 23
         <![CDATA[
18
-            this.windowTitle = "Typica - Recent Average Weekly Coffee Production";
24
+            this.windowTitle = "Typica - Recent Average Coffee Production";
19 25
             var report = findChildObject(this, 'report');
20 26
             var printMenu = findChildObject(this, 'print');
21 27
             printMenu.triggered.connect(function() {
@@ -27,10 +33,38 @@
27 33
             sortBox.addItem("Weekly Use Ascending");
28 34
             sortBox.addItem("Weekly Use Descending");
29 35
             sortBox.currentIndex = QSettings.value("rwacp_sort", 3);
30
-			var unitBox = findChildObject(this, 'unit');
31
-			unitBox.addItem("Kg");
32
-			unitBox.addItem("Lb");
33
-			unitBox.currentIndex = QSettings.value("script/report_unit", 1);
36
+            var unitBox = findChildObject(this, 'unit');
37
+            unitBox.addItem("Kg");
38
+            unitBox.addItem("Lb");
39
+            unitBox.currentIndex = QSettings.value("script/report_unit", 1);
40
+            var batchType = findChildObject(this, 'batchtype');
41
+            batchType.addItem("Any");
42
+            batchType.addItem("Production Roasts");
43
+            batchType.addItem("Sample Roasts");
44
+            batchType.currentIndex = QSettings.value("script/racpreport/batchtypefilter", 1);
45
+            batchType['currentIndexChanged(int)'].connect(function() {
46
+                QSettings.setValue("script/racpreport/batchtypefilter",
47
+                                   batchType.currentIndex);
48
+                refresh();
49
+            });
50
+            var daysBox = findChildObject(this, 'days');
51
+            daysBox.text = QSettings.value("script/racpreport/days", "28");
52
+            daysBox.editingFinished.connect(function() {
53
+                if(Number(daysBox.text) < 1) {
54
+                    daysBox.text = QSettings.value("script/racpreport/days");
55
+                }
56
+                QSettings.setValue("script/racpreport/days", daysBox.text);
57
+                refresh();
58
+            });
59
+            var scaleBox = findChildObject(this, 'scale');
60
+            scaleBox.text = QSettings.value("script/racpreport/scale", "7");
61
+            scaleBox.editingFinished.connect(function() {
62
+                if(Number(scaleBox.text) < 1) {
63
+                    scaleBox.text = QSettings.value("script/racpreport/scale");
64
+                }
65
+                QSettings.setValue("script/racpreport/scale", scaleBox.text);
66
+                refresh();
67
+            });
34 68
             function refresh() {
35 69
                 var buffer = new QBuffer;
36 70
                 buffer.open(3);
@@ -40,19 +74,19 @@
40 74
                 output.writeStartElement("html");
41 75
                 output.writeAttribute("xmlns", "http://www.w3.org/1999/xhtml");
42 76
                 output.writeStartElement("head");
43
-                output.writeTextElement("title", "Recent Average Weekly Coffee Production");
77
+                output.writeTextElement("title", "Recent Average Coffee Production");
44 78
                 output.writeEndElement();
45 79
                 output.writeStartElement("body");
46
-                output.writeTextElement("h1", "Recent Average Weekly Coffee Production");
47
-				switch(unitBox.currentIndex)
48
-				{
49
-					case 0:
50
-						output.writeTextElement("p", "This is a report of average weekly coffee production in kilograms over the past 28 days.");
51
-						break;
52
-					case 1:
53
-						output.writeTextElement("p", "This is a report of average weekly coffee production in pounds over the past 28 days.");
54
-						break;
55
-				}
80
+                output.writeTextElement("h1", "Recent Average Coffee Production");
81
+                switch(unitBox.currentIndex)
82
+                {
83
+                    case 0:
84
+                        output.writeTextElement("p", "This is a report of average coffee production per " + scaleBox.text + " days in kilograms over the past " + daysBox.text + " days.");
85
+                        break;
86
+                    case 1:
87
+                        output.writeTextElement("p", "This is a report of average coffee production per " + scaleBox.text + " days in pounds over the past " + daysBox.text + " days.");
88
+                        break;
89
+                }
56 90
                 output.writeStartElement("table");
57 91
                 output.writeAttribute("rules", "groups");
58 92
                 output.writeAttribute("cellpadding", "3px");
@@ -63,33 +97,43 @@
63 97
                 output.writeEndElement();
64 98
                 output.writeEndElement();
65 99
                 output.writeStartElement("tbody");
66
-				var q = "SELECT (SELECT name FROM items WHERE id = roasted_id) AS name, ((sum(roasted_quantity) / 4) / :conversion)::numeric(18,2) AS weekly FROM roasting_log WHERE time > current_date - integer '28' AND roasted_quantity > 0 GROUP BY roasted_id ORDER BY "
100
+                var batchClause = "";
101
+                switch(batchType.currentIndex) {
102
+                    case 1:
103
+                        batchClause = " AND transaction_type = 'ROAST'";
104
+                        break;
105
+                    case 2:
106
+                        batchClause = " AND transaction_type = 'SAMPLEROAST'";
107
+                        break;
108
+                }
109
+                var q = "SELECT (SELECT name FROM items WHERE id = roasted_id) AS name, ((sum(roasted_quantity) / :scale) / :conversion)::numeric(18,2) AS weekly FROM roasting_log WHERE time > current_date - integer '" + daysBox.text + "' AND roasted_quantity > 0 " + batchClause + " GROUP BY roasted_id ORDER BY "
67 110
                 switch(sortBox.currentIndex)
68 111
                 {
69 112
                     case 0:
70
-						q += "name ASC";
113
+                        q += "name ASC";
71 114
                         break;
72 115
                     case 1:
73
-						q += "name DESC";
74
-						break;
116
+                        q += "name DESC";
117
+                        break;
75 118
                     case 2:
76
-						q += "weekly ASC";
77
-						break;
119
+                        q += "weekly ASC";
120
+                        break;
78 121
                     case 3:
79
-						q += "weekly DESC";
80
-						break;
122
+                        q += "weekly DESC";
123
+                        break;
81 124
                 }
82
-				var query = new QSqlQuery();
83
-				query.prepare(q);
84
-				switch(unitBox.currentIndex)
85
-				{
86
-					case 0:
87
-						query.bind(":conversion", 2.2);
88
-						break;
89
-					case 1:
90
-						query.bind(":conversion", 1);
91
-						break;
92
-				}
125
+                var query = new QSqlQuery();
126
+                query.prepare(q);
127
+                switch(unitBox.currentIndex)
128
+                {
129
+                    case 0:
130
+                        query.bind(":conversion", 2.2);
131
+                        break;
132
+                    case 1:
133
+                        query.bind(":conversion", 1);
134
+                        break;
135
+                }
136
+                query.bind(":scale", Number(daysBox.text)/Number(scaleBox.text));
93 137
                 query.exec();
94 138
                 while(query.next())
95 139
                 {
@@ -101,21 +145,22 @@
101 145
                 output.writeEndElement();
102 146
                 output.writeStartElement("tfoot")
103 147
                 output.writeTextElement("th", "Total");
104
-                query.prepare("SELECT (sum(roasted_quantity) / 4 / :conversion)::numeric(18,2) FROM roasting_log WHERE time > current_date - integer '28' AND roasted_quantity > 0");
148
+                query.prepare("SELECT ((sum(roasted_quantity) / :scale) / :conversion)::numeric(18,2) FROM roasting_log WHERE time > current_date - integer '" + daysBox.text + "' AND roasted_quantity > 0 " + batchClause);
105 149
                 switch(unitBox.currentIndex)
106
-				{
107
-					case 0:
108
-						query.bind(":conversion", 2.2);
109
-						break;
110
-					case 1:
111
-						query.bind(":conversion", 1);
112
-						break;
113
-				}
114
-				query.exec();
115
-				query.next();
150
+                {
151
+                    case 0:
152
+                        query.bind(":conversion", 2.2);
153
+                        break;
154
+                    case 1:
155
+                        query.bind(":conversion", 1);
156
+                        break;
157
+                }
158
+                query.bind(":scale", Number(daysBox.text)/Number(scaleBox.text));
159
+                query.exec();
160
+                query.next();
116 161
                 output.writeTextElement("td", query.value(0));
117 162
                 query = query.invalidate();
118
-				output.writeEndElement();
163
+                output.writeEndElement();
119 164
                 output.writeEndElement();
120 165
                 output.writeEndElement();
121 166
                 output.writeEndElement();

+ 8
- 1
config/Windows/batchdetailsnew.xml View File

@@ -10,6 +10,7 @@
10 10
     </layout>
11 11
 	<menu name="File">
12 12
             <item id="save" shortcut="Ctrl+S">Save…</item>
13
+            <item id="print" shortcut="Ctrl+P">Print…</item>
13 14
 	</menu>
14 15
     <program>
15 16
         <![CDATA[
@@ -22,6 +23,10 @@
22 23
             }
23 24
             var unitText = (unit == 0 ? "Kg" : "Lb");
24 25
             dataView = findChildObject(this, 'view');
26
+            var printMenu = findChildObject(this, 'print');
27
+            printMenu.triggered.connect(function() {
28
+                dataView.print();
29
+            });
25 30
             var fileID;
26 31
             var target = findChildObject(this, 'target');
27 32
             var compare = findChildObject(this, 'compare');
@@ -37,9 +42,10 @@
37 42
             var machine;
38 43
             var approval;
39 44
             var annotation;
45
+            var roastWeight;
40 46
             edit.clicked.connect(function() {
41 47
                 var editWindow = createWindow("editBatchDetails");
42
-                editWindow.loadData(window, tableReference, rowReference, batchTime, machine, approval, annotation);
48
+                editWindow.loadData(window, tableReference, rowReference, batchTime, machine, approval, annotation, roastWeight, unit);
43 49
             });
44 50
             compare.clicked.connect(function() {
45 51
                 var query = new QSqlQuery;
@@ -250,6 +256,7 @@
250 256
                 output.writeStartElement("td");
251 257
                 output.writeAttribute("align", "center");
252 258
                 output.writeCharacters(query.value(6));
259
+                roastWeight = query.value(6);
253 260
                 output.writeEndElement();
254 261
                 output.writeEndElement();
255 262
                 output.writeStartElement("tr");

+ 56
- 40
config/Windows/editbatchdetails.xml View File

@@ -1,47 +1,63 @@
1 1
 <window id="editBatchDetails">
2 2
     <layout type="vertical">
3
-		<button type="check" name="Approved" id="approval" />
4
-		<layout type="horizontal">
5
-			<label>Annotation</label>
6
-			<textarea id="annotation" />
7
-		</layout>
8
-		<button type="push" id="submit" name="Submit" />
9
-	</layout>
3
+        <layout type="horizontal">
4
+            <label>Roasted Weight: </label>
5
+            <line id="roasted" validator="numeric" />
6
+            <line id="roastunit" writable="false" />
7
+        </layout>
8
+        <button type="check" name="Approved" id="approval" />
9
+        <layout type="horizontal">
10
+            <label>Annotation</label>
11
+            <textarea id="annotation" />
12
+        </layout>
13
+        <button type="push" id="submit" name="Submit" />
14
+    </layout>
10 15
     <program>
11 16
         <![CDATA[
12
-			var window = this;
13
-			var approvalButton = findChildObject(this, 'approval');
14
-			var annotationField = findChildObject(this, 'annotation');
15
-			var parentWindow;
16
-			var tableReference;
17
-			var rowReference;
18
-			var timeKey;
19
-			var machineKey;
20
-			var submit = findChildObject(this, 'submit');
21
-			submit.enabled = false;
22
-			this.loadData = function(parent, table, row, time, machine, approval, annotation) {
23
-				parentWindow = parent;
24
-				tableReference = table;
25
-				rowReference = row;
26
-				if(approval == "true") {
27
-					approvalButton.checked = true;
28
-				}
29
-				annotationField.plainText = annotation;
30
-				timeKey = time;
31
-				machineKey = machine;
32
-				submit.enabled = true;
33
-			};
34
-			submit.clicked.connect(function() {
35
-				var query = new QSqlQuery;
36
-				query.prepare("UPDATE roasting_log SET approval = :approval, annotation = :annotation WHERE time = :time AND machine = :machine");
37
-				query.bind("approval", approvalButton.checked);
38
-				query.bind("annotation", annotationField.plainText);
39
-				query.bind("time", timeKey);
40
-				query.bind("machine", machineKey);
41
-				query.exec();
42
-				parentWindow.loadData(tableReference, rowReference);
43
-				window.close();
44
-			});
17
+            var window = this;
18
+            var approvalButton = findChildObject(this, 'approval');
19
+            var annotationField = findChildObject(this, 'annotation');
20
+            var parentWindow;
21
+            var tableReference;
22
+            var rowReference;
23
+            var timeKey;
24
+            var machineKey;
25
+            var submit = findChildObject(this, 'submit');
26
+            submit.enabled = false;
27
+            var roastedEdit = findChildObject(this, 'roasted');
28
+            var unitEdit = findChildObject(this, 'roastunit');
29
+            var conversion = 1;
30
+            this.loadData = function(parent, table, row, time, machine, approval, annotation, roastWeight, unit) {
31
+                parentWindow = parent;
32
+                tableReference = table;
33
+                rowReference = row;
34
+                if(approval == "true") {
35
+                    approvalButton.checked = true;
36
+                }
37
+                annotationField.plainText = annotation;
38
+                timeKey = time;
39
+                machineKey = machine;
40
+                submit.enabled = true;
41
+                roastedEdit.text = roastWeight;
42
+                if(unit == 0) {
43
+                    unitEdit.text = "Kg";
44
+                    conversion = 2.2;
45
+                } else {
46
+                    unitEdit.text = "Lb";
47
+                }
48
+            };
49
+            submit.clicked.connect(function() {
50
+                var query = new QSqlQuery;
51
+                query.prepare("UPDATE roasting_log SET roasted_quantity = :roasted, approval = :approval, annotation = :annotation WHERE time = :time AND machine = :machine");
52
+                query.bind(":approval", approvalButton.checked);
53
+                query.bind(":annotation", annotationField.plainText);
54
+                query.bind(":roasted", Number(roastedEdit.text)/conversion);
55
+                query.bind(":time", timeKey);
56
+                query.bind(":machine", Number(machineKey));
57
+                query.exec();
58
+                parentWindow.loadData(tableReference, rowReference);
59
+                window.close();
60
+            });
45 61
         ]]>
46 62
     </program>
47 63
 </window>

+ 4
- 0
config/Windows/editreminder.xml View File

@@ -72,6 +72,10 @@
72 72
             var batchesfield = findChildObject(this, 'batches');
73 73
             var hoursfield = findChildObject(this, 'roastingtime');
74 74
             var time = new QTime();
75
+            var nowButton = findChildObject(this, 'now');
76
+            nowButton.clicked.connect(function() {
77
+                sincefield.setToCurrentTime();
78
+            });
75 79
             var deleteButton = findChildObject(this, 'delete');
76 80
             deleteButton.enabled = false;
77 81
             deleteButton.clicked.connect(function() {

+ 6
- 17
config/Windows/navigation.xml View File

@@ -33,11 +33,6 @@
33 33
 				<button name="Update Inventory" id="inventory" type="push" />
34 34
 			</column>
35 35
 		</row>
36
-		<row>
37
-			<column>
38
-				<button name="Batch Log" id="history" type="push" />
39
-			</column>
40
-		</row>
41 36
 		<row>
42 37
 			<column>
43 38
 				<button name="New Cupping Session" id="createcupping"
@@ -132,11 +127,6 @@ type="push" />
132 127
             var invwin = createWindow("inventory");
133 128
             invwin.windowTitle = "Typica - Inventory";
134 129
         });
135
-        var history = findChildObject(this, 'history');
136
-        history.clicked.connect(function() {
137
-            var histwindow = createWindow("history");
138
-            histwindow.windowTitle = "Typica - Batch Log";
139
-        });
140 130
         var roastspecbutton = findChildObject(this, 'roastspec');
141 131
         roastspecbutton.clicked.connect(function() {
142 132
             var specwindow = createWindow("roastspec");
@@ -161,20 +151,19 @@ type="push" />
161 151
             {
162 152
                 window.loggingWindow = createWindow("basicWindow");
163 153
                 window.loggingWindow.windowTitle = "Typica [*]";
164
-				window.loggingWindow.navigationWindow = window;
154
+                window.loggingWindow.navigationWindow = window;
165 155
             }
166 156
             else
167 157
             {
168
-				print(window.loggingWindow);
169 158
                 window.loggingWindow.raise();
170 159
                 window.loggingWindow.activateWindow();
171 160
             }
172 161
         });
173
-		var configurebutton = findChildObject(this, 'configure');
174
-		configurebutton.clicked.connect(function() {
175
-			var confwindow = new SettingsWindow;
176
-			confwindow.show();
177
-		});
162
+        var configurebutton = findChildObject(this, 'configure');
163
+        configurebutton.clicked.connect(function() {
164
+            var confwindow = new SettingsWindow;
165
+            confwindow.show();
166
+        });
178 167
         <![CDATA[
179 168
 		var DBCreateBase = function() {
180 169
 			var query = new QSqlQuery();

+ 63
- 4
config/Windows/newbatch.xml View File

@@ -41,7 +41,7 @@
41 41
             </layout>
42 42
             <layout type="horizontal">
43 43
                 <label>Roasted Weight:</label>
44
-                <line id="roast" validator="numeric" />
44
+                <line id="roast" validator="numeric">0.0</line>
45 45
                 <label>Weight Loss:</label>
46 46
                 <line id="wloss" writable="false" />
47 47
                 <button type="check" id="approval" name="Approved" />
@@ -381,7 +381,26 @@
381 381
                 roastestimate.text = "";
382 382
                 query = query.invalidate();
383 383
             });
384
+            var validateCapacity = function() {
385
+                if(checkCapacity == "true") {
386
+                    if(convertToPounds(parseFloat(green.text), unitBox.currentText) > poundsCapacity) {
387
+                        return false;
388
+                    }
389
+                }
390
+                return true;
391
+            }
384 392
             profilebutton.clicked.connect(function() {
393
+                var proceed = false;
394
+                if(validateCapacity()) {
395
+                    proceed = true;
396
+                } else {
397
+                    proceed = displayWarning("Suspicious Input", "Entered green coffee weight exceeds maximum batch size. Continue?");
398
+                }
399
+                if(proceed) {
400
+                    doLoadProfile();
401
+                }
402
+            });
403
+            var doLoadProfile = function() {
385 404
                 batch.windowModified = true;
386 405
                 currentBatchInfo = batch;
387 406
                 query = new QSqlQuery();
@@ -450,14 +469,25 @@
450 469
                 log.updatesEnabled = true;
451 470
                 graph.updatesEnabled = true;
452 471
                 log.newAnnotation("End", 1, lc);
453
-            });
472
+            }
454 473
             var noprofilebutton = findChildObject(this, 'noprofile');
455 474
             noprofilebutton.clicked.connect(function() {
475
+                var proceed = false;
476
+                if(validateCapacity()) {
477
+                    proceed = true;
478
+                } else {
479
+                    proceed = displayWarning("Suspicious Input", "Entered green coffee weight exceeds maximum batch size. Continue?");
480
+                }
481
+                if(proceed) {
482
+                    doNoProfile();
483
+                }
484
+            });
485
+            var doNoProfile = function() {
456 486
                 batch.windowModified = true;
457 487
                 currentBatchInfo = batch;
458 488
                 navigationwindow.loggingWindow.raise();
459 489
                 navigationwindow.loggingWindow.activateWindow();
460
-            });
490
+            }
461 491
             var submitbutton = findChildObject(this, 'submit');
462 492
             var timefield = findChildObject(this, 'time');
463 493
             var notes = findChildObject(this, 'annotation');
@@ -465,7 +495,36 @@
465 495
             var approval = findChildObject(this, 'approval');
466 496
             approval.checked = true;
467 497
             var target = findChildObject(this, 'target');
498
+            var checkSubmitEnable = function () {
499
+                if(roasted.currentIndex > 0) {
500
+                    if(timefield.text.length > 0) {
501
+                        if(duration.text.length > 0) {
502
+                            if(batch.tempData.length > 0) {
503
+                                if(green.text.length > 0) {
504
+                                    return true;
505
+                                }
506
+                            }
507
+                        }
508
+                    }
509
+                }
510
+                return false;
511
+            }
468 512
             submitbutton.clicked.connect(function() {
513
+                var proceed = false;
514
+                if(validateCapacity()) {
515
+                    proceed = true;
516
+                } else {
517
+                    proceed = displayWarning("Suspicious Input", "Entered green coffee weight exceeds maximum batch size. Continue?");
518
+                }
519
+                if(proceed) {
520
+                    if(checkSubmitEnable()) {
521
+                        doSubmit();
522
+                    } else {
523
+                        displayError("Incomplete Input", "Some required information is not available. Please check inputs and try again.");
524
+                    }
525
+                }
526
+            });
527
+            var doSubmit = function() {
469 528
                 checkQuery = new QSqlQuery();
470 529
                 checkQuery.exec("SELECT 1 FROM machine WHERE id = " + selectedRoasterID);
471 530
                 if(!checkQuery.next())
@@ -525,7 +584,7 @@
525 584
                 query = query.invalidate();
526 585
                 batch.windowModified = false;
527 586
                 batch.close();
528
-            });
587
+            }
529 588
         ]]>
530 589
     </program>
531 590
 </window>

+ 34
- 4
config/Windows/newsamplebatch.xml View File

@@ -179,7 +179,26 @@
179 179
 			stop.clicked.connect(function() {
180 180
 				submit.setEnabled(true);
181 181
 			});
182
-			roastButton.clicked.connect(function() {
182
+                        var validateCapacity = function() {
183
+                            if(checkCapacity == "true") {
184
+                                if(convertToPounds(parseFloat(green.text), GunitBox.currentText) > poundsCapacity) {
185
+                                    return false;
186
+                                }
187
+                            }
188
+                            return true;
189
+                        }
190
+                        roastButton.clicked.connect(function() {
191
+                            var proceed = false;
192
+                            if(validateCapacity()) {
193
+                                proceed = true;
194
+                            } else {
195
+                                proceed = displayWarning("Suspicious Input", "Entered green coffee weight exceeds maximum batch size. Continue?");
196
+                            }
197
+                            if(proceed) {
198
+                                doRoast();
199
+                            }
200
+                        });
201
+                        var doRoast = function() {
183 202
 				var lc = 1;
184 203
 				currentBatchInfo = batch;
185 204
 				query = new QSqlQuery();
@@ -242,7 +261,7 @@
242 261
 					t = t + ", " + profileName.currentText;
243 262
 				}
244 263
 				navigationwindow.loggingWindow.windowTitle = t;
245
-			});
264
+			};
246 265
 			var notes = findChildObject(this, 'annotation');
247 266
 			var machine = findChildObject(this, 'machine');
248 267
 			var duration = findChildObject(this, 'duration');
@@ -250,7 +269,18 @@
250 269
 			var vendor = findChildObject(this, 'vendor');
251 270
 			var attributes = findChildObject(this, 'attributes');
252 271
 			var target = findChildObject(this, 'target');
253
-			submit.clicked.connect(function() {
272
+                        submit.clicked.connect(function() {
273
+                            var proceed = false;
274
+                            if(validateCapacity()) {
275
+                                proceed = true;
276
+                            } else {
277
+                                proceed = displayWarning("Suspicious Input", "Entered green coffee weight exceeds maximum batch size. Continue?");
278
+                            }
279
+                            if(proceed) {
280
+                                doLoadProfile();
281
+                            }
282
+                        });
283
+                        var doSubmit = function() {
254 284
 				query = new QSqlQuery();
255 285
 				query.prepare("INSERT INTO files (id, name, type, note, file) VALUES(DEFAULT, :name, 'profile', NULL, :data) RETURNING id");
256 286
 				query.bind(":name", timefield.text + " " + name.text + " " + profileName.currentText);
@@ -328,7 +358,7 @@
328 358
 				query.exec();
329 359
 				query = query.invalidate();
330 360
 				batch.close();
331
-			});
361
+			}
332 362
 		]]>
333 363
 	</program>
334 364
 </window>

+ 708
- 690
config/Windows/productionroaster.xml
File diff suppressed because it is too large
View File


+ 1
- 1
src/daterangeselector.w View File

@@ -81,7 +81,7 @@ class DateRangeSelector : public QWidget
81 81
 @<CustomDateRangePopup implementation@>
82 82
 @<DateRangeSelector implementation@>
83 83
 
84
-#if 0
84
+#ifdef __unix__
85 85
 #include "moc_daterangeselector.cpp"
86 86
 #endif
87 87
 

+ 110
- 2
src/typica.w View File

@@ -922,6 +922,53 @@ QScriptValue QWidget_activateWindow(QScriptContext *context,
922 922
     return QScriptValue();
923 923
 }
924 924
 
925
+@* Scripting QMessageBox.
926
+
927
+\noindent Some features require that \pn{} pauses an operation until further
928
+information can be obtained. An example of this is discretionary validation
929
+where input is checked and if it seems unlikely but not impossible to be
930
+correct a dialog should come up asking if that input is correct. If it is not,
931
+the operation should be cancelled and the person using \pn{} should be allowed
932
+to correct the information and try again.
933
+
934
+For this use case, it is not necessary to fully expose the |QMessageBox| class.
935
+Instead, it is enough to provide a function that will raise an appropriate
936
+message and return the selected action.
937
+
938
+@<Function prototypes for scripting@>=
939
+QScriptValue displayWarning(QScriptContext *context, QScriptEngine *engine);
940
+QScriptValue displayError(QScriptContext *context, QScriptEngine *engine);
941
+
942
+@ This function is exposed to the host environment.
943
+
944
+@<Set up the scripting engine@>=
945
+constructor = engine->newFunction(displayWarning);
946
+engine->globalObject().setProperty("displayWarning", constructor);
947
+constructor = engine->newFunction(displayError);
948
+engine->globalObject().setProperty("displayError", constructor);
949
+
950
+@ The function takes some arguments.
951
+
952
+@<Functions for scripting@>=
953
+QScriptValue displayWarning(QScriptContext *context, QScriptEngine *)
954
+{
955
+    QMessageBox::StandardButton selection = QMessageBox::warning(NULL,
956
+        argument<QString>(0, context),
957
+        argument<QString>(1, context),
958
+        QMessageBox::Ok | QMessageBox::Cancel);
959
+    if(selection == QMessageBox::Ok) {
960
+        return QScriptValue(true);
961
+    }
962
+    return QScriptValue(false);
963
+}
964
+
965
+QScriptValue displayError(QScriptContext *context, QScriptEngine *)
966
+{
967
+    QMessageBox::critical(NULL, argument<QString>(0, context),
968
+                          argument<QString>(1, context));
969
+    return QScriptValue();
970
+}
971
+
925 972
 @* Scripting QMainWindow.
926 973
 
927 974
 \noindent Rather than directly exposing |QMainWindow| to the scripting engine,
@@ -6033,6 +6080,8 @@ void setQDateTimeEditProperties(QScriptValue value, QScriptEngine *engine)
6033 6080
     value.setProperty("day", engine->newFunction(QDateTimeEdit_day));
6034 6081
     value.setProperty("month", engine->newFunction(QDateTimeEdit_month));
6035 6082
     value.setProperty("year", engine->newFunction(QDateTimeEdit_year));
6083
+    value.setProperty("setToCurrentTime",
6084
+                      engine->newFunction(QDateTimeEdit_setToCurrentTime));
6036 6085
 }
6037 6086
 
6038 6087
 @ Certain operations on a |QDateEdit| are easier with a few convenience
@@ -6077,6 +6126,13 @@ QScriptValue QDateTimeEdit_year(QScriptContext *context, QScriptEngine *)
6077 6126
     return QScriptValue(self->date().year());
6078 6127
 }
6079 6128
 
6129
+QScriptValue QDateTimeEdit_setToCurrentTime(QScriptContext *context, QScriptEngine *)
6130
+{
6131
+    QDateTimeEdit *self = getself<QDateTimeEdit *>(context);
6132
+    self->setDateTime(QDateTime::currentDateTime());
6133
+    return QScriptValue();
6134
+}
6135
+
6080 6136
 @ A few function prototypes are needed for this.
6081 6137
 
6082 6138
 @<Function prototypes for scripting@>=
@@ -6088,6 +6144,7 @@ QScriptValue QDateTimeEdit_day(QScriptContext *context, QScriptEngine *engine);
6088 6144
 QScriptValue QDateTimeEdit_month(QScriptContext *context,
6089 6145
                                  QScriptEngine *engine);
6090 6146
 QScriptValue QDateTimeEdit_year(QScriptContext *context, QScriptEngine *engine);
6147
+QScriptValue QDateTimeEdit_setToCurrentTime(QScriptContext *context, QScriptEngine *engine);
6091 6148
 
6092 6149
 @ In order to get to objects created from the XML description, it is necessary
6093 6150
 to provide a function that can be called to retrieve children of a given widget.
@@ -16105,6 +16162,9 @@ class RoasterConfWidget : public BasicDeviceConfigurationWidget
16105 16162
                                             const QModelIndex &index);
16106 16163
     @[private slots@]:@/
16107 16164
         void updateRoasterId(int id);
16165
+        void updateCapacityCheck(int value);
16166
+        void updateCapacity(const QString &value);
16167
+        void updateCapacityUnit(const QString &value);
16108 16168
 };
16109 16169
 
16110 16170
 @ Aside from the ID number used to identify the roaster in the database we also
@@ -16186,7 +16246,26 @@ RoasterConfWidget::RoasterConfWidget(DeviceTreeModel *model, const QModelIndex &
16186 16246
     idLayout->addWidget(idLabel);
16187 16247
     QSpinBox *id = new QSpinBox;
16188 16248
     idLayout->addWidget(id);
16249
+    idLayout->addStretch();
16189 16250
     layout->addLayout(idLayout);
16251
+    QHBoxLayout *capacityLayout = new QHBoxLayout;
16252
+    QCheckBox *capacityCheckEnabled = new QCheckBox(tr("Maximum batch size:"));
16253
+    QDoubleSpinBox *capacity = new QDoubleSpinBox;
16254
+    capacity->setMinimum(0.0);
16255
+    capacity->setDecimals(3);
16256
+    capacity->setMaximum(999999.999);
16257
+    QComboBox *capacityUnit = new QComboBox;
16258
+    capacityUnit->addItem("g");
16259
+    capacityUnit->addItem("Kg");
16260
+    capacityUnit->addItem("oz");
16261
+    capacityUnit->addItem("Lb");
16262
+    capacityUnit->setCurrentIndex(3);
16263
+    capacityLayout->addWidget(capacityCheckEnabled);
16264
+    capacityLayout->addWidget(capacity);
16265
+    capacityLayout->addWidget(capacityUnit);
16266
+    capacityLayout->addStretch();
16267
+    layout->addLayout(capacityLayout);
16268
+    layout->addStretch();
16190 16269
     @<Get device configuration data for current node@>@;
16191 16270
     for(int i = 0; i < configData.size(); i++)
16192 16271
     {
@@ -16194,11 +16273,25 @@ RoasterConfWidget::RoasterConfWidget(DeviceTreeModel *model, const QModelIndex &
16194 16273
         if(node.attribute("name") == "databaseid")
16195 16274
         {
16196 16275
             id->setValue(node.attribute("value").toInt());
16197
-            break;
16276
+        }
16277
+        else if(node.attribute("name") == "checkcapacity")
16278
+        {
16279
+            capacityCheckEnabled->setChecked(node.attribute("value") == "true");
16280
+        }
16281
+        else if(node.attribute("name") == "capacity")
16282
+        {
16283
+            capacity->setValue(node.attribute("value").toDouble());
16284
+        }
16285
+        else if(node.attribute("name") == "capacityunit")
16286
+        {
16287
+            capacityUnit->setCurrentIndex(capacityUnit->findText(node.attribute("value")));
16198 16288
         }
16199 16289
     }
16200 16290
     updateRoasterId(id->value());
16201 16291
     connect(id, SIGNAL(valueChanged(int)), this, SLOT(updateRoasterId(int)));
16292
+    connect(capacityCheckEnabled, SIGNAL(stateChanged(int)), this, SLOT(updateCapacityCheck(int)));
16293
+    connect(capacity, SIGNAL(valueChanged(QString)), this, SLOT(updateCapacity(QString)));
16294
+    connect(capacityUnit, SIGNAL(currentIndexChanged(QString)), this, SLOT(updateCapacityUnit(QString)));
16202 16295
     setLayout(layout);
16203 16296
 }
16204 16297
 
@@ -16215,7 +16308,7 @@ QDomElement referenceElement =
16215 16308
 QDomNodeList configData = referenceElement.elementsByTagName("attribute");
16216 16309
 QDomElement node;
16217 16310
 
16218
-@ We need to propagate changes to the ID number field to the device
16311
+@ We need to propagate changes to the configuration fields to the device
16219 16312
 configuration document. The |updateAttribute()| method in the base class
16220 16313
 makes this trivial.
16221 16314
 
@@ -16225,6 +16318,21 @@ void RoasterConfWidget::updateRoasterId(int id)
16225 16318
     updateAttribute("databaseid", QString("%1").arg(id));
16226 16319
 }
16227 16320
 
16321
+void RoasterConfWidget::updateCapacityCheck(int value)
16322
+{
16323
+    updateAttribute("checkcapacity", value == Qt::Checked ? "true" : "false");
16324
+}
16325
+
16326
+void RoasterConfWidget::updateCapacity(const QString &value)
16327
+{
16328
+    updateAttribute("capacity", value);
16329
+}
16330
+
16331
+void RoasterConfWidget::updateCapacityUnit(const QString &value)
16332
+{
16333
+    updateAttribute("capacityunit", value);
16334
+}
16335
+
16228 16336
 @ Finally we must register the configuration widget so that it can be
16229 16337
 instantiated at the appropriate time.
16230 16338
 

Loading…
Cancel
Save