瀏覽代碼

Wrap all SQLCommand objects in using blocks.
Improve button layout calculation and centre button images.
Rewrite download thread logic.
Enable resync timer.
Replace Command.ExecuteNonQuery and Command.ExecuteScalar with calls to DBExecuteNonQuery and DBExecuteScalar wherever possible.
Remove unnecessary ExecuteNonQuery calls from before ExecuteReader calls in export form.
Add database write lock and wrap all ExecuteNonQuery calls and transactions with it.
Move MAXDbPath and MAXDbFilePath to Globals and set at startup.
Add migration to add database indexes, change log id to autoincrement and add Download column to batches.
Modify RESTRequest to set Result parameter to null on 404 errors.
Fixed button paint.

Brett Credo 8 年之前
父節點
當前提交
67157e8bc2

+ 358 - 126
BulkPrinting/BulkPrinting/BatchForm.cs

@@ -1,26 +1,21 @@
1 1
 using System;
2 2
 using System.Collections.Generic;
3 3
 using System.ComponentModel;
4
-using System.Data;
5
-using System.Drawing;
6
-using System.Linq;
7
-using System.Text;
8
-using System.Threading.Tasks;
9
-using System.Windows.Forms;
10
-using System.IO;
11
-using System.Net;
12
-using Newtonsoft.Json;
13
-using Newtonsoft.Json.Serialization;
14 4
 using System.Data.SQLite;
15
-using System.Threading;
5
+using System.Diagnostics;
6
+using System.Drawing;
16 7
 using System.Globalization;
8
+using System.Threading;
9
+using System.Windows.Forms;
17 10
 
18 11
 namespace BulkPrinting
19 12
 {
20 13
     public partial class BatchForm : ObservedForm
21 14
     {
22
-        EventWaitHandle LoadingThreadEvent;
23 15
         Thread LoadingThread;
16
+        readonly object LoadingThreadLock = new object();
17
+        bool CheckForNewBatches;
18
+        bool RetryDownloads;
24 19
 
25 20
         public BatchForm()
26 21
         {
@@ -38,32 +33,34 @@ namespace BulkPrinting
38 33
         {
39 34
             Dictionary<int, BatchEvent> BatchEvents = new Dictionary<int, BatchEvent>();
40 35
             string Sql = "Select COUNT(v.BatchId) AS Total, v.BatchId,l.EventType,l.Retry FROM Voucher v LEFT JOIN Logs l on v.Id = l.VoucherId WHERE l.EventType in (@printevent,@exportevent) GROUP BY v.BatchId,l.EventType,l.Retry ORDER BY BatchId";
41
-            SQLiteCommand Command = new SQLiteCommand(Sql, Globals.DBConnection);
42
-            Command.Parameters.Add(new SQLiteParameter("@printevent", VendorEvent.VendorEventType.PrintVoucher));
43
-            Command.Parameters.Add(new SQLiteParameter("@exportevent", VendorEvent.VendorEventType.ExportVoucher));
44
-            using (SQLiteDataReader read = Command.ExecuteReader())
36
+            using (var Command = new SQLiteCommand(Sql, Globals.DBConnection))
45 37
             {
46
-                while (read.Read())
38
+                Command.Parameters.AddWithValue("@printevent", VendorEvent.VendorEventType.PrintVoucher);
39
+                Command.Parameters.AddWithValue("@exportevent", VendorEvent.VendorEventType.ExportVoucher);
40
+                using (SQLiteDataReader read = Command.ExecuteReader())
47 41
                 {
48
-                    int BatchId = int.Parse(read["BatchId"].ToString());
49
-                    if (!BatchEvents.ContainsKey(BatchId))
50
-                    {
51
-                        BatchEvents.Add(BatchId, new BatchEvent());
52
-                    }
53
-                    if (read["EventType"].ToString() == "6")
42
+                    while (read.Read())
54 43
                     {
55
-                        if (read["Retry"].ToString() == "True")
44
+                        int BatchId = int.Parse(read["BatchId"].ToString());
45
+                        if (!BatchEvents.ContainsKey(BatchId))
56 46
                         {
57
-                            BatchEvents[BatchId].ReprintCount += int.Parse(read["Total"].ToString());
47
+                            BatchEvents.Add(BatchId, new BatchEvent());
58 48
                         }
59
-                        else
49
+                        if (read["EventType"].ToString() == "6")
60 50
                         {
61
-                            BatchEvents[BatchId].PrintCount += int.Parse(read["Total"].ToString());
51
+                            if (read["Retry"].ToString() == "True")
52
+                            {
53
+                                BatchEvents[BatchId].ReprintCount += int.Parse(read["Total"].ToString());
54
+                            }
55
+                            else
56
+                            {
57
+                                BatchEvents[BatchId].PrintCount += int.Parse(read["Total"].ToString());
58
+                            }
59
+                        }
60
+                        else if (read["EventType"].ToString() == "8")
61
+                        {
62
+                            BatchEvents[BatchId].ExportCount += int.Parse(read["Total"].ToString());
62 63
                         }
63
-                    }
64
-                    else if (read["EventType"].ToString() == "8")
65
-                    {
66
-                        BatchEvents[BatchId].ExportCount += int.Parse(read["Total"].ToString());
67 64
                     }
68 65
                 }
69 66
             }
@@ -83,95 +80,105 @@ namespace BulkPrinting
83 80
             if (CanOrder) dgvBatches.Columns.Add("RequestedQuantity", "Quantity Ordered");
84 81
             dgvBatches.Columns.Add("DeliveredQuantity", "Quantity Delivered");
85 82
             if (CanOrder) dgvBatches.Columns.Add("ReadyForDownload", "Batch Ready for Download");
83
+            dgvBatches.Columns.Add("Downloaded", "Downloaded");
86 84
             dgvBatches.Columns.Add("PrintedQuantity", "Quantity Printed");
87 85
             if (CanExport) dgvBatches.Columns.Add("Exported", "Exported Batch");
88
-            Sql = "Select Id,OrderDate,OrderReference,InternalReference,NetworkName,ProductDescription,VoucherType,FaceValue,RequestedQuantity,DeliveredQuantity,ReadyForDownload From Batch WHERE OrderDate BETWEEN @startdate AND @enddate";
89
-
86
+            Sql = "Select Id,OrderDate,OrderReference,InternalReference,NetworkName,ProductDescription,VoucherType,FaceValue,RequestedQuantity,DeliveredQuantity,ReadyForDownload,Downloaded From Batch WHERE OrderDate BETWEEN @startdate AND @enddate";
90 87
 
88
+            //Sql = "Select Id,OrderDate,OrderReference,InternalReference,NetworkName,ProductDescription,VoucherType,FaceValue,RequestedQuantity,DeliveredQuantity,ReadyForDownload,Downloaded,(SELECT COUNT(*) FROM Voucher WHERE Voucher.BatchId=Batch.Id) AS VoucherCount From Batch WHERE OrderDate BETWEEN @startdate AND @enddate";
89
+            //dgvBatches.Columns.Add("VoucherCount", "Voucher Count");
91 90
 
92
-            SQLiteCommand comm = new SQLiteCommand(Sql, Globals.DBConnection);
93 91
 
94
-            CultureInfo IVC = CultureInfo.InvariantCulture;
95
-            comm.Parameters.Add(new SQLiteParameter("@startdate", dtpFilterStartDate.Value.Date.ToString("yyyy-MM-dd 00:00:00", IVC)));
96
-            comm.Parameters.Add(new SQLiteParameter("@enddate", dtpFilterEndDate.Value.Date.ToString("yyyy-MM-dd 23:59:59", IVC)));
97
-
98
-
99
-            lblLoading.Hide();
100
-            using (SQLiteDataReader read = comm.ExecuteReader())
92
+            using (var Command = new SQLiteCommand(Sql, Globals.DBConnection))
101 93
             {
102
-                while (read.Read())
103
-                {
104
-                    int BatchId = int.Parse(read["Id"].ToString());
105
-                    if (!BatchEvents.ContainsKey(BatchId))
106
-                    { //For batches with no events
107
-                        BatchEvents.Add(BatchId, new BatchEvent());
108
-                    }
109
-                    int DeliveredQuantity = int.Parse(read["DeliveredQuantity"].ToString());
94
+                CultureInfo IVC = CultureInfo.InvariantCulture;
95
+                Command.Parameters.AddWithValue("@startdate", dtpFilterStartDate.Value.Date.ToString("yyyy-MM-dd 00:00:00", IVC));
96
+                Command.Parameters.AddWithValue("@enddate", dtpFilterEndDate.Value.Date.ToString("yyyy-MM-dd 23:59:59", IVC));
110 97
 
111
-                    //Filters to exclude rows that don't match
112
-                    if (rdoFilterPrinted.Checked)
98
+                lblLoading.Hide();
99
+                using (SQLiteDataReader read = Command.ExecuteReader())
100
+                {
101
+                    while (read.Read())
113 102
                     {
114
-                        if (BatchEvents[BatchId].PrintCount == 0)
103
+                        int BatchId = int.Parse(read["Id"].ToString());
104
+                        if (!BatchEvents.ContainsKey(BatchId))
105
+                        { //For batches with no events
106
+                            BatchEvents.Add(BatchId, new BatchEvent());
107
+                        }
108
+                        int DeliveredQuantity = int.Parse(read["DeliveredQuantity"].ToString());
109
+
110
+                        //Filters to exclude rows that don't match
111
+                        if (rdoFilterPrinted.Checked)
115 112
                         {
116
-                            continue;
113
+                            if (BatchEvents[BatchId].PrintCount == 0)
114
+                            {
115
+                                continue;
116
+                            }
117 117
                         }
118
-                    }
119
-                    if (rdoFilterUnprinted.Checked) {
120
-                        if (BatchEvents[BatchId].PrintCount >= DeliveredQuantity)
118
+                        if (rdoFilterUnprinted.Checked)
121 119
                         {
122
-                            continue;
120
+                            if (BatchEvents[BatchId].PrintCount >= DeliveredQuantity)
121
+                            {
122
+                                continue;
123
+                            }
123 124
                         }
124
-                    }
125
-                    if (rdoFilterReprinted.Checked) {
126
-                        if (BatchEvents[BatchId].ReprintCount == 0)
125
+                        if (rdoFilterReprinted.Checked)
127 126
                         {
128
-                            continue;
127
+                            if (BatchEvents[BatchId].ReprintCount == 0)
128
+                            {
129
+                                continue;
130
+                            }
129 131
                         }
130
-                    }
131
-                    if (rdoFilterExported.Checked)
132
-                    {
133
-                        if (BatchEvents[BatchId].ExportCount == 0)
132
+                        if (rdoFilterExported.Checked)
134 133
                         {
135
-                            continue;
134
+                            if (BatchEvents[BatchId].ExportCount == 0)
135
+                            {
136
+                                continue;
137
+                            }
136 138
                         }
137
-                    }
138
-                    else {
139
-                        if (BatchEvents[BatchId].ExportCount > 0)
139
+                        else
140 140
                         {
141
-                            continue;
141
+                            if (BatchEvents[BatchId].ExportCount > 0)
142
+                            {
143
+                                continue;
144
+                            }
142 145
                         }
143
-                    }
144 146
 
145
-                    var BatchRow = new object[] {
146
-                        BatchId,
147
-                        read["OrderDate"] };
148
-                    if (CanOrder)
149
-                    {
150
-                        BatchRow = BatchRow.Concat(new[] { read["OrderReference"] }).ToArray();
151
-                        BatchRow = BatchRow.Concat(new[] { read["InternalReference"] }).ToArray();
152
-                    }
153
-                    BatchRow = BatchRow.Concat(new[] { read["NetworkName"].ToString() }).ToArray();
154
-                    BatchRow = BatchRow.Concat(new[] { read["ProductDescription"].ToString() }).ToArray();
155
-                    BatchRow = BatchRow.Concat(new[] { Enum.Parse(typeof(Vouchertype), read["VoucherType"].ToString()).ToString() }).ToArray();
156
-                    BatchRow = BatchRow.Concat(new[] { "R" + ((decimal)read["FaceValue"]).ToString("0.##") }).ToArray();
147
+                        var BatchRow = new List<object>
148
+                            {
149
+                                BatchId,
150
+                                read["OrderDate"]
151
+                            };
152
+                        if (CanOrder)
153
+                        {
154
+                            BatchRow.Add(read["OrderReference"]);
155
+                            BatchRow.Add(read["InternalReference"]);
156
+                        }
157
+                        BatchRow.Add(read["NetworkName"].ToString());
158
+                        BatchRow.Add(read["ProductDescription"].ToString());
159
+                        BatchRow.Add(Enum.Parse(typeof(Vouchertype), read["VoucherType"].ToString()).ToString());
160
+                        BatchRow.Add("R" + ((decimal)read["FaceValue"]).ToString("0.##"));
161
+
162
+                        if (CanOrder)
163
+                            BatchRow.Add(read["RequestedQuantity"]);
157 164
 
158
-                    
159
-                    if (CanOrder)
160
-                        BatchRow = BatchRow.Concat(new[] { read["RequestedQuantity"] }).ToArray();
165
+                        BatchRow.Add(read["DeliveredQuantity"]);
161 166
 
162
-                    BatchRow = BatchRow.Concat(new[] { read["DeliveredQuantity"] }).ToArray();
167
+                        if (CanOrder)
168
+                            BatchRow.Add(((bool)read["ReadyForDownload"] == true ? "Yes" : "No"));
163 169
 
164
-                    if (CanOrder)
165
-                        BatchRow = BatchRow.Concat(new[] { ((bool)read["ReadyForDownload"] == true ? "Yes" : "No") }).ToArray();
170
+                        BatchRow.Add((bool)read["Downloaded"] ? "Yes" : "No");
171
+                        BatchRow.Add((object)BatchEvents[BatchId].PrintCount);
166 172
 
167
-                    BatchRow = BatchRow.Concat(new[] { (object)BatchEvents[BatchId].PrintCount }).ToArray();
173
+                        if (CanExport)
174
+                            BatchRow.Add((BatchEvents[BatchId].ExportCount > 0 ? "Exported" : ""));
168 175
 
169
-                    if (CanExport)
170
-                        BatchRow = BatchRow.Concat(new[] { (BatchEvents[BatchId].ExportCount >0?"Exported":"") }).ToArray();
176
+                        //BatchRow.Add(read["VoucherCount"]);
171 177
 
172
-                    dgvBatches.Rows.Add(BatchRow);
178
+                        dgvBatches.Rows.Add(BatchRow.ToArray());
179
+                    }
180
+                    dgvBatches.Sort(dgvBatches.Columns["OrderDate"], ListSortDirection.Descending);
173 181
                 }
174
-                dgvBatches.Sort(dgvBatches.Columns["OrderDate"], ListSortDirection.Descending);
175 182
             }
176 183
         }
177 184
 
@@ -228,51 +235,272 @@ namespace BulkPrinting
228 235
             if (!Utility.CheckUserAccess(Utility.UserPermissions.BulkViewPins))
229 236
                 RightButtonList.Remove(this.btnViewPINs);
230 237
 
231
-            int ButtonX = 12;
238
+            int ButtonX = btnLogout.Location.X;
239
+            int ButtonY = btnLogout.Location.Y;
240
+            int ButtonSpacing = btnOrderReport.Location.X - ButtonX;
232 241
             foreach (Button b in LeftButtonList)
233 242
             {
234
-                b.Location = new Point(ButtonX, 0);
243
+                b.Location = new Point(ButtonX, ButtonY);
235 244
                 b.Show();
236
-                ButtonX += 106;
245
+                ButtonX += ButtonSpacing;
237 246
             }
238 247
 
239
-            ButtonX = pnlSplitGrids.Width - 378;
248
+            ButtonX = btnReprint.Location.X;
240 249
             RightButtonList.Reverse();
241 250
             foreach (Button b in RightButtonList)
242 251
             {
243
-                b.Location = new Point(ButtonX, 0);
252
+                b.Location = new Point(ButtonX, ButtonY);
244 253
                 b.Show();
245
-                ButtonX -= 106;
254
+                ButtonX -= ButtonSpacing;
246 255
             }
247 256
 
248 257
             lblLoading.Show();
249 258
             dtpFilterStartDate.Value = DateTime.Now.AddMonths(-3);
250 259
             Globals.OpenBatches = new List<int>();
251 260
 
252
-            LoadingThreadEvent = new EventWaitHandle(true, EventResetMode.AutoReset);
253
-            LoadingThread = new Thread(() =>
261
+            RetryDownloads = true;
262
+            CheckForNewBatches = true;
263
+
264
+            LoadingThread = new Thread(LoadingThreadWorker);
265
+            LoadingThread.Start();
266
+            Utility.InitialiseUserLimits(Globals.DBConnection);
267
+            ReSyncTimer.Enabled = true;
268
+        }
269
+
270
+        private void LoadingThreadWorker()
271
+        {
272
+            const int voucherPageSize = 5000;
273
+            var conn = Globals.DBConnection;
274
+            //using (var conn = Utility.OpenDBConnection())
254 275
             {
255 276
                 Invoke(new Action(() =>
256 277
                 {
257
-                    this.Enabled = false;
258 278
                     PopulateGrid();
259
-                    this.Enabled = true;
260 279
                 }));
261 280
 
262
-                while (LoadingThreadEvent.WaitOne())
281
+                var lastSyncedBatchId = Utility.GetSavedParameterAsInt(conn, "LastSyncedBatchId");
282
+
283
+                bool skipNewBatchCheck = false;
284
+                while (true)
263 285
                 {
286
+                    bool forceNewBatchCheck;
287
+                    lock (LoadingThreadLock)
288
+                    {
289
+                        while (!RetryDownloads)
290
+                        {
291
+                            Monitor.Wait(LoadingThreadLock);
292
+                        }
293
+                        forceNewBatchCheck = CheckForNewBatches;
294
+                        RetryDownloads = false;
295
+                        CheckForNewBatches = false;
296
+                    }
264 297
                     if (Globals.SessionMode == SessionModes.Online)
265 298
                     {
266
-                        Utility.SyncAllBatches();
267
-                        Invoke(new Action(() =>
299
+                        Debug.WriteLine("Checking for downloads");
300
+
301
+                        if (forceNewBatchCheck)
302
+                        {
303
+                            skipNewBatchCheck = false;
304
+                        }
305
+
306
+                        // Check for new batches if required.
307
+                        var refreshGrid = false;
308
+                        try
309
+                        {
310
+                            while (!skipNewBatchCheck)
311
+                            {
312
+                                Debug.WriteLine("Querying batches");
313
+                                Page<Batch> BatchPage = new Page<Batch>();
314
+                                if (Utility.RESTRequest(ref BatchPage, String.Format("/api/batches/?lastBatchId={0}", lastSyncedBatchId)))
315
+                                {
316
+                                    if (BatchPage.Items.Count == 0)
317
+                                    {
318
+                                        // No more new batches, so stop checking until an order is placed.
319
+                                        skipNewBatchCheck = true;
320
+                                    }
321
+                                    else
322
+                                    {
323
+                                        foreach (var batch in BatchPage.Items)
324
+                                        {
325
+                                            refreshGrid = true;
326
+                                            Utility.SaveBatch(conn, batch);
327
+                                            lastSyncedBatchId = batch.Id;
328
+                                            if (!Utility.UpdateSavedParameter(conn, "LastSyncedBatchId", lastSyncedBatchId))
329
+                                            {
330
+                                                // Shouldn't happen.
331
+                                                throw new Exception("Failed to update LastSyncedBatchId");
332
+                                            }
333
+                                        }
334
+                                    }
335
+                                }
336
+                                else
337
+                                {
338
+                                    // Error, so leave skipNewBatchCheck unchanged.
339
+                                    break;
340
+                                }
341
+                            }
342
+                        }
343
+                        catch (Exception e)
344
+                        {
345
+                            Debug.WriteLine("Error while downloading batches");
346
+                            Debug.WriteLine(e.ToString());
347
+                        }
348
+
349
+                        if (refreshGrid)
268 350
                         {
269
-                            PopulateGrid();
270
-                        }));
351
+                            Invoke(new Action(() =>
352
+                            {
353
+                                PopulateGrid();
354
+                            }));
355
+                        }
356
+
357
+                        // Continue downloading incomplete batches if any.
358
+                        try
359
+                        {
360
+                            using (var command = new SQLiteCommand(
361
+                                "SELECT Id FROM Batch WHERE Downloaded=0 ORDER BY Downloaded, Id",
362
+                                conn))
363
+                            {
364
+                                using (SQLiteDataReader row = command.ExecuteReader())
365
+                                {
366
+                                    while (row.Read())
367
+                                    {
368
+                                        refreshGrid = false;
369
+
370
+                                        int batchId = (int)row["Id"];
371
+                                        try
372
+                                        {
373
+                                            Batch batch = new Batch();
374
+                                            if (Utility.RESTRequest(ref batch, String.Format("/api/batches/{0}", batchId)))
375
+                                            {
376
+                                                refreshGrid = true;
377
+                                                Utility.SaveBatch(conn, batch);
378
+
379
+                                                if (batch.ReadyForDownload)
380
+                                                {
381
+                                                    long result = (long)Utility.DBExecuteScalar(conn,
382
+                                                        "SELECT COUNT(*) FROM Voucher WHERE BatchId=@BatchId",
383
+                                                        new SQLiteParameter("@BatchId", batchId));
384
+                                                    int voucherCount = (int)result;
385
+
386
+                                                    while (voucherCount < batch.DeliveredQuantity)
387
+                                                    {
388
+                                                        Debug.WriteLine(String.Format("Downloading vouchers for batch {0} (got {1})", batchId, voucherCount));
389
+
390
+                                                        int page = voucherCount / voucherPageSize + 1;
391
+                                                        int offset = voucherCount % voucherPageSize;
392
+
393
+                                                        Page<Voucher> voucherPage = new Page<Voucher>();
394
+                                                        if (!Utility.RESTRequest(ref voucherPage, String.Format("/api/batches/{0}/vouchers/?page={1}&pageSize={2}", batchId, page, voucherPageSize)))
395
+                                                        {
396
+                                                            break;
397
+                                                        }
398
+                                                        if (voucherPage.Items.Count == 0)
399
+                                                        {
400
+                                                            throw new Exception(String.Format("Too few vouchers were returned for batch {0}", batchId));
401
+                                                        }
402
+
403
+                                                        Debug.WriteLine(String.Format("Downloaded vouchers for batch {0} (got {1})", batchId, voucherCount + voucherPage.Items.Count));
404
+
405
+                                                        lock (Globals.DBWriteLock)
406
+                                                        {
407
+                                                            using (var trans = conn.BeginTransaction())
408
+                                                            {
409
+                                                                using (var insert = new SQLiteCommand(
410
+                                                                    "INSERT INTO Voucher (Id, SequenceNumber, ExpiryDate, Serial, EncryptedPIN, BatchId)" +
411
+                                                                                 "VALUES (@Id,@SequenceNumber,@ExpiryDate,@Serial,@EncryptedPin,@BatchId)",
412
+                                                                    conn, trans))
413
+                                                                {
414
+                                                                    for (var i = offset; i < voucherPage.Items.Count; i++)
415
+                                                                    {
416
+                                                                        var voucher = voucherPage.Items[i];
417
+                                                                        if (voucher.SequenceNumber != voucherCount + 1)
418
+                                                                        {
419
+                                                                            throw new Exception(String.Format("Vouchers for batch {0} are not sequential: expecting {1}, got {2}", batchId, voucherCount + 1, voucher.SequenceNumber));
420
+                                                                        }
421
+                                                                        insert.Parameters.Clear();
422
+                                                                        insert.Parameters.AddWithValue("@Id", voucher.Id);
423
+                                                                        insert.Parameters.AddWithValue("@SequenceNumber", voucher.SequenceNumber);
424
+                                                                        insert.Parameters.AddWithValue("@ExpiryDate", voucher.ExpiryDate.Date);
425
+                                                                        insert.Parameters.AddWithValue("@Serial", voucher.Serial);
426
+                                                                        insert.Parameters.AddWithValue("@EncryptedPIN", voucher.EncryptedPIN);
427
+                                                                        insert.Parameters.AddWithValue("@BatchId", batchId);
428
+                                                                        insert.ExecuteNonQuery();
429
+                                                                        voucherCount++;
430
+                                                                    }
431
+                                                                }
432
+                                                                trans.Commit();
433
+                                                            }
434
+                                                        }
435
+
436
+                                                        Debug.WriteLine(String.Format("Inserted vouchers for batch {0}", batchId));
437
+                                                    }
438
+
439
+                                                    if (voucherCount > batch.DeliveredQuantity)
440
+                                                    {
441
+                                                        throw new Exception("Batch contains more than the specified number of vouchers");
442
+                                                    }
443
+                                                    else
444
+                                                    {
445
+                                                        Debug.WriteLine(String.Format("Batch {0} complete", batchId));
446
+
447
+                                                        Utility.DBExecuteNonQuery(conn,
448
+                                                            "UPDATE Batch SET Downloaded=1 WHERE Id=@BatchId",
449
+                                                            new SQLiteParameter("@BatchId", batchId));
450
+                                                    }
451
+                                                }
452
+                                            }
453
+                                            else if (batch == null)
454
+                                            {
455
+                                                // Batch will only be null if we got a 404.
456
+                                                Debug.WriteLine(String.Format("Removing deleted batch {0}", batchId));
457
+
458
+                                                Utility.DBExecuteNonQuery(conn,
459
+                                                    "DELETE FROM Voucher WHERE BatchId=@BatchId",
460
+                                                    new SQLiteParameter("@BatchId", batchId));
461
+
462
+                                                Utility.DBExecuteNonQuery(conn,
463
+                                                    "DELETE FROM Batch WHERE Id=@BatchId",
464
+                                                    new SQLiteParameter("@BatchId", batchId));
465
+
466
+                                                refreshGrid = true;
467
+                                            }
468
+                                        }
469
+                                        catch (Exception e)
470
+                                        {
471
+                                            Debug.WriteLine(String.Format("Error while downloading vouchers for batch {0}", batchId));
472
+                                            Debug.WriteLine(e.ToString());
473
+                                        }
474
+
475
+                                        if (refreshGrid)
476
+                                        {
477
+                                            Invoke(new Action(() =>
478
+                                            {
479
+                                                PopulateGrid();
480
+                                            }));
481
+                                        }
482
+                                    }
483
+                                }
484
+                            }
485
+                        }
486
+                        catch (Exception e)
487
+                        {
488
+                            Debug.WriteLine("Error while downloading vouchers");
489
+                            Debug.WriteLine(e.ToString());
490
+                        }
271 491
                     }
272 492
                 }
273
-            });
274
-            LoadingThread.Start();
275
-            Utility.InitialiseUserLimits();
493
+            }
494
+        }
495
+
496
+        public void NewBatchAvailable()
497
+        {
498
+            lock (LoadingThreadLock)
499
+            {
500
+                RetryDownloads = true;
501
+                CheckForNewBatches = true;
502
+                Monitor.Pulse(LoadingThreadLock);
503
+            }
276 504
         }
277 505
 
278 506
         private void btnOrder_Click(object sender, EventArgs e)
@@ -309,10 +537,9 @@ namespace BulkPrinting
309 537
             }
310 538
 
311 539
             int DeliveredVoucherCount = (int)dgvBatches.SelectedRows[0].Cells[dgvBatches.Columns["DeliveredQuantity"].Index].Value;
312
-            string Sql = "SELECT COUNT(*) FROM Voucher WHERE BatchId=@id";
313
-            SQLiteCommand Command = new SQLiteCommand(Sql, Globals.DBConnection);
314
-            Command.Parameters.Add(new SQLiteParameter("@id", BatchID));
315
-            int DownloadedVoucherCount = Convert.ToInt32(Command.ExecuteScalar());
540
+            int DownloadedVoucherCount = Convert.ToInt32(Utility.DBExecuteScalar(Globals.DBConnection,
541
+                "SELECT COUNT(*) FROM Voucher WHERE BatchId=@id",
542
+                new SQLiteParameter("@id", BatchID)));
316 543
             if (DownloadedVoucherCount < DeliveredVoucherCount) {
317 544
                 MessageBox.Show(string.Format("Batch {0} has not finished downloading.\nDownloaded {1} of {2} vouchers in batch.",BatchID,DownloadedVoucherCount,DeliveredVoucherCount), "Cannot open print dialog", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
318 545
                 return;
@@ -359,6 +586,7 @@ namespace BulkPrinting
359 586
             if ((LoadingThread != null) && (LoadingThread.IsAlive))
360 587
             {
361 588
                 LoadingThread.Abort();
589
+                LoadingThread.Join();
362 590
             }
363 591
             Utility.Logout();
364 592
         }
@@ -461,10 +689,10 @@ namespace BulkPrinting
461 689
                 MessageBox.Show("This batch has been exported previously. Exported batches cannot be printed.", "Cannot print batch", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
462 690
                 return;
463 691
             }
464
-            SQLiteCommand Command = new SQLiteCommand("SELECT COUNT(*) FROM Voucher v LEFT JOIN Logs l ON v.Id = l.VoucherId AND l.EventType = @eventtype WHERE l.VoucherId IS NOT NULL AND v.BatchId=@batchid AND Retry=0", Globals.DBConnection);
465
-            Command.Parameters.Add(new SQLiteParameter("@batchid", BatchID));
466
-            Command.Parameters.Add(new SQLiteParameter("@eventtype", VendorEvent.VendorEventType.PrintVoucher));
467
-            int PrintCount = int.Parse(Command.ExecuteScalar().ToString());
692
+            int PrintCount = int.Parse(Utility.DBExecuteScalar(Globals.DBConnection,
693
+                "SELECT COUNT(*) FROM Voucher v LEFT JOIN Logs l ON v.Id = l.VoucherId AND l.EventType = @eventtype WHERE l.VoucherId IS NOT NULL AND v.BatchId=@batchid AND Retry=0",
694
+                new SQLiteParameter("@batchid", BatchID),
695
+                new SQLiteParameter("@eventtype", VendorEvent.VendorEventType.PrintVoucher)).ToString());
468 696
 
469 697
             if (PrintCount == 0) {
470 698
                 MessageBox.Show("You can only use the Reprint feature for vouchers that have already been printed. Please choose a batch with previously printed vouchers.", "Cannot reprint batch", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
@@ -472,10 +700,9 @@ namespace BulkPrinting
472 700
             }
473 701
 
474 702
             int DeliveredVoucherCount = (int)dgvBatches.SelectedRows[0].Cells[dgvBatches.Columns["DeliveredQuantity"].Index].Value;
475
-            string Sql = "SELECT COUNT(*) FROM Voucher WHERE BatchId=@id";
476
-            Command = new SQLiteCommand(Sql, Globals.DBConnection);
477
-            Command.Parameters.Add(new SQLiteParameter("@id", BatchID));
478
-            int DownloadedVoucherCount = Convert.ToInt32(Command.ExecuteScalar());
703
+            int DownloadedVoucherCount = Convert.ToInt32(Utility.DBExecuteScalar(Globals.DBConnection,
704
+                "SELECT COUNT(*) FROM Voucher WHERE BatchId=@id",
705
+                new SQLiteParameter("@id", BatchID)));
479 706
             if (DownloadedVoucherCount < DeliveredVoucherCount)
480 707
             {
481 708
                 MessageBox.Show(string.Format("Batch {0} has not finished downloading.\nDownloaded {1} of {2} vouchers in batch.", BatchID, DownloadedVoucherCount, DeliveredVoucherCount), "Cannot open print dialog", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
@@ -538,13 +765,18 @@ namespace BulkPrinting
538 765
             if (!b.Enabled)
539 766
             {
540 767
                 e.Graphics.Clear(Color.Gray);
541
-                e.Graphics.DrawImage(b.BackgroundImage, e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width, e.ClipRectangle.Height);
768
+                //e.Graphics.DrawImage(b.BackgroundImage, e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width, e.ClipRectangle.Height);
769
+                e.Graphics.DrawImage(b.BackgroundImage, b.ClientRectangle);
542 770
             }
543 771
         }
544 772
 
545 773
         private void ReSyncTimer_Tick(object sender, EventArgs e)
546 774
         {
547
-            LoadingThreadEvent.Set();
775
+            lock (LoadingThreadLock)
776
+            {
777
+                RetryDownloads = true;
778
+                Monitor.Pulse(LoadingThreadLock);
779
+            }
548 780
         }
549 781
     }
550 782
 }

+ 1 - 8
BulkPrinting/BulkPrinting/Configuration.cs

@@ -1,11 +1,4 @@
1
-using System;
2
-using System.Collections.Generic;
3
-using System.Linq;
4
-using System.Text;
5
-using System.Threading.Tasks;
6
-using System.IO;
7
-
8
-namespace BulkPrinting
1
+namespace BulkPrinting
9 2
 {
10 3
     public static class Configuration
11 4
     {

+ 78 - 76
BulkPrinting/BulkPrinting/ExportForm.cs

@@ -49,35 +49,36 @@ namespace BulkPrinting
49 49
                 Sql += " AND b.NetworkName=@networkname";
50 50
             }
51 51
             Sql += " GROUP BY b.Id,b.FaceValue,b.ProductDescription,b.DeliveredQuantity";
52
-            SQLiteCommand Command = new SQLiteCommand(Sql, Globals.DBConnection);
53
-            if (cmbNetwork.SelectedItem.ToString() != "All")
52
+            using (var Command = new SQLiteCommand(Sql, Globals.DBConnection))
54 53
             {
55
-                Command.Parameters.Add(new SQLiteParameter("@networkname", cmbNetwork.SelectedItem.ToString()));
56
-            }
57
-            CultureInfo IVC = CultureInfo.InvariantCulture;
58
-            Command.Parameters.Add(new SQLiteParameter("@startdate", dtpStartDate.Value.Date.ToString("yyyy-MM-dd 00:00:00", IVC)));
59
-            Command.Parameters.Add(new SQLiteParameter("@enddate", dtpEndDate.Value.Date.ToString("yyyy-MM-dd 23:59:59", IVC)));
60
-            Command.Parameters.Add(new SQLiteParameter("@printevent", VendorEvent.VendorEventType.PrintVoucher));
61
-            Command.Parameters.Add(new SQLiteParameter("@exportevent", VendorEvent.VendorEventType.ExportVoucher));
62
-            Command.ExecuteNonQuery();
63
-            lstBatchList.Items.Clear();
64
-            using (SQLiteDataReader read = Command.ExecuteReader())
65
-            {
66
-                while (read.Read())
54
+                if (cmbNetwork.SelectedItem.ToString() != "All")
67 55
                 {
68
-                    if (read["Printed"].ToString() == "0")
56
+                    Command.Parameters.AddWithValue("@networkname", cmbNetwork.SelectedItem.ToString());
57
+                }
58
+                CultureInfo IVC = CultureInfo.InvariantCulture;
59
+                Command.Parameters.AddWithValue("@startdate", dtpStartDate.Value.Date.ToString("yyyy-MM-dd 00:00:00", IVC));
60
+                Command.Parameters.AddWithValue("@enddate", dtpEndDate.Value.Date.ToString("yyyy-MM-dd 23:59:59", IVC));
61
+                Command.Parameters.AddWithValue("@printevent", VendorEvent.VendorEventType.PrintVoucher);
62
+                Command.Parameters.AddWithValue("@exportevent", VendorEvent.VendorEventType.ExportVoucher);
63
+                lstBatchList.Items.Clear();
64
+                using (SQLiteDataReader read = Command.ExecuteReader())
65
+                {
66
+                    while (read.Read())
69 67
                     {
70
-                        if ((SelectedMode == ExportMode.Export && read["Exported"].ToString() != "0") ||
71
-                            (SelectedMode == ExportMode.Reexport && read["Exported"].ToString() == "0"))
68
+                        if (read["Printed"].ToString() == "0")
72 69
                         {
73
-                            continue;
70
+                            if ((SelectedMode == ExportMode.Export && read["Exported"].ToString() != "0") ||
71
+                                (SelectedMode == ExportMode.Reexport && read["Exported"].ToString() == "0"))
72
+                            {
73
+                                continue;
74
+                            }
75
+                            BatchItem NewBatchItem = new BatchItem();
76
+                            NewBatchItem.Id = int.Parse(read["Id"].ToString());
77
+                            NewBatchItem.Description = read["ProductDescription"].ToString();
78
+                            NewBatchItem.Quantity = int.Parse(read["DeliveredQuantity"].ToString());
79
+                            NewBatchItem.FaceValue = int.Parse(read["FaceValue"].ToString());
80
+                            lstBatchList.Items.Add(NewBatchItem);
74 81
                         }
75
-                        BatchItem NewBatchItem = new BatchItem();
76
-                        NewBatchItem.Id = int.Parse(read["Id"].ToString());
77
-                        NewBatchItem.Description = read["ProductDescription"].ToString();
78
-                        NewBatchItem.Quantity = int.Parse(read["DeliveredQuantity"].ToString());
79
-                        NewBatchItem.FaceValue = int.Parse(read["FaceValue"].ToString());
80
-                        lstBatchList.Items.Add(NewBatchItem);
81 82
                     }
82 83
                 }
83 84
             }
@@ -96,15 +97,16 @@ namespace BulkPrinting
96 97
                 lblBatchType.Text = "Previously Exported Batches";
97 98
             }
98 99
             string Sql = "SELECT DISTINCT NetworkName FROM Batch";
99
-            SQLiteCommand Command = new SQLiteCommand(Sql, Globals.DBConnection);
100
-            Command.ExecuteNonQuery();
101
-            cmbNetwork.Items.Clear();
102
-            cmbNetwork.Items.Add("All");
103
-            using (SQLiteDataReader read = Command.ExecuteReader())
100
+            using (var Command = new SQLiteCommand(Sql, Globals.DBConnection))
104 101
             {
105
-                while (read.Read())
102
+                cmbNetwork.Items.Clear();
103
+                cmbNetwork.Items.Add("All");
104
+                using (SQLiteDataReader read = Command.ExecuteReader())
106 105
                 {
107
-                    cmbNetwork.Items.Add(read["NetworkName"]);
106
+                    while (read.Read())
107
+                    {
108
+                        cmbNetwork.Items.Add(read["NetworkName"]);
109
+                    }
108 110
                 }
109 111
             }
110 112
             cmbNetwork.SelectedItem="All";
@@ -151,59 +153,59 @@ namespace BulkPrinting
151 153
                     List<EventLog> LogEvents = new List<EventLog>();
152 154
 
153 155
                     string Sql = "SELECT v.Id,v.ExpiryDate,v.Serial,v.EncryptedPIN,b.FaceValue,v.BatchId,v.SequenceNumber,b.ProductDescription,COUNT(l.Id) AS Exports FROM Voucher v LEFT JOIN Logs l ON v.Id = l.VoucherId AND l.EventType=@eventtype LEFT JOIN Batch b ON v.BatchId=b.Id WHERE BatchId=@batchid GROUP BY v.Id,v.ExpiryDate,v.Serial,v.EncryptedPIN,b.FaceValue,v.BatchId,v.SequenceNumber,b.ProductDescription";
154
-                    SQLiteCommand Command = new SQLiteCommand(Sql, Globals.DBConnection);
155
-
156
-                    foreach (BatchItem ExportBatch in lstSelectedBatches.Items)
156
+                    using (var Command = new SQLiteCommand(Sql, Globals.DBConnection))
157 157
                     {
158
-                        /*  -Id
159
-                            -Expiry
160
-                            -Serial
161
-                            -PIN
162
-                            -Face Value
163
-                            -BatchID
164
-                            -SQN
165
-                            -Description
166
-                        */
167
-                        if (Command.Parameters.Count == 0)
158
+                        foreach (BatchItem ExportBatch in lstSelectedBatches.Items)
168 159
                         {
169
-                            Command.Parameters.Add(new SQLiteParameter("@batchid", ExportBatch.Id));
170
-                            Command.Parameters.Add(new SQLiteParameter("@eventtype", VendorEvent.VendorEventType.ExportVoucher));
171
-                        }
172
-                        else
173
-                        {
174
-                            Command.Parameters[0].Value = ExportBatch.Id;
175
-                            Command.Parameters[1].Value = VendorEvent.VendorEventType.ExportVoucher;
176
-                        }
177
-                        // Command.Prepare(); // < -- internal
178
-                        Command.ExecuteNonQuery();
179
-                        using (StreamWriter sw = File.CreateText(Path.Combine(PathDialog.SelectedPath, "RG_" + ExportBatch.Id.ToString() + "_" + ExportBatch.Description + "_" + ExportBatch.FaceValue.ToString() + ".txt")))
180
-                        {
181
-                            sw.WriteLine("ID|Expiry|Serial|PIN|Value|BatchId|SQN|Description");
182
-                            using (SQLiteDataReader read = Command.ExecuteReader())
160
+                            /*  -Id
161
+                                -Expiry
162
+                                -Serial
163
+                                -PIN
164
+                                -Face Value
165
+                                -BatchID
166
+                                -SQN
167
+                                -Description
168
+                            */
169
+                            if (Command.Parameters.Count == 0)
170
+                            {
171
+                                Command.Parameters.AddWithValue("@batchid", ExportBatch.Id);
172
+                                Command.Parameters.AddWithValue("@eventtype", VendorEvent.VendorEventType.ExportVoucher);
173
+                            }
174
+                            else
175
+                            {
176
+                                Command.Parameters[0].Value = ExportBatch.Id;
177
+                                Command.Parameters[1].Value = VendorEvent.VendorEventType.ExportVoucher;
178
+                            }
179
+                            // Command.Prepare(); // < -- internal
180
+                            using (StreamWriter sw = File.CreateText(Path.Combine(PathDialog.SelectedPath, "RG_" + ExportBatch.Id.ToString() + "_" + ExportBatch.Description + "_" + ExportBatch.FaceValue.ToString() + ".txt")))
183 181
                             {
184
-                                while (read.Read())
182
+                                sw.WriteLine("ID|Expiry|Serial|PIN|Value|BatchId|SQN|Description");
183
+                                using (SQLiteDataReader read = Command.ExecuteReader())
185 184
                                 {
186
-                                    string DecryptedPIN = Utility.TripleDESDecrypt(read["EncryptedPIN"].ToString(), Globals.SessionVoucherKey).ToString();
187
-                                    string ExportRow = string.Format("{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}",
188
-                                                 read["Id"].ToString(),
189
-                                                 DateTime.Parse(read["ExpiryDate"].ToString()).ToString("dd/MM/yyyy"),
190
-                                                 read["Serial"].ToString(),
191
-                                                 DecryptedPIN,
192
-                                                 read["FaceValue"].ToString(),
193
-                                                 read["BatchId"].ToString(),
194
-                                                 read["SequenceNumber"].ToString(),
195
-                                                 read["ProductDescription"].ToString());
196
-                                    sw.WriteLine(ExportRow);
197
-                                    var ExportEvent = new EventLog();
198
-                                    ExportEvent.EventType = VendorEvent.VendorEventType.ExportVoucher;
199
-                                    ExportEvent.VoucherId = int.Parse(read["Id"].ToString());
200
-                                    ExportEvent.Retry = (read["Exports"].ToString() != "0");
201
-                                    LogEvents.Add(ExportEvent);
185
+                                    while (read.Read())
186
+                                    {
187
+                                        string DecryptedPIN = Utility.TripleDESDecrypt(read["EncryptedPIN"].ToString(), Globals.SessionVoucherKey).ToString();
188
+                                        string ExportRow = string.Format("{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}",
189
+                                                     read["Id"].ToString(),
190
+                                                     DateTime.Parse(read["ExpiryDate"].ToString()).ToString("dd/MM/yyyy"),
191
+                                                     read["Serial"].ToString(),
192
+                                                     DecryptedPIN,
193
+                                                     read["FaceValue"].ToString(),
194
+                                                     read["BatchId"].ToString(),
195
+                                                     read["SequenceNumber"].ToString(),
196
+                                                     read["ProductDescription"].ToString());
197
+                                        sw.WriteLine(ExportRow);
198
+                                        var ExportEvent = new EventLog();
199
+                                        ExportEvent.EventType = VendorEvent.VendorEventType.ExportVoucher;
200
+                                        ExportEvent.VoucherId = int.Parse(read["Id"].ToString());
201
+                                        ExportEvent.Retry = (read["Exports"].ToString() != "0");
202
+                                        LogEvents.Add(ExportEvent);
203
+                                    }
202 204
                                 }
203 205
                             }
204 206
                         }
205
-                        Utility.LogBulkEvents(LogEvents);
206 207
                     }
208
+                    Utility.LogBulkEvents(Globals.DBConnection, LogEvents);
207 209
                 }
208 210
                 MessageBox.Show("Vouchers Exported");
209 211
                 this.Close();

+ 3 - 0
BulkPrinting/BulkPrinting/Globals.cs

@@ -10,6 +10,9 @@ namespace BulkPrinting
10 10
 {
11 11
     public static class Globals
12 12
     {
13
+        public static string MaxDBPath;
14
+        public static string MaxDBFilePath;
15
+        public static readonly object DBWriteLock = new object();
13 16
         public static SessionModes SessionMode;
14 17
         public static OKResponse SessionData;
15 18
         public static string HDDSerialNumber;

+ 142 - 116
BulkPrinting/BulkPrinting/Migrations.cs

@@ -6,133 +6,159 @@ namespace BulkPrinting
6 6
 {
7 7
     class Migrations
8 8
     {
9
-        public static void CheckMigrations() {
10
-
11
-            string sql;
12
-            SQLiteCommand Command;
13
-            sql = "SELECT Value FROM Parameters WHERE Key = 'Migration'";
14
-            Command = new SQLiteCommand(sql, Globals.DBConnection);
15
-            var result = Command.ExecuteScalar();
9
+        public static void CheckMigrations(SQLiteConnection conn) {
10
+            var result = Utility.DBExecuteScalar(conn, "SELECT Value FROM Parameters WHERE Key = 'Migration'");
11
+            int startingMigration;
12
+            if (result == null)
13
+            {
14
+                startingMigration = 0;
15
+            }
16
+            else if (! int.TryParse((string)result, out startingMigration))
17
+            {
18
+                throw new Exception(String.Format("Invalid migration value: {0}", result));
19
+            }
16 20
 
17
-            if (result == null) {
18
-                Migration1();
21
+            if (startingMigration > 2)
22
+            {
23
+                throw new Exception("Database is for a newer version of this application. Please upgrade and try again.");
24
+            }
25
+            if (startingMigration < 1) {
26
+                Migration1(conn);
27
+            }
28
+            if (startingMigration < 2)
29
+            {
30
+                Migration2(conn);
19 31
             }
20 32
             //Add further migration executions here - Migration = '1', '2', '3' etc
21 33
 
22 34
             return;
23 35
         }
24 36
 
25
-        public static bool InitialVersion() {
26
-            string MaxDBPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Configuration.MaxDataPathName);
27
-            string MaxDBFilePath = Path.Combine(MaxDBPath, Configuration.MaxDBFileName);
28
-            Globals.DBConnection = new SQLiteConnection(string.Format("Data Source={0};", MaxDBFilePath));
29
-            Globals.DBConnection.SetPassword(Globals.SessionDatabasePassword);
30
-            Globals.DBConnection.Open();
31
-            string sql = "CREATE TABLE Batch (" +
32
-                "Id INT," +
33
-                "OrderDate DATETIME," +
34
-                "OrderGuid VARCHAR(36), " +
35
-                "OrderReference VARCHAR(20) NOT NULL," +
36
-                "NetworkId INT," +
37
-                "NetworkName VARCHAR(20) NOT NULL," +
38
-                "ProductId INT," +
39
-                "ProductDescription VARCHAR(50)," +
40
-                "VoucherType INT," +
41
-                "FaceValue DECIMAL(10,2)," +
42
-                "DiscountPercentage DECIMAL(10,2)," +
43
-                "RequestedQuantity INT," +
44
-                "DeliveredQuantity INT," +
45
-                "Cost DECIMAL(10,2)," +
46
-                "ReadyForDownload BOOLEAN)";
47
-
48
-            SQLiteCommand command = new SQLiteCommand(sql, Globals.DBConnection);
49
-            command.ExecuteNonQuery();
50
-
51
-            sql = "CREATE TABLE Voucher(" +
52
-                "Id INT ," +
53
-                "SequenceNumber INT," +
54
-                "ExpiryDate DATE," +
55
-                "Serial VARCHAR(50)," +
56
-                "EncryptedPIN VARCHAR(50)," +
57
-                "BatchId INT)";
58
-
59
-            command = new SQLiteCommand(sql, Globals.DBConnection);
60
-            command.ExecuteNonQuery();
61
-
62
-            sql = "CREATE TABLE SessionData(" +
63
-                "Key VARCHAR(20)," +
64
-                "Value TEXT)";
65
-
66
-            command = new SQLiteCommand(sql, Globals.DBConnection);
67
-            command.ExecuteNonQuery();
68
-
69
-            sql = "CREATE TABLE Parameters(" +
70
-                "Key VARCHAR(20)," +
71
-                "Value TEXT)";
72
-
73
-            command = new SQLiteCommand(sql, Globals.DBConnection);
74
-            command.ExecuteNonQuery();
75
-
76
-            sql = "CREATE TABLE AccessControlTracking (" +
77
-                "UserID INT NOT NULL," +
78
-                "Permission VARCHAR(20)," +
79
-                "Date DATETIME," +
80
-                "CurrentUsage DECIMAL)";
81
-
82
-            command = new SQLiteCommand(sql, Globals.DBConnection);
83
-            command.ExecuteNonQuery();
84
-
85
-            sql = "CREATE TABLE Logs(" +
86
-                "Id INTEGER PRIMARY KEY," +
87
-                "UserId INT NOT NULL," +
88
-                "VoucherId INT," +
89
-                "EventDate DATETIME," +
90
-                "EventType VARCHAR(50)," +
91
-                "Retry BOOLEAN)";
92
-
93
-            command = new SQLiteCommand(sql, Globals.DBConnection);
94
-            command.ExecuteNonQuery();
95
-
96
-            sql = "CREATE TABLE Orders(" +
97
-                "Id INTEGER PRIMARY KEY," +
98
-                "UserId INT NOT NULL," +
99
-                "UserName VARCHAR(50)," +
100
-                "OrderDate DATETIME," +
101
-                "OrderCost DECIMAL," +
102
-                "BalanceAfterOrder DECIMAL)";
103
-
104
-            command = new SQLiteCommand(sql, Globals.DBConnection);
105
-            command.ExecuteNonQuery();
106
-
107
-            sql = "CREATE TABLE OrderedItems(" +
108
-                "Id INTEGER PRIMARY KEY," +
109
-                "OrderId INT NOT NULL," +
110
-                "Cost DECIMAL," +
111
-                "Quantity INT," +
112
-                "Description VARCHAR(50)," +
113
-                "ProductId)";
114
-
115
-            command = new SQLiteCommand(sql, Globals.DBConnection);
116
-            command.ExecuteNonQuery();
117
-            
118
-            return true; //Initial Migration doesn't trigger any others, as a Migration check is performed later in the login
37
+        private static bool ApplyMigrationQueries(SQLiteConnection conn, params string[] queries)
38
+        {
39
+            lock (Globals.DBWriteLock)
40
+            {
41
+                using (var trans = conn.BeginTransaction())
42
+                {
43
+                    foreach (var query in queries)
44
+                    {
45
+                        using (var command = new SQLiteCommand(query, conn, trans))
46
+                        {
47
+                            command.ExecuteNonQuery();
48
+                        }
49
+                    }
50
+                    trans.Commit();
51
+                }
52
+            }
53
+            return true;
119 54
         }
120 55
 
121
-        public static bool Migration1 (){
122
-            string sql = "ALTER TABLE Orders ADD COLUMN InternalReference VARCHAR(32)";
123
-            SQLiteCommand command = new SQLiteCommand(sql, Globals.DBConnection);
124
-            command.ExecuteNonQuery();
125
-
126
-            sql = "ALTER TABLE Batch ADD COLUMN InternalReference VARCHAR(32)";
127
-            command = new SQLiteCommand(sql, Globals.DBConnection);
128
-            command.ExecuteNonQuery();
56
+        public static bool InitialVersion(SQLiteConnection conn) {
57
+            return ApplyMigrationQueries(
58
+                conn,
59
+                "CREATE TABLE Batch (" +
60
+                    "Id INT," +
61
+                    "OrderDate DATETIME," +
62
+                    "OrderGuid VARCHAR(36), " +
63
+                    "OrderReference VARCHAR(20) NOT NULL," +
64
+                    "NetworkId INT," +
65
+                    "NetworkName VARCHAR(20) NOT NULL," +
66
+                    "ProductId INT," +
67
+                    "ProductDescription VARCHAR(50)," +
68
+                    "VoucherType INT," +
69
+                    "FaceValue DECIMAL(10,2)," +
70
+                    "DiscountPercentage DECIMAL(10,2)," +
71
+                    "RequestedQuantity INT," +
72
+                    "DeliveredQuantity INT," +
73
+                    "Cost DECIMAL(10,2)," +
74
+                    "ReadyForDownload BOOLEAN)",
75
+
76
+                "CREATE TABLE Voucher(" +
77
+                    "Id INT ," +
78
+                    "SequenceNumber INT," +
79
+                    "ExpiryDate DATE," +
80
+                    "Serial VARCHAR(50)," +
81
+                    "EncryptedPIN VARCHAR(50)," +
82
+                    "BatchId INT)",
83
+
84
+                "CREATE TABLE SessionData(" +
85
+                    "Key VARCHAR(20)," +
86
+                    "Value TEXT)",
87
+
88
+                "CREATE TABLE Parameters(" +
89
+                    "Key VARCHAR(20)," +
90
+                    "Value TEXT)",
91
+
92
+                "CREATE TABLE AccessControlTracking (" +
93
+                    "UserID INT NOT NULL," +
94
+                    "Permission VARCHAR(20)," +
95
+                    "Date DATETIME," +
96
+                    "CurrentUsage DECIMAL)",
97
+
98
+                "CREATE TABLE Logs(" +
99
+                    "Id INTEGER PRIMARY KEY," +
100
+                    "UserId INT NOT NULL," +
101
+                    "VoucherId INT," +
102
+                    "EventDate DATETIME," +
103
+                    "EventType VARCHAR(50)," +
104
+                    "Retry BOOLEAN)",
105
+
106
+                "CREATE TABLE Orders(" +
107
+                    "Id INTEGER PRIMARY KEY," +
108
+                    "UserId INT NOT NULL," +
109
+                    "UserName VARCHAR(50)," +
110
+                    "OrderDate DATETIME," +
111
+                    "OrderCost DECIMAL," +
112
+                    "BalanceAfterOrder DECIMAL)",
113
+
114
+                "CREATE TABLE OrderedItems(" +
115
+                    "Id INTEGER PRIMARY KEY," +
116
+                    "OrderId INT NOT NULL," +
117
+                    "Cost DECIMAL," +
118
+                    "Quantity INT," +
119
+                    "Description VARCHAR(50)," +
120
+                    "ProductId)"
121
+            );
122
+        }
129 123
 
130
-            //First Migration value - future values to be updated
131
-            sql = "INSERT INTO Parameters (Key, Value) VALUES ('Migration','1')";
132
-            command = new SQLiteCommand(sql, Globals.DBConnection);
133
-            command.ExecuteNonQuery();
124
+        public static bool Migration1 (SQLiteConnection conn){
125
+            return ApplyMigrationQueries(
126
+                conn,
127
+                "ALTER TABLE Orders ADD COLUMN InternalReference VARCHAR(32)",
128
+                "ALTER TABLE Batch ADD COLUMN InternalReference VARCHAR(32)",
129
+                "INSERT INTO Parameters (Key, Value) VALUES ('Migration','1')"
130
+            );
131
+        }
134 132
 
135
-            return true;
133
+        public static bool Migration2(SQLiteConnection conn)
134
+        {
135
+            return ApplyMigrationQueries(
136
+                conn,
137
+                "ALTER TABLE Batch ADD COLUMN Downloaded BOOLEAN",
138
+                "CREATE UNIQUE INDEX Batch_Id ON Batch(Id)",
139
+                "CREATE INDEX Batch_OrderDate ON Batch(OrderDate)",
140
+                "CREATE INDEX Batch_Downloaded_Id ON Batch(Downloaded, Id)",
141
+                "CREATE UNIQUE INDEX Voucher_Id ON Voucher(Id)",
142
+                "CREATE UNIQUE INDEX Voucher_BatchId_SequenceNumber ON Voucher(BatchId, SequenceNumber)",
143
+                "CREATE UNIQUE INDEX SessionData_Key ON SessionData(Key)",
144
+                "CREATE UNIQUE INDEX Parameters_Key ON Parameters(Key)",
145
+                "CREATE INDEX Orders_OrderDate ON Orders(OrderDate)",
146
+                "CREATE INDEX OrderedItems_OrderId ON OrderedItems(OrderId)",
147
+                "UPDATE Parameters SET Value='2' WHERE Key='Migration'",
148
+                "UPDATE Batch SET Downloaded=(ReadyForDownload=1 AND DeliveredQuantity<=COALESCE((SELECT COUNT(*) FROM Voucher WHERE Voucher.BatchId=Batch.Id), 0))",
149
+                "INSERT INTO Parameters (Key, Value) VALUES ('LastSyncedBatchId', '0')",
150
+                "CREATE TABLE Logs_New (" +
151
+                    "Id INTEGER PRIMARY KEY AUTOINCREMENT," +
152
+                    "UserId INT NOT NULL," +
153
+                    "VoucherId INT," +
154
+                    "EventDate DATETIME," +
155
+                    "EventType VARCHAR(50)," +
156
+                    "Retry BOOLEAN)",
157
+                "INSERT INTO Logs_New (Id, UserId, VoucherId, EventDate, EventType, Retry) " +
158
+                    "SELECT Id, UserId, VoucherId, EventDate, EventType, Retry FROM Logs",
159
+                "DROP TABLE Logs",
160
+                "ALTER TABLE Logs_New RENAME TO Logs"
161
+            );
136 162
         }
137 163
     }
138 164
 }

+ 65 - 61
BulkPrinting/BulkPrinting/OrderForm.cs

@@ -1,20 +1,10 @@
1 1
 using System;
2 2
 using System.Collections.Generic;
3
-using System.Collections.ObjectModel;
4 3
 using System.ComponentModel;
5
-using System.Data;
6
-using System.Drawing;
7
-using System.Linq;
8
-using System.Text;
9
-using System.Threading.Tasks;
10
-using System.Windows.Forms;
11
-using System.IO;
12
-using System.Net;
13
-using Newtonsoft.Json;
14
-using Newtonsoft.Json.Serialization;
4
+using System.Data.SQLite;
15 5
 using System.Runtime.CompilerServices;
16 6
 using System.Threading;
17
-using System.Data.SQLite;
7
+using System.Windows.Forms;
18 8
 
19 9
 namespace BulkPrinting
20 10
 {
@@ -119,31 +109,38 @@ namespace BulkPrinting
119 109
             DialogResult PlaceOrder = MessageBox.Show(OrderReviewMessage, "Proceed?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
120 110
             if (PlaceOrder == DialogResult.Yes) {
121 111
                 string InternalReference = Utility.GetNextInternalReference();
122
-                string Sql = "INSERT INTO Orders (UserId,UserName,OrderDate,OrderCost,BalanceAfterOrder,InternalReference) VALUES (@userid,@username,datetime('now'),@ordercost,@balanceafterorder,@internalreference)";
123
-                SQLiteCommand Command = new SQLiteCommand(Sql, Globals.DBConnection);
124
-                Command.Parameters.Add(new SQLiteParameter("@userid", Globals.SessionData.Credentials.Payload.User.Id));
125
-                Command.Parameters.Add(new SQLiteParameter("@username", Globals.SessionData.Credentials.Payload.User.FirstName + " " + Globals.SessionData.Credentials.Payload.User.Surname));
126
-                Command.Parameters.Add(new SQLiteParameter("@ordercost", TotalCost));
127
-                Command.Parameters.Add(new SQLiteParameter("@balanceafterorder", Globals.SessionData.Credentials.Payload.User.Account.Balance - TotalCost));
128
-                Command.Parameters.Add(new SQLiteParameter("@internalreference", InternalReference));
129
-                Command.ExecuteNonQuery();
112
+                Utility.DBExecuteNonQuery(Globals.DBConnection,
113
+                    "INSERT INTO Orders (UserId,UserName,OrderDate,OrderCost,BalanceAfterOrder,InternalReference) VALUES (@userid,@username,datetime('now'),@ordercost,@balanceafterorder,@internalreference)",
114
+                        new SQLiteParameter("@userid", Globals.SessionData.Credentials.Payload.User.Id),
115
+                        new SQLiteParameter("@username", Globals.SessionData.Credentials.Payload.User.FirstName + " " + Globals.SessionData.Credentials.Payload.User.Surname),
116
+                        new SQLiteParameter("@ordercost", TotalCost),
117
+                        new SQLiteParameter("@balanceafterorder", Globals.SessionData.Credentials.Payload.User.Account.Balance - TotalCost),
118
+                        new SQLiteParameter("@internalreference", InternalReference));
130 119
 
131
-                Sql = "SELECT MAX(Id) FROM Orders";
132
-                Command = new SQLiteCommand(Sql, Globals.DBConnection);
133
-                int OrderId = int.Parse(Command.ExecuteScalar().ToString()); 
120
+                int OrderId = int.Parse(Utility.DBExecuteScalar(Globals.DBConnection, "SELECT MAX(Id) FROM Orders").ToString());
134 121
 
135
-                Sql = "INSERT INTO OrderedItems (OrderId,Cost,Quantity,Description,ProductId) VALUES (@orderId,@cost,@quantity,@description,@productid)";
136
-                for (int i = 0; i < this.SelectedProducts.Count; i++)
122
+                lock (Globals.DBWriteLock)
137 123
                 {
138
-                    OrderItem OrderedItem = this.SelectedProducts[i];
139
-                    decimal ItemCost = OrderedItem.Quantity * OrderedItem.FaceValue * (1 - (OrderedItem.DiscountPercentage / 100));
140
-                    Command = new SQLiteCommand(Sql, Globals.DBConnection);
141
-                    Command.Parameters.Add(new SQLiteParameter("@orderId", OrderId));
142
-                    Command.Parameters.Add(new SQLiteParameter("@cost", ItemCost));
143
-                    Command.Parameters.Add(new SQLiteParameter("@quantity", OrderedItem.Quantity));
144
-                    Command.Parameters.Add(new SQLiteParameter("@description", OrderedItem.ProductDescription));
145
-                    Command.Parameters.Add(new SQLiteParameter("@productid", OrderedItem.ProductId));
146
-                    Command.ExecuteNonQuery();
124
+                    using (var trans = Globals.DBConnection.BeginTransaction())
125
+                    {
126
+                        var Sql = "INSERT INTO OrderedItems (OrderId,Cost,Quantity,Description,ProductId) VALUES (@orderId,@cost,@quantity,@description,@productid)";
127
+                        using (var Command = new SQLiteCommand(Sql, Globals.DBConnection, trans))
128
+                        {
129
+                            for (int i = 0; i < this.SelectedProducts.Count; i++)
130
+                            {
131
+                                OrderItem OrderedItem = this.SelectedProducts[i];
132
+                                decimal ItemCost = OrderedItem.Quantity * OrderedItem.FaceValue * (1 - (OrderedItem.DiscountPercentage / 100));
133
+                                Command.Parameters.Clear();
134
+                                Command.Parameters.AddWithValue("@orderId", OrderId);
135
+                                Command.Parameters.AddWithValue("@cost", ItemCost);
136
+                                Command.Parameters.AddWithValue("@quantity", OrderedItem.Quantity);
137
+                                Command.Parameters.AddWithValue("@description", OrderedItem.ProductDescription);
138
+                                Command.Parameters.AddWithValue("@productid", OrderedItem.ProductId);
139
+                                Command.ExecuteNonQuery();
140
+                            }
141
+                        }
142
+                        trans.Commit();
143
+                    }
147 144
                 }
148 145
 
149 146
                 this.Hide();
@@ -152,37 +149,44 @@ namespace BulkPrinting
152 149
                 ProgressDialog Progress = new ProgressDialog();
153 150
                 Progress.Show();
154 151
                 Thread t = new Thread(() => {
155
-                    Progress.UpdateProgressText("Please wait...");
156
-                    Progress.UpdateProgressBar(0);
157
-                    for (int i=0; i<this.SelectedProducts.Count; i++)
152
+                    var conn = Globals.DBConnection;
153
+                    //using (var conn = Utility.OpenDBConnection())
158 154
                     {
159
-                        OrderItem OrderedItem = this.SelectedProducts[i];
160
-                        Progress.UpdateProgressText("Placing order for " + OrderedItem.Quantity.ToString() + " of " + OrderedItem.ProductDescription + "...");
161
-                        OrderPlacementData OrderData = new OrderPlacementData();
162
-                        OrderData.ProductId = OrderedItem.ProductId;
163
-                        OrderData.Quantity = OrderedItem.Quantity;
164
-                        OrderData.CustomerReference = CustomerReference;
165
-                        OrderData.InternalReference = InternalReference;
166
-                        BatchListing OrderedBatch = new BatchListing();
167
-                        bool OrderResult = Utility.RESTRequest<OrderPlacementData, BatchListing>(OrderData, ref OrderedBatch, "/api/batches/");
168
-                        if (OrderedBatch.Batch == null) {
169
-                            string ErrorMessage = "An error occurred while attempting to order " + OrderedItem.Quantity.ToString() + " of " + OrderedItem.ProductDescription;
170
-                            if (i < (SelectedProducts.Count - 1)){
171
-                                ErrorMessage += "\nPress OK to continue attempting to order remaining items.";
155
+                        Progress.UpdateProgressText("Please wait...");
156
+                        Progress.UpdateProgressBar(0);
157
+                        for (int i = 0; i < this.SelectedProducts.Count; i++)
158
+                        {
159
+                            OrderItem OrderedItem = this.SelectedProducts[i];
160
+                            Progress.UpdateProgressText("Placing order for " + OrderedItem.Quantity.ToString() + " of " + OrderedItem.ProductDescription + "...");
161
+                            OrderPlacementData OrderData = new OrderPlacementData();
162
+                            OrderData.ProductId = OrderedItem.ProductId;
163
+                            OrderData.Quantity = OrderedItem.Quantity;
164
+                            OrderData.CustomerReference = CustomerReference;
165
+                            OrderData.InternalReference = InternalReference;
166
+                            BatchListing OrderedBatch = new BatchListing();
167
+                            bool OrderResult = Utility.RESTRequest<OrderPlacementData, BatchListing>(OrderData, ref OrderedBatch, "/api/batches/");
168
+                            if (OrderedBatch.Batch == null)
169
+                            {
170
+                                string ErrorMessage = "An error occurred while attempting to order " + OrderedItem.Quantity.ToString() + " of " + OrderedItem.ProductDescription;
171
+                                if (i < (SelectedProducts.Count - 1))
172
+                                {
173
+                                    ErrorMessage += "\nPress OK to continue attempting to order remaining items.";
174
+                                }
175
+                                MessageBox.Show(ErrorMessage, "Error Ordering", MessageBoxButtons.OK, MessageBoxIcon.Error);
176
+                                continue;
172 177
                             }
173
-                            MessageBox.Show(ErrorMessage ,"Error Ordering",MessageBoxButtons.OK,MessageBoxIcon.Error);
174
-                            continue;
178
+                            //TODO: Handle failed order
179
+                            Utility.SaveBatch(conn, OrderedBatch.Batch);
180
+                            SourceForm.NewBatchAvailable();
181
+                            Globals.SessionData.Credentials.Payload.User.Account.Balance = OrderedBatch.RemainingBalance;
182
+                            Utility.AddUserUsage(conn, UserLimits.UserLimitTypes.BulkOrder, OrderedBatch.Batch.Cost);
183
+                            Progress.UpdateProgressBar((int)Math.Round(100 * (((decimal)i + 1) / (decimal)SelectedProducts.Count)));
184
+                            Thread.Sleep(50);
175 185
                         }
176
-                        //TODO: Handle failed order
177
-                        Utility.DownloadBatch(OrderedBatch.Batch);
178
-                        Globals.SessionData.Credentials.Payload.User.Account.Balance = OrderedBatch.RemainingBalance;
179
-                        Utility.AddUserUsage(UserLimits.UserLimitTypes.BulkOrder, OrderedBatch.Batch.Cost);
180
-                        Progress.UpdateProgressBar((int)Math.Round(100 * (((decimal)i+1)/(decimal)SelectedProducts.Count)));
181
-                        Thread.Sleep(50);
182
-                    }
183 186
 
184
-                    Progress.Invoke((Action)(() => Progress.Close()));
185
-                    this.Invoke((Action)(() => { SourceForm.PopulateGrid(); this.Close(); }));
187
+                        Progress.Invoke((Action)(() => Progress.Close()));
188
+                        this.Invoke((Action)(() => { SourceForm.PopulateGrid(); this.Close(); }));
189
+                    }
186 190
                 });
187 191
                 t.Start();
188 192
             }

+ 58 - 55
BulkPrinting/BulkPrinting/OrderReport.cs

@@ -36,30 +36,31 @@ namespace BulkPrinting
36 36
             dgvOrderReport.Columns.Add("DeliveredQuantity", "Delivered Quantity");
37 37
             string Sql = "Select o.Id,o.InternalReference,o.UserId,o.UserName,o.OrderDate,oi.Description,o.OrderCost,o.BalanceAfterOrder,oi.Cost,b.RequestedQuantity,b.DeliveredQuantity From Orders o LEFT JOIN OrderedItems oi on oi.OrderId = o.Id LEFT JOIN Batch b ON b.InternalReference = o.InternalReference AND b.ProductId = oi.ProductId WHERE o.OrderDate BETWEEN @startdate AND @enddate";
38 38
 
39
-            SQLiteCommand Command = new SQLiteCommand(Sql, Globals.DBConnection);
40
-            CultureInfo IVC = CultureInfo.InvariantCulture;
41
-            Command.Parameters.Add(new SQLiteParameter("@startdate", dtpStartDate.Value.ToString("yyyy-MM-dd 00:00:00", IVC)));
42
-            Command.Parameters.Add(new SQLiteParameter("@enddate", dtpEndDate.Value.ToString("yyyy-MM-dd 23:59:59", IVC)));
43
-
44
-            using (SQLiteDataReader read = Command.ExecuteReader())
39
+            using (var Command = new SQLiteCommand(Sql, Globals.DBConnection))
45 40
             {
46
-                while (read.Read())
41
+                CultureInfo IVC = CultureInfo.InvariantCulture;
42
+                Command.Parameters.AddWithValue("@startdate", dtpStartDate.Value.ToString("yyyy-MM-dd 00:00:00", IVC));
43
+                Command.Parameters.AddWithValue("@enddate", dtpEndDate.Value.ToString("yyyy-MM-dd 23:59:59", IVC));
44
+
45
+                using (SQLiteDataReader read = Command.ExecuteReader())
47 46
                 {
48
-                    dgvOrderReport.Rows.Add(new object[] {
49
-                    read.GetValue(1).ToString(),
50
-                    read.GetValue(2).ToString(),
51
-                    read.GetValue(3).ToString(),
52
-                    read.GetValue(4).ToString(),
53
-                    read.GetValue(5).ToString(),
54
-                    read.GetValue(6).ToString(),
55
-                    read.GetValue(7).ToString(),
56
-                    read.GetValue(8).ToString(),
57
-                    read.GetValue(9).ToString(),
58
-                    read.GetValue(10).ToString(),
59
-                });
47
+                    while (read.Read())
48
+                    {
49
+                        dgvOrderReport.Rows.Add(new object[] {
50
+                            read.GetValue(1).ToString(),
51
+                            read.GetValue(2).ToString(),
52
+                            read.GetValue(3).ToString(),
53
+                            read.GetValue(4).ToString(),
54
+                            read.GetValue(5).ToString(),
55
+                            read.GetValue(6).ToString(),
56
+                            read.GetValue(7).ToString(),
57
+                            read.GetValue(8).ToString(),
58
+                            read.GetValue(9).ToString(),
59
+                            read.GetValue(10).ToString(),
60
+                        });
61
+                    }
60 62
                 }
61 63
             }
62
-
63 64
         }
64 65
 
65 66
         private void OrderReport_Load(object sender, EventArgs e)
@@ -105,49 +106,51 @@ namespace BulkPrinting
105 106
         private void btnPrint_Click(object sender, EventArgs e)
106 107
         {
107 108
             string Sql = "Select o.Id,o.OrderDate,o.InternalReference,o.UserName,o.OrderCost,o.BalanceAfterOrder,oi.Description,oi.Cost,b.RequestedQuantity,b.DeliveredQuantity From Orders o LEFT JOIN OrderedItems oi on oi.OrderId = o.Id LEFT JOIN Batch b ON b.InternalReference = o.InternalReference AND b.ProductId = oi.ProductId WHERE o.OrderDate BETWEEN @startdate AND @enddate ORDER BY o.Id";
108
-            SQLiteCommand Command = new SQLiteCommand(Sql, Globals.DBConnection);
109
-            CultureInfo IVC = CultureInfo.InvariantCulture;
110
-            Command.Parameters.Add(new SQLiteParameter("@startdate", dtpStartDate.Value.ToString("yyyy-MM-dd 00:00:00", IVC)));
111
-            Command.Parameters.Add(new SQLiteParameter("@enddate", dtpEndDate.Value.ToString("yyyy-MM-dd 23:59:59", IVC)));
112
-
113
-            int CurrentId;
114
-            int LastId = -1;
115
-            List<OrderList> Orders = new List<OrderList>();
116
-            OrderList IndividualOrder = new OrderList();
117
-            using (SQLiteDataReader read = Command.ExecuteReader())
109
+            using (var Command = new SQLiteCommand(Sql, Globals.DBConnection))
118 110
             {
119
-                while (read.Read())
111
+                CultureInfo IVC = CultureInfo.InvariantCulture;
112
+                Command.Parameters.AddWithValue("@startdate", dtpStartDate.Value.ToString("yyyy-MM-dd 00:00:00", IVC));
113
+                Command.Parameters.AddWithValue("@enddate", dtpEndDate.Value.ToString("yyyy-MM-dd 23:59:59", IVC));
114
+
115
+                int CurrentId;
116
+                int LastId = -1;
117
+                List<OrderList> Orders = new List<OrderList>();
118
+                OrderList IndividualOrder = new OrderList();
119
+                using (SQLiteDataReader read = Command.ExecuteReader())
120 120
                 {
121
-                    CurrentId = int.Parse(read.GetValue(0).ToString());
122
-                    if (CurrentId != LastId)
121
+                    while (read.Read())
123 122
                     {
124
-                        if (IndividualOrder.OrderReference != null)
123
+                        CurrentId = int.Parse(read.GetValue(0).ToString());
124
+                        if (CurrentId != LastId)
125 125
                         {
126
-                            Orders.Add(IndividualOrder);
126
+                            if (IndividualOrder.OrderReference != null)
127
+                            {
128
+                                Orders.Add(IndividualOrder);
129
+                            }
130
+                            IndividualOrder = new OrderList();
131
+                            IndividualOrder.OrderLines = new List<OrderReportLine>();
132
+                            IndividualOrder.OrderDate = read.GetValue(1).ToString();
133
+                            IndividualOrder.OrderDate = IndividualOrder.OrderDate.Substring(0, IndividualOrder.OrderDate.IndexOf(" "));
134
+                            IndividualOrder.OrderReference = read.GetValue(2).ToString();
135
+                            IndividualOrder.User = read.GetValue(3).ToString();
136
+                            IndividualOrder.OrderCost = read.GetValue(4).ToString();
137
+                            IndividualOrder.Balance = read.GetValue(5).ToString();
138
+                            LastId = CurrentId;
127 139
                         }
128
-                        IndividualOrder = new OrderList();
129
-                        IndividualOrder.OrderLines = new List<OrderReportLine>();
130
-                        IndividualOrder.OrderDate = read.GetValue(1).ToString();
131
-                        IndividualOrder.OrderDate = IndividualOrder.OrderDate.Substring(0, IndividualOrder.OrderDate.IndexOf(" "));
132
-                        IndividualOrder.OrderReference = read.GetValue(2).ToString();
133
-                        IndividualOrder.User = read.GetValue(3).ToString();
134
-                        IndividualOrder.OrderCost = read.GetValue(4).ToString();
135
-                        IndividualOrder.Balance = read.GetValue(5).ToString();
136
-                        LastId = CurrentId;
140
+                        OrderReportLine OrderLine = new OrderReportLine();
141
+                        OrderLine.OrderItem = read.GetValue(6).ToString();
142
+                        OrderLine.Cost = read.GetValue(7).ToString();
143
+                        OrderLine.QtyOrdered = read.GetValue(8).ToString();
144
+                        OrderLine.QtyDelivered = read.GetValue(9).ToString();
145
+                        IndividualOrder.OrderLines.Add(OrderLine);
146
+                    }
147
+                    if (IndividualOrder.OrderReference != null)
148
+                    {
149
+                        Orders.Add(IndividualOrder);
137 150
                     }
138
-                    OrderReportLine OrderLine = new OrderReportLine();
139
-                    OrderLine.OrderItem = read.GetValue(6).ToString();
140
-                    OrderLine.Cost = read.GetValue(7).ToString();
141
-                    OrderLine.QtyOrdered = read.GetValue(8).ToString();
142
-                    OrderLine.QtyDelivered = read.GetValue(9).ToString();
143
-                    IndividualOrder.OrderLines.Add(OrderLine);
144
-                }
145
-                if (IndividualOrder.OrderReference != null)
146
-                {
147
-                    Orders.Add(IndividualOrder);
148 151
                 }
152
+                Printer.PrintOrderReport(Orders);
149 153
             }
150
-            Printer.PrintOrderReport(Orders);
151 154
         }
152 155
 
153 156
         private void label1_Click(object sender, EventArgs e)

+ 18 - 14
BulkPrinting/BulkPrinting/PrintAlignmentDialog.cs

@@ -97,13 +97,12 @@ namespace BulkPrinting
97 97
             }
98 98
             else if (NumVouchers != null)
99 99
             {
100
-                string Sql = "SELECT MIN(v.SequenceNumber) FROM Voucher v " +
101
-                    "LEFT JOIN Logs l ON v.Id = l.VoucherId AND l.EventType = @eventtype " +
102
-                    "WHERE v.BatchId = @batchid AND l.id IS NULL";
103
-                SQLiteCommand Command = new SQLiteCommand(Sql, Globals.DBConnection);
104
-                Command.Parameters.Add(new SQLiteParameter("@eventtype", VendorEvent.VendorEventType.PrintVoucher));
105
-                Command.Parameters.Add(new SQLiteParameter("@batchid", BatchID));
106
-                FirstVoucherSequenceNumber = Convert.ToInt32(Command.ExecuteScalar());
100
+                FirstVoucherSequenceNumber = Convert.ToInt32(Utility.DBExecuteScalar(Globals.DBConnection,
101
+                    "SELECT MIN(v.SequenceNumber) FROM Voucher v " +
102
+                        "LEFT JOIN Logs l ON v.Id = l.VoucherId AND l.EventType = @eventtype " +
103
+                        "WHERE v.BatchId = @batchid AND l.id IS NULL",
104
+                    new SQLiteParameter("@eventtype", VendorEvent.VendorEventType.PrintVoucher),
105
+                    new SQLiteParameter("@batchid", BatchID)));
107 106
                 LastVoucherSequenceNumber = FirstVoucherSequenceNumber + (int)NumVouchers - 1;
108 107
             }
109 108
             else {
@@ -118,13 +117,18 @@ namespace BulkPrinting
118 117
             this.Enabled = false;
119 118
             Thread t = new Thread(() =>
120 119
             {
121
-                Utility.PrintVouchers(this.BatchID, FirstVoucherSequenceNumber, LastVoucherSequenceNumber);
122
-                Globals.OpenBatches.Remove(BatchID);
123
-                this.Invoke((Action)(() => {
124
-                    BatchForm.PopulateGrid();
125
-                    this.Enabled = true;
126
-                    this.Close();
127
-                }));
120
+                var conn = Globals.DBConnection;
121
+                //using (var conn = Utility.OpenDBConnection())
122
+                {
123
+                    Utility.PrintVouchers(conn, BatchID, FirstVoucherSequenceNumber, LastVoucherSequenceNumber);
124
+                    Globals.OpenBatches.Remove(BatchID);
125
+                    this.Invoke((Action)(() =>
126
+                    {
127
+                        BatchForm.PopulateGrid();
128
+                        this.Enabled = true;
129
+                        this.Close();
130
+                    }));
131
+                }
128 132
             });
129 133
             t.Start();
130 134
 

+ 4 - 4
BulkPrinting/BulkPrinting/PrintForm.cs

@@ -75,12 +75,12 @@ namespace BulkPrinting
75 75
                     return;
76 76
                 }
77 77
             }
78
-            string Sql = "SELECT FaceValue FROM Batch WHERE Id = @id";
79
-            SQLiteCommand Command = new SQLiteCommand(Sql, Globals.DBConnection);
80
-            Command.Parameters.Add(new SQLiteParameter("@id", BatchID));
81 78
 
82 79
             VoucherCount = numNumVouchers.Value;
83
-            decimal TotalVoucherValue = VoucherCount * (decimal)Command.ExecuteScalar();
80
+            decimal TotalVoucherValue = VoucherCount * (decimal)Utility.DBExecuteScalar(Globals.DBConnection,
81
+                "SELECT FaceValue FROM Batch WHERE Id = @id",
82
+                new SQLiteParameter("@id", BatchID));
83
+
84 84
             if (Globals.SessionMode == SessionModes.Online)
85 85
             {
86 86
                 if (!Utility.IsValueWithinRemainingUserLimit(UserLimits.UserLimitTypes.OnlinePrint, TotalVoucherValue))

+ 0 - 2
BulkPrinting/BulkPrinting/Printer.cs

@@ -202,12 +202,10 @@ namespace BulkPrinting
202 202
         private static PrintDocument pdoc = null;
203 203
         private static List<OrderList> OrderReportList;
204 204
         private static int ListLoc = 0;
205
-        private static int pages = 0;
206 205
 
207 206
         public static void PrintOrderReport(List<OrderList> OrderPrintList)
208 207
         {
209 208
             ListLoc = 0;
210
-            pages = 0;
211 209
             OrderReportList = OrderPrintList;
212 210
             PrintDialog pd = new PrintDialog();
213 211
             pd.UseEXDialog = true; //Required for AMD64 based processors

+ 3 - 0
BulkPrinting/BulkPrinting/Program.cs

@@ -1,4 +1,5 @@
1 1
 using System;
2
+using System.IO;
2 3
 using System.Collections.Generic;
3 4
 using System.Linq;
4 5
 using System.Threading.Tasks;
@@ -15,6 +16,8 @@ namespace BulkPrinting
15 16
         static void Main()
16 17
         {
17 18
             Globals.HDDSerialNumber = Utility.GetHDDSerial();
19
+            Globals.MaxDBPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Configuration.MaxDataPathName);
20
+            Globals.MaxDBFilePath = Path.Combine(Globals.MaxDBPath, Configuration.MaxDBFileName);
18 21
             Application.EnableVisualStyles();
19 22
             Application.SetCompatibleTextRenderingDefault(false);
20 23
             Application.Run(new UserLoginForm());

+ 25 - 27
BulkPrinting/BulkPrinting/ReprintForm.cs

@@ -44,13 +44,18 @@ namespace BulkPrinting
44 44
             lblFaceValue.Text = FaceValue;
45 45
             lblVoucherType.Text = VoucherTypeName;
46 46
             lblNetwork.Text = NetworkName;
47
-            SQLiteCommand Command = new SQLiteCommand("SELECT MIN(v.SequenceNumber), MAX(v.SequenceNumber) FROM Voucher v LEFT JOIN Logs l ON v.Id = l.VoucherId AND l.EventType = @eventtype WHERE l.VoucherId IS NOT NULL AND v.BatchId=@batchid AND Retry=0", Globals.DBConnection);
48
-            Command.Parameters.Add(new SQLiteParameter("@batchid", BatchID));
49
-            Command.Parameters.Add(new SQLiteParameter("@eventtype", VendorEvent.VendorEventType.PrintVoucher));
50
-            SQLiteDataReader read = Command.ExecuteReader();
51
-            read.Read();
52
-            MinSeqNo = int.Parse(read.GetValue(0).ToString());
53
-            MaxSeqNo = int.Parse(read.GetValue(1).ToString());
47
+            using (var Command = new SQLiteCommand("SELECT MIN(v.SequenceNumber), MAX(v.SequenceNumber) FROM Voucher v LEFT JOIN Logs l ON v.Id = l.VoucherId AND l.EventType = @eventtype WHERE l.VoucherId IS NOT NULL AND v.BatchId=@batchid AND Retry=0", Globals.DBConnection))
48
+            {
49
+                Command.Parameters.AddWithValue("@batchid", BatchID);
50
+                Command.Parameters.AddWithValue("@eventtype", VendorEvent.VendorEventType.PrintVoucher);
51
+                using (SQLiteDataReader read = Command.ExecuteReader())
52
+                {
53
+                    read.Read();
54
+                    MinSeqNo = int.Parse(read.GetValue(0).ToString());
55
+                    MaxSeqNo = int.Parse(read.GetValue(1).ToString());
56
+                }
57
+            }
58
+
54 59
             numFirstSeqNum.Minimum = MinSeqNo;
55 60
             numFirstSeqNum.Maximum = MaxSeqNo;
56 61
             numLastSeqNum.Minimum = MinSeqNo;
@@ -70,8 +75,6 @@ namespace BulkPrinting
70 75
         {
71 76
             int SelectedRangeStart = 0;
72 77
             int SelectedRangeEnd = 0;
73
-            string Sql;
74
-            SQLiteCommand Command;
75 78
 
76 79
             decimal VoucherCount;
77 80
 
@@ -97,33 +100,28 @@ namespace BulkPrinting
97 100
                 SelectedRangeEnd = (int)numLastSeqNum.Value;
98 101
             }
99 102
             else if (rdoSerial.Checked) {
100
-                Sql = "SELECT Count(*) FROM Logs l left join Voucher v on l.VoucherId=v.id WHERE v.Serial=@serialnum and l.EventType=@eventtype and Retry=0";
101
-                Command = new SQLiteCommand(Sql, Globals.DBConnection);
102
-                Command.Parameters.Add(new SQLiteParameter("@serialnum", txtSerialNum.Text));
103
-                Command.Parameters.Add(new SQLiteParameter("@eventtype", VendorEvent.VendorEventType.PrintVoucher));
104
-                int PrintCount = int.Parse(Command.ExecuteScalar().ToString());
103
+                int PrintCount = int.Parse(Utility.DBExecuteScalar(Globals.DBConnection,
104
+                    "SELECT Count(*) FROM Logs l left join Voucher v on l.VoucherId=v.id WHERE v.Serial=@serialnum and l.EventType=@eventtype and Retry=0",
105
+                    new SQLiteParameter("@serialnum", txtSerialNum.Text),
106
+                    new SQLiteParameter("@eventtype", VendorEvent.VendorEventType.PrintVoucher)).ToString());
105 107
                 if (PrintCount == 0) {
106 108
                     MessageBox.Show("No voucher with that serial number was found to have been printed. Please provide a previously printed voucher number or use the 'Print' function to print new vouchers.", "Cannot find printed voucher", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
107 109
                     return;
108 110
                 }
109 111
             }
110
-            Sql = "SELECT FaceValue FROM Batch WHERE Id=@id";
111
-            Command = new SQLiteCommand(Sql, Globals.DBConnection);
112
-            Command.Parameters.Add(new SQLiteParameter("@id", BatchID));
113 112
 
114 113
             VoucherCount = SelectedRangeEnd - SelectedRangeStart + 1;
115
-            decimal VoucherFaceValue = (decimal)Command.ExecuteScalar();
116
-
117
-            string countsql = "SELECT COUNT(v.ID) FROM Voucher v LEFT JOIN Logs l ON v.Id=l.VoucherId AND l.EventType=@event WHERE v.BatchId=@batchid AND v.SequenceNumber BETWEEN @startseq AND @endseq AND l.id IS NULL";
118
-            SQLiteCommand NewCommand = new SQLiteCommand(countsql, Globals.DBConnection);
114
+            decimal VoucherFaceValue = (decimal)Utility.DBExecuteScalar(Globals.DBConnection,
115
+                "SELECT FaceValue FROM Batch WHERE Id=@id",
116
+                new SQLiteParameter("@id", BatchID));
119 117
 
120
-            NewCommand.Parameters.AddWithValue("@event", (int) VendorEvent.VendorEventType.PrintVoucher);
121
-            NewCommand.Parameters.AddWithValue("@batchid", BatchID);
122
-            NewCommand.Parameters.AddWithValue("@startseq", SelectedRangeStart);
123
-            NewCommand.Parameters.AddWithValue("@endseq", SelectedRangeEnd);
118
+            int UnprintedVouchersInRange = int.Parse(Utility.DBExecuteScalar(Globals.DBConnection,
119
+                "SELECT COUNT(v.ID) FROM Voucher v LEFT JOIN Logs l ON v.Id=l.VoucherId AND l.EventType=@event WHERE v.BatchId=@batchid AND v.SequenceNumber BETWEEN @startseq AND @endseq AND l.id IS NULL",
120
+                new SQLiteParameter("@event", (int) VendorEvent.VendorEventType.PrintVoucher),
121
+                new SQLiteParameter("@batchid", BatchID),
122
+                new SQLiteParameter("@startseq", SelectedRangeStart),
123
+                new SQLiteParameter("@endseq", SelectedRangeEnd)).ToString());
124 124
 
125
-            var result = Command.ExecuteScalar();//Utility.GetNumberOfUnprintedVouchersInRange((int)numFirstSeqNum.Value, (int)numLastSeqNum.Value, BatchID);
126
-            int UnprintedVouchersInRange = int.Parse(result.ToString());
127 125
             decimal PrintedVoucherValue = (VoucherCount - UnprintedVouchersInRange) * VoucherFaceValue;
128 126
             decimal UnprintedVoucherValue = UnprintedVouchersInRange * VoucherFaceValue;
129 127
 

+ 15 - 21
BulkPrinting/BulkPrinting/UserLoginForm.cs

@@ -19,8 +19,6 @@ namespace BulkPrinting
19 19
         private void btnLogin_Click(object sender, EventArgs e)
20 20
         {
21 21
             bool LoginSuccessful = false;
22
-            string MaxDBPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Configuration.MaxDataPathName);
23
-            string MaxDBFilePath = Path.Combine(MaxDBPath, Configuration.MaxDBFileName);
24 22
             LoginData UserLoginData = new LoginData();
25 23
             UserLoginData.VendorId = int.Parse(this.txtVendorID.Text);
26 24
             UserLoginData.SerialNumber = Globals.HDDSerialNumber;
@@ -54,7 +52,7 @@ namespace BulkPrinting
54 52
                     return;
55 53
                 }
56 54
 
57
-                if (!File.Exists(MaxDBFilePath))
55
+                if (!File.Exists(Globals.MaxDBFilePath))
58 56
                 {
59 57
                     //Shouldn't get here unless the database is deleted or moved
60 58
                     MessageBox.Show("A problem has been detected and online initialisation must be performed. You cannot use offline mode until this has been completed.", "Application error", MessageBoxButtons.OK, MessageBoxIcon.Error);
@@ -62,13 +60,11 @@ namespace BulkPrinting
62 60
                 }
63 61
                 else
64 62
                 {
65
-                    Globals.DBConnection = new SQLiteConnection(String.Format("Data Source={0};", MaxDBFilePath));
66
-                    Globals.DBConnection.SetPassword(Globals.SessionDatabasePassword);
67
-                    Globals.DBConnection.Open();
63
+                    Globals.DBConnection = Utility.OpenDBConnection();
68 64
                     //Test login success
69 65
                     Globals.SessionMode = SessionModes.Offline;
70
-                    SQLiteCommand SQLCommand = new SQLiteCommand("SELECT Value FROM SessionData WHERE Key = 'SessionDataJson'", Globals.DBConnection);
71
-                    Globals.SessionData = JsonConvert.DeserializeObject<OKResponse>(Convert.ToString(SQLCommand.ExecuteScalar()));
66
+                    Globals.SessionData = JsonConvert.DeserializeObject<OKResponse>(Convert.ToString(Utility.DBExecuteScalar(
67
+                        Globals.DBConnection, "SELECT Value FROM SessionData WHERE Key = 'SessionDataJson'")));
72 68
                     Globals.SessionVoucherKey = Utility.AesDecryptBytes(Globals.SessionData.Credentials.Payload.EncryptedVoucherKey, userKey);
73 69
                     DateTime ServerDate = Globals.SessionData.Credentials.Payload.Date;
74 70
                     DateTime Today = DateTime.Now;
@@ -76,7 +72,7 @@ namespace BulkPrinting
76 72
                         MessageBox.Show("It looks like this user hasn't performed an online login today or since the application started. You must perform an online login at least once during the day to use the offline feature. To use offline mode, please remember not to close the application after each session.", "Cannot perform offline login", MessageBoxButtons.OK, MessageBoxIcon.Error);
77 73
                         return;
78 74
                     }
79
-                    Utility.LogEvent(VendorEvent.VendorEventType.OfflineLogin);
75
+                    Utility.LogEvent(Globals.DBConnection, VendorEvent.VendorEventType.OfflineLogin);
80 76
                     LoginSuccessful = true;
81 77
                 }
82 78
             }
@@ -110,22 +106,22 @@ namespace BulkPrinting
110 106
                         Globals.SessionDatabasePassword = Utility.AesDecryptBytes(Globals.SessionEncryptedDatabasePassword, userKey);
111 107
                         Globals.SessionVoucherKey = Utility.AesDecryptBytes(Globals.SessionData.Credentials.Payload.EncryptedVoucherKey, userKey);
112 108
 
113
-                        if (!File.Exists(MaxDBFilePath))
109
+                        if (!File.Exists(Globals.MaxDBFilePath))
114 110
                         {
115
-                            if (!Directory.Exists(MaxDBPath))
111
+                            if (!Directory.Exists(Globals.MaxDBPath))
116 112
                             {
117
-                                Directory.CreateDirectory(MaxDBPath);
113
+                                Directory.CreateDirectory(Globals.MaxDBPath);
118 114
                             }
119
-                            SQLiteConnection.CreateFile(MaxDBFilePath);
120
-                            Migrations.InitialVersion();
115
+                            SQLiteConnection.CreateFile(Globals.MaxDBFilePath);
116
+                            Globals.DBConnection = Utility.OpenDBConnection();
117
+                            Migrations.InitialVersion(Globals.DBConnection);
121 118
                         }
122 119
                         else
123 120
                         {
124
-                            Globals.DBConnection = new SQLiteConnection(String.Format("Data Source={0};", MaxDBFilePath));
125
-                            Globals.DBConnection.SetPassword(Globals.SessionDatabasePassword);
126
-                            Globals.DBConnection.Open();
121
+                            Globals.DBConnection = Utility.OpenDBConnection();
127 122
                         }
128
-                        Migrations.CheckMigrations();
123
+                        Migrations.CheckMigrations(Globals.DBConnection);
124
+                        Utility.CheckLastSyncedLogID(Globals.DBConnection);
129 125
                         Utility.TriggerLogSync(); //Perform log sync before any logging happens to ensure synchronicity with server
130 126
                     }
131 127
                 }
@@ -149,9 +145,7 @@ namespace BulkPrinting
149 145
                 Globals.SessionData.Credentials.Payload.User.OnlineReprintValue = 0;
150 146
                 Globals.SessionData.Credentials.Payload.User.OfflineReprintValue = 0;
151 147
                 */
152
-                string Sql = "DELETE FROM SessionData"; //Destroy stored session data on login - keep in memory until logout
153
-                SQLiteCommand Command = new SQLiteCommand(Sql, Globals.DBConnection);
154
-                Command.ExecuteNonQuery();
148
+                Utility.DBExecuteNonQuery(Globals.DBConnection, "DELETE FROM SessionData"); //Destroy stored session data on login - keep in memory until logout
155 149
                 Globals.MaxPrinter = new Printer();
156 150
                 this.txtPassword.Text = "";
157 151
                 this.Hide();

文件差異過大導致無法顯示
+ 442 - 480
BulkPrinting/BulkPrinting/Utility.cs


+ 59 - 39
BulkPrinting/BulkPrinting/VoucherForm.Designer.cs

@@ -64,11 +64,12 @@
64 64
             this.dgvVouchers.BackgroundColor = System.Drawing.Color.FromArgb(((int)(((byte)(107)))), ((int)(((byte)(157)))), ((int)(((byte)(233)))));
65 65
             this.dgvVouchers.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
66 66
             this.dgvVouchers.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
67
-            this.dgvVouchers.Location = new System.Drawing.Point(12, 108);
67
+            this.dgvVouchers.Location = new System.Drawing.Point(16, 133);
68
+            this.dgvVouchers.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
68 69
             this.dgvVouchers.MultiSelect = false;
69 70
             this.dgvVouchers.Name = "dgvVouchers";
70 71
             this.dgvVouchers.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
71
-            this.dgvVouchers.Size = new System.Drawing.Size(704, 434);
72
+            this.dgvVouchers.Size = new System.Drawing.Size(939, 534);
72 73
             this.dgvVouchers.TabIndex = 5;
73 74
             this.dgvVouchers.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgvVouchers_CellContentClick);
74 75
             // 
@@ -76,9 +77,10 @@
76 77
             // 
77 78
             this.lblBatchDetails.AutoSize = true;
78 79
             this.lblBatchDetails.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
79
-            this.lblBatchDetails.Location = new System.Drawing.Point(12, 12);
80
+            this.lblBatchDetails.Location = new System.Drawing.Point(16, 15);
81
+            this.lblBatchDetails.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
80 82
             this.lblBatchDetails.Name = "lblBatchDetails";
81
-            this.lblBatchDetails.Size = new System.Drawing.Size(0, 25);
83
+            this.lblBatchDetails.Size = new System.Drawing.Size(0, 31);
82 84
             this.lblBatchDetails.TabIndex = 7;
83 85
             this.lblBatchDetails.Click += new System.EventHandler(this.lblBatchDetails_Click);
84 86
             // 
@@ -86,9 +88,10 @@
86 88
             // 
87 89
             this.rdoPrintDate.AutoSize = true;
88 90
             this.rdoPrintDate.ForeColor = System.Drawing.Color.White;
89
-            this.rdoPrintDate.Location = new System.Drawing.Point(12, 40);
91
+            this.rdoPrintDate.Location = new System.Drawing.Point(16, 49);
92
+            this.rdoPrintDate.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
90 93
             this.rdoPrintDate.Name = "rdoPrintDate";
91
-            this.rdoPrintDate.Size = new System.Drawing.Size(123, 17);
94
+            this.rdoPrintDate.Size = new System.Drawing.Size(163, 21);
92 95
             this.rdoPrintDate.TabIndex = 8;
93 96
             this.rdoPrintDate.Text = "Date Printed (range):";
94 97
             this.rdoPrintDate.UseVisualStyleBackColor = true;
@@ -98,9 +101,10 @@
98 101
             // 
99 102
             this.rdoVoucherRange.AutoSize = true;
100 103
             this.rdoVoucherRange.ForeColor = System.Drawing.Color.White;
101
-            this.rdoVoucherRange.Location = new System.Drawing.Point(12, 63);
104
+            this.rdoVoucherRange.Location = new System.Drawing.Point(16, 78);
105
+            this.rdoVoucherRange.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
102 106
             this.rdoVoucherRange.Name = "rdoVoucherRange";
103
-            this.rdoVoucherRange.Size = new System.Drawing.Size(160, 17);
107
+            this.rdoVoucherRange.Size = new System.Drawing.Size(207, 21);
104 108
             this.rdoVoucherRange.TabIndex = 8;
105 109
             this.rdoVoucherRange.Text = "Vouchers in Selected Batch:";
106 110
             this.rdoVoucherRange.UseVisualStyleBackColor = true;
@@ -111,9 +115,10 @@
111 115
             this.rdoSerialNum.AutoSize = true;
112 116
             this.rdoSerialNum.Checked = true;
113 117
             this.rdoSerialNum.ForeColor = System.Drawing.Color.White;
114
-            this.rdoSerialNum.Location = new System.Drawing.Point(12, 86);
118
+            this.rdoSerialNum.Location = new System.Drawing.Point(16, 106);
119
+            this.rdoSerialNum.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
115 120
             this.rdoSerialNum.Name = "rdoSerialNum";
116
-            this.rdoSerialNum.Size = new System.Drawing.Size(94, 17);
121
+            this.rdoSerialNum.Size = new System.Drawing.Size(123, 21);
117 122
             this.rdoSerialNum.TabIndex = 8;
118 123
             this.rdoSerialNum.TabStop = true;
119 124
             this.rdoSerialNum.Text = "Serial Number:";
@@ -124,9 +129,10 @@
124 129
             // 
125 130
             this.label1.AutoSize = true;
126 131
             this.label1.ForeColor = System.Drawing.Color.White;
127
-            this.label1.Location = new System.Drawing.Point(12, 12);
132
+            this.label1.Location = new System.Drawing.Point(16, 15);
133
+            this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
128 134
             this.label1.Name = "label1";
129
-            this.label1.Size = new System.Drawing.Size(120, 13);
135
+            this.label1.Size = new System.Drawing.Size(159, 17);
130 136
             this.label1.TabIndex = 9;
131 137
             this.label1.Text = "Search for vouchers by:";
132 138
             this.label1.Click += new System.EventHandler(this.label1_Click);
@@ -134,35 +140,39 @@
134 140
             // dtpStartDate
135 141
             // 
136 142
             this.dtpStartDate.Format = System.Windows.Forms.DateTimePickerFormat.Short;
137
-            this.dtpStartDate.Location = new System.Drawing.Point(353, 39);
143
+            this.dtpStartDate.Location = new System.Drawing.Point(471, 48);
144
+            this.dtpStartDate.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
138 145
             this.dtpStartDate.Name = "dtpStartDate";
139
-            this.dtpStartDate.Size = new System.Drawing.Size(100, 20);
146
+            this.dtpStartDate.Size = new System.Drawing.Size(132, 22);
140 147
             this.dtpStartDate.TabIndex = 10;
141 148
             this.dtpStartDate.ValueChanged += new System.EventHandler(this.dtpStartDate_ValueChanged);
142 149
             // 
143 150
             // dtpEndDate
144 151
             // 
145 152
             this.dtpEndDate.Format = System.Windows.Forms.DateTimePickerFormat.Short;
146
-            this.dtpEndDate.Location = new System.Drawing.Point(510, 39);
153
+            this.dtpEndDate.Location = new System.Drawing.Point(680, 48);
154
+            this.dtpEndDate.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
147 155
             this.dtpEndDate.Name = "dtpEndDate";
148
-            this.dtpEndDate.Size = new System.Drawing.Size(100, 20);
156
+            this.dtpEndDate.Size = new System.Drawing.Size(132, 22);
149 157
             this.dtpEndDate.TabIndex = 10;
150 158
             this.dtpEndDate.ValueChanged += new System.EventHandler(this.dtpEndDate_ValueChanged);
151 159
             // 
152 160
             // txtSerial
153 161
             // 
154
-            this.txtSerial.Location = new System.Drawing.Point(320, 85);
162
+            this.txtSerial.Location = new System.Drawing.Point(427, 105);
163
+            this.txtSerial.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
155 164
             this.txtSerial.Name = "txtSerial";
156
-            this.txtSerial.Size = new System.Drawing.Size(290, 20);
165
+            this.txtSerial.Size = new System.Drawing.Size(385, 22);
157 166
             this.txtSerial.TabIndex = 11;
158 167
             // 
159 168
             // lblBatch1
160 169
             // 
161 170
             this.lblBatch1.AutoSize = true;
162 171
             this.lblBatch1.ForeColor = System.Drawing.Color.White;
163
-            this.lblBatch1.Location = new System.Drawing.Point(317, 64);
172
+            this.lblBatch1.Location = new System.Drawing.Point(423, 79);
173
+            this.lblBatch1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
164 174
             this.lblBatch1.Name = "lblBatch1";
165
-            this.lblBatch1.Size = new System.Drawing.Size(30, 13);
175
+            this.lblBatch1.Size = new System.Drawing.Size(40, 17);
166 176
             this.lblBatch1.TabIndex = 12;
167 177
             this.lblBatch1.Text = "From";
168 178
             this.lblBatch1.Click += new System.EventHandler(this.lblBatch1_Click);
@@ -171,9 +181,10 @@
171 181
             // 
172 182
             this.label3.AutoSize = true;
173 183
             this.label3.ForeColor = System.Drawing.Color.White;
174
-            this.label3.Location = new System.Drawing.Point(317, 41);
184
+            this.label3.Location = new System.Drawing.Point(423, 50);
185
+            this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
175 186
             this.label3.Name = "label3";
176
-            this.label3.Size = new System.Drawing.Size(30, 13);
187
+            this.label3.Size = new System.Drawing.Size(40, 17);
177 188
             this.label3.TabIndex = 12;
178 189
             this.label3.Text = "From";
179 190
             this.label3.Click += new System.EventHandler(this.label3_Click);
@@ -182,9 +193,10 @@
182 193
             // 
183 194
             this.label4.AutoSize = true;
184 195
             this.label4.ForeColor = System.Drawing.Color.White;
185
-            this.label4.Location = new System.Drawing.Point(484, 41);
196
+            this.label4.Location = new System.Drawing.Point(645, 50);
197
+            this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
186 198
             this.label4.Name = "label4";
187
-            this.label4.Size = new System.Drawing.Size(20, 13);
199
+            this.label4.Size = new System.Drawing.Size(25, 17);
188 200
             this.label4.TabIndex = 12;
189 201
             this.label4.Text = "To";
190 202
             this.label4.Click += new System.EventHandler(this.label4_Click);
@@ -193,26 +205,29 @@
193 205
             // 
194 206
             this.lblBatch2.AutoSize = true;
195 207
             this.lblBatch2.ForeColor = System.Drawing.Color.White;
196
-            this.lblBatch2.Location = new System.Drawing.Point(484, 64);
208
+            this.lblBatch2.Location = new System.Drawing.Point(645, 79);
209
+            this.lblBatch2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
197 210
             this.lblBatch2.Name = "lblBatch2";
198
-            this.lblBatch2.Size = new System.Drawing.Size(20, 13);
211
+            this.lblBatch2.Size = new System.Drawing.Size(25, 17);
199 212
             this.lblBatch2.TabIndex = 12;
200 213
             this.lblBatch2.Text = "To";
201 214
             this.lblBatch2.Click += new System.EventHandler(this.lblBatch2_Click);
202 215
             // 
203 216
             // numStartSeqNo
204 217
             // 
205
-            this.numStartSeqNo.Location = new System.Drawing.Point(353, 62);
218
+            this.numStartSeqNo.Location = new System.Drawing.Point(471, 76);
219
+            this.numStartSeqNo.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
206 220
             this.numStartSeqNo.Name = "numStartSeqNo";
207
-            this.numStartSeqNo.Size = new System.Drawing.Size(100, 20);
221
+            this.numStartSeqNo.Size = new System.Drawing.Size(133, 22);
208 222
             this.numStartSeqNo.TabIndex = 14;
209 223
             this.numStartSeqNo.ValueChanged += new System.EventHandler(this.numStartSeqNo_ValueChanged);
210 224
             // 
211 225
             // numEndSeqNo
212 226
             // 
213
-            this.numEndSeqNo.Location = new System.Drawing.Point(510, 62);
227
+            this.numEndSeqNo.Location = new System.Drawing.Point(680, 76);
228
+            this.numEndSeqNo.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
214 229
             this.numEndSeqNo.Name = "numEndSeqNo";
215
-            this.numEndSeqNo.Size = new System.Drawing.Size(100, 20);
230
+            this.numEndSeqNo.Size = new System.Drawing.Size(133, 22);
216 231
             this.numEndSeqNo.TabIndex = 14;
217 232
             this.numEndSeqNo.ValueChanged += new System.EventHandler(this.numEndSeqNo_ValueChanged);
218 233
             // 
@@ -220,37 +235,41 @@
220 235
             // 
221 236
             this.btnSearch.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(132)))), ((int)(((byte)(186)))));
222 237
             this.btnSearch.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("btnSearch.BackgroundImage")));
238
+            this.btnSearch.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
223 239
             this.btnSearch.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
224
-            this.btnSearch.Location = new System.Drawing.Point(616, 2);
240
+            this.btnSearch.Location = new System.Drawing.Point(821, 2);
241
+            this.btnSearch.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
225 242
             this.btnSearch.Name = "btnSearch";
226
-            this.btnSearch.Size = new System.Drawing.Size(100, 100);
243
+            this.btnSearch.Size = new System.Drawing.Size(133, 123);
227 244
             this.btnSearch.TabIndex = 13;
228 245
             this.btnSearch.UseVisualStyleBackColor = false;
229 246
             this.btnSearch.Click += new System.EventHandler(this.btnSearch_Click);
230 247
             // 
231 248
             // numBatchId
232 249
             // 
233
-            this.numBatchId.Location = new System.Drawing.Point(242, 62);
250
+            this.numBatchId.Location = new System.Drawing.Point(323, 76);
251
+            this.numBatchId.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
234 252
             this.numBatchId.Name = "numBatchId";
235
-            this.numBatchId.Size = new System.Drawing.Size(69, 20);
253
+            this.numBatchId.Size = new System.Drawing.Size(92, 22);
236 254
             this.numBatchId.TabIndex = 15;
237 255
             // 
238 256
             // label2
239 257
             // 
240 258
             this.label2.AutoSize = true;
241 259
             this.label2.ForeColor = System.Drawing.Color.White;
242
-            this.label2.Location = new System.Drawing.Point(187, 65);
260
+            this.label2.Location = new System.Drawing.Point(249, 80);
261
+            this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
243 262
             this.label2.Name = "label2";
244
-            this.label2.Size = new System.Drawing.Size(49, 13);
263
+            this.label2.Size = new System.Drawing.Size(61, 17);
245 264
             this.label2.TabIndex = 16;
246 265
             this.label2.Text = "Batch ID";
247 266
             // 
248 267
             // VoucherForm
249 268
             // 
250
-            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
269
+            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
251 270
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
252 271
             this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(7)))), ((int)(((byte)(63)))), ((int)(((byte)(145)))));
253
-            this.ClientSize = new System.Drawing.Size(728, 554);
272
+            this.ClientSize = new System.Drawing.Size(971, 682);
254 273
             this.Controls.Add(this.label2);
255 274
             this.Controls.Add(this.numBatchId);
256 275
             this.Controls.Add(this.numEndSeqNo);
@@ -270,7 +289,8 @@
270 289
             this.Controls.Add(this.lblBatchDetails);
271 290
             this.Controls.Add(this.dgvVouchers);
272 291
             this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
273
-            this.MinimumSize = new System.Drawing.Size(621, 531);
292
+            this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
293
+            this.MinimumSize = new System.Drawing.Size(822, 643);
274 294
             this.Name = "VoucherForm";
275 295
             this.Text = "View PINs";
276 296
             this.Load += new System.EventHandler(this.VoucherForm_Load);

+ 41 - 40
BulkPrinting/BulkPrinting/VoucherForm.cs

@@ -52,48 +52,49 @@ namespace BulkPrinting
52 52
 
53 53
         private void btnSearch_Click(object sender, EventArgs e)
54 54
         {
55
-            string Sql;
56
-            SQLiteCommand Command = new SQLiteCommand();
57
-            if (rdoPrintDate.Checked) {
58
-                Sql = "SELECT v.BatchId, v.Serial, v.SequenceNumber, v.ExpiryDate, v.EncryptedPIN FROM Voucher v LEFT JOIN Logs l on v.Id = l.VoucherId and l.EventType=@eventtype WHERE l.EventDate BETWEEN @startdate AND @enddate";
59
-                Command = new SQLiteCommand(Sql, Globals.DBConnection);
60
-                Command.Parameters.Add(new SQLiteParameter("@eventtype", VendorEvent.VendorEventType.PrintVoucher));
61
-                CultureInfo IVC = CultureInfo.InvariantCulture;
62
-                Command.Parameters.Add(new SQLiteParameter("@startdate", dtpStartDate.Value.ToString("yyyy-MM-dd 00:00:00", IVC)));
63
-                Command.Parameters.Add(new SQLiteParameter("@enddate", dtpEndDate.Value.ToString("yyyy-MM-dd 23:59:59", IVC)));
64
-            }
65
-            else if (rdoVoucherRange.Checked) {
66
-                Sql = "SELECT BatchId, Serial, SequenceNumber, ExpiryDate, EncryptedPIN FROM Voucher WHERE BatchId = @batchid AND SequenceNumber BETWEEN @minseqno AND @maxseqno";
67
-                Command = new SQLiteCommand(Sql, Globals.DBConnection);
68
-                Command.Parameters.Add(new SQLiteParameter("@batchid", numBatchId.Value));
69
-                Command.Parameters.Add(new SQLiteParameter("@minseqno", numStartSeqNo.Value));
70
-                Command.Parameters.Add(new SQLiteParameter("@maxseqno", numEndSeqNo.Value));
71
-            }
72
-            else if (rdoSerialNum.Checked) {
73
-                Sql = "SELECT BatchId, Serial, SequenceNumber, ExpiryDate, EncryptedPIN FROM Voucher WHERE Serial=@serial";
74
-                Command = new SQLiteCommand(Sql, Globals.DBConnection);
75
-                Command.Parameters.Add(new SQLiteParameter("@serial", txtSerial.Text));
76
-            }
77
-
78
-            dgvVouchers.Rows.Clear();
79
-            dgvVouchers.Columns.Clear();
80
-            dgvVouchers.Columns.Add("BatchId", "Batch ID");
81
-            dgvVouchers.Columns.Add("Serial", "Serial Number");
82
-            dgvVouchers.Columns.Add("SequenceNumber", "Sequence Number");
83
-            dgvVouchers.Columns.Add("ExpiryDate", "Expiry Date");
84
-            dgvVouchers.Columns.Add("PIN", "PIN");
85
-            using (SQLiteDataReader SQLReader = Command.ExecuteReader())
55
+            using (var Command = new SQLiteCommand(Globals.DBConnection))
86 56
             {
87
-                while (SQLReader.Read())
57
+                if (rdoPrintDate.Checked)
58
+                {
59
+                    Command.CommandText = "SELECT v.BatchId, v.Serial, v.SequenceNumber, v.ExpiryDate, v.EncryptedPIN FROM Voucher v LEFT JOIN Logs l on v.Id = l.VoucherId and l.EventType=@eventtype WHERE l.EventDate BETWEEN @startdate AND @enddate";
60
+                    Command.Parameters.AddWithValue("@eventtype", VendorEvent.VendorEventType.PrintVoucher);
61
+                    CultureInfo IVC = CultureInfo.InvariantCulture;
62
+                    Command.Parameters.AddWithValue("@startdate", dtpStartDate.Value.ToString("yyyy-MM-dd 00:00:00", IVC));
63
+                    Command.Parameters.AddWithValue("@enddate", dtpEndDate.Value.ToString("yyyy-MM-dd 23:59:59", IVC));
64
+                }
65
+                else if (rdoVoucherRange.Checked)
66
+                {
67
+                    Command.CommandText = "SELECT BatchId, Serial, SequenceNumber, ExpiryDate, EncryptedPIN FROM Voucher WHERE BatchId = @batchid AND SequenceNumber BETWEEN @minseqno AND @maxseqno";
68
+                    Command.Parameters.AddWithValue("@batchid", numBatchId.Value);
69
+                    Command.Parameters.AddWithValue("@minseqno", numStartSeqNo.Value);
70
+                    Command.Parameters.AddWithValue("@maxseqno", numEndSeqNo.Value);
71
+                }
72
+                else if (rdoSerialNum.Checked)
73
+                {
74
+                    Command.CommandText = "SELECT BatchId, Serial, SequenceNumber, ExpiryDate, EncryptedPIN FROM Voucher WHERE Serial=@serial";
75
+                    Command.Parameters.AddWithValue("@serial", txtSerial.Text);
76
+                }
77
+
78
+                dgvVouchers.Rows.Clear();
79
+                dgvVouchers.Columns.Clear();
80
+                dgvVouchers.Columns.Add("BatchId", "Batch ID");
81
+                dgvVouchers.Columns.Add("Serial", "Serial Number");
82
+                dgvVouchers.Columns.Add("SequenceNumber", "Sequence Number");
83
+                dgvVouchers.Columns.Add("ExpiryDate", "Expiry Date");
84
+                dgvVouchers.Columns.Add("PIN", "PIN");
85
+                using (SQLiteDataReader SQLReader = Command.ExecuteReader())
88 86
                 {
89
-                    string VoucherPIN = Utility.TripleDESDecrypt(SQLReader.GetValue(4).ToString(), Globals.SessionVoucherKey).ToString();
90
-                    dgvVouchers.Rows.Add(new object[] {
91
-                        SQLReader.GetValue(0),
92
-                        SQLReader.GetValue(1),
93
-                        SQLReader.GetValue(2),
94
-                        SQLReader.GetValue(3),
95
-                        VoucherPIN
96
-                    });
87
+                    while (SQLReader.Read())
88
+                    {
89
+                        string VoucherPIN = Utility.TripleDESDecrypt(SQLReader.GetValue(4).ToString(), Globals.SessionVoucherKey).ToString();
90
+                        dgvVouchers.Rows.Add(new object[] {
91
+                            SQLReader.GetValue(0),
92
+                            SQLReader.GetValue(1),
93
+                            SQLReader.GetValue(2),
94
+                            SQLReader.GetValue(3),
95
+                            VoucherPIN
96
+                        });
97
+                    }
97 98
                 }
98 99
             }
99 100
         }