Procházet zdrojové kódy

Add BinStack integration, barcode scanning, and item lookup

master
Skylar Ittner před 1 rokem
rodič
revize
40bc592a8d
8 změnil soubory, kde provedl 250 přidání a 46 odebrání
  1. 22
    1
      action.php
  2. 1
    0
      pages.php
  3. 0
    1
      pages/home.php
  4. 3
    37
      pages/pos.php
  5. 9
    0
      required.php
  6. 9
    0
      settings.template.php
  7. 91
    0
      static/js/bsalert.js
  8. 115
    7
      static/js/pos.js

+ 22
- 1
action.php Zobrazit soubor

@@ -7,7 +7,6 @@
7 7
 /**
8 8
  * Make things happen when buttons are pressed and forms submitted.
9 9
  */
10
-
11 10
 require_once __DIR__ . "/required.php";
12 11
 
13 12
 if ($VARS['action'] !== "signout") {
@@ -31,6 +30,28 @@ function returnToSender($msg, $arg = "") {
31 30
 }
32 31
 
33 32
 switch ($VARS['action']) {
33
+    case "itemsearch":
34
+        header("Content-Type: application/json");
35
+        if (!is_empty($VARS['q'])) {
36
+            $where["AND"]["OR"] = [
37
+                "name[~]" => $VARS['q'],
38
+                "code1[~]" => $VARS['q'],
39
+                "code2[~]" => $VARS['q']
40
+            ];
41
+        } else {
42
+            exit(json_encode(["status" => "ERROR", "items" => false]));
43
+        }
44
+
45
+        $items = $binstack->select('items', [
46
+            'itemid (id)',
47
+            'name',
48
+            'code1',
49
+            'code2',
50
+            'cost',
51
+            'price'
52
+                ], $where);
53
+        $items = (count($items) > 0 ? $items : false);
54
+        exit(json_encode(["status" => "OK", "items" => $items]));
34 55
     case "signout":
35 56
         session_destroy();
36 57
         header('Location: index.php');

+ 1
- 0
pages.php Zobrazit soubor

@@ -16,6 +16,7 @@ define("PAGES", [
16 16
         "navbar" => true,
17 17
         "icon" => "far fa-money-bill-alt",
18 18
         "scripts" => [
19
+            "static/js/bsalert.js",
19 20
             "static/js/pos.js",
20 21
         ]
21 22
     ],

+ 0
- 1
pages/home.php Zobrazit soubor

@@ -3,4 +3,3 @@
3 3
  * License, v. 2.0. If a copy of the MPL was not distributed with this
4 4
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 5
 ?>
6
-<h1>Hello World</h1>

+ 3
- 37
pages/pos.php Zobrazit soubor

@@ -15,51 +15,17 @@
15 15
             <div class="card-header p-1">
16 16
                 <div class="input-group">
17 17
                     <div class="input-group-prepend">
18
-                        <span class="input-group-text"><i class="fas fa-barcode"></i></span>
18
+                        <span class="input-group-text px-2"><i class="fas fa-barcode"></i></span>
19 19
                     </div>
20 20
                     <input type="text" class="form-control" id="barcode" placeholder="<?php lang("barcode"); ?>" />
21 21
                     <div class="input-group-append">
22
-                        <button class="btn btn-link" type="button"><i class="fas fa-plus"></i></button>
22
+                        <button class="btn btn-link" type="button" id="barcodebtn"><i class="fas fa-search"></i></button>
23 23
                     </div>
24 24
                 </div>
25 25
             </div>
26 26
             <div>
27 27
                 <div class="list-group" id="pos-lines-box">
28
-                    <?php
29
-                    for ($i = 0; $i < 5; $i++) {
30
-                        ?>
31
-                        <div class="list-group-item">
32
-                            <div class="d-flex w-100 justify-content-between mb-2">
33
-                                <h5 class="item-name">
34
-                                    Cool Widget
35
-                                </h5>
36
-                                <h5>
37
-                                    <small class="item-code">659321</small>
38
-                                    <span class="badge badge-light">
39
-                                        $<span class="line-total">10.23</span>
40
-                                    </span>
41
-                                </h5>
42
-                            </div>
43
-                            <div class="d-inline-flex">
44
-                                <div class="input-group input-group-sm qty-control">
45
-                                    <div class="input-group-prepend">
46
-                                        <span class="input-group-text mx-0 px-0"><b>$</b></span>
47
-                                    </div>
48
-                                    <input type="number" class="form-control item-price" value="10.23"/>
49
-                                    <div class="input-group-prepend">
50
-                                        <span class="input-group-text"><i class="fas fa-times"></i></span>
51
-                                        <button class="btn btn-red qty-minus" type="button"><i class="fas fa-trash"></i></button>
52
-                                    </div>
53
-                                    <input type="number" class="form-control item-qty" value="1" />
54
-                                    <div class="input-group-append">
55
-                                        <button class="btn btn-light-green qty-plus" type="button"><i class="fas fa-plus"></i></button>
56
-                                    </div>
57
-                                </div>
58
-                            </div>
59
-                        </div>
60
-                        <?php
61
-                    }
62
-                    ?>
28
+                    <!-- Items go here -->
63 29
                 </div>
64 30
             </div>
65 31
         </div>

+ 9
- 0
required.php Zobrazit soubor

@@ -92,6 +92,7 @@ date_default_timezone_set(TIMEZONE);
92 92
 use Medoo\Medoo;
93 93
 
94 94
 $database;
95
+$binstack;
95 96
 try {
96 97
     $database = new Medoo([
97 98
         'database_type' => DB_TYPE,
@@ -101,6 +102,14 @@ try {
101 102
         'password' => DB_PASS,
102 103
         'charset' => DB_CHARSET
103 104
     ]);
105
+    $binstack = new Medoo([
106
+        'database_type' => BINSTACK_DB_TYPE,
107
+        'database_name' => BINSTACK_DB_NAME,
108
+        'server' => BINSTACK_DB_SERVER,
109
+        'username' => BINSTACK_DB_USER,
110
+        'password' => BINSTACK_DB_PASS,
111
+        'charset' => BINSTACK_DB_CHARSET
112
+    ]);
104 113
 } catch (Exception $ex) {
105 114
     //header('HTTP/1.1 500 Internal Server Error');
106 115
     sendError("Database error.  Try again later.  $ex");

+ 9
- 0
settings.template.php Zobrazit soubor

@@ -17,6 +17,15 @@ define("DB_USER", "nickelbox");
17 17
 define("DB_PASS", "");
18 18
 define("DB_CHARSET", "utf8");
19 19
 
20
+// BinStack database connection settings
21
+define("BINSTACK_DB_TYPE", "mysql");
22
+define("BINSTACK_DB_NAME", "inventory");
23
+define("BINSTACK_DB_SERVER", "localhost");
24
+define("BINSTACK_DB_USER", "inventory");
25
+define("BINSTACK_DB_PASS", "");
26
+define("BINSTACK_DB_CHARSET", "utf8");
27
+
28
+
20 29
 // Name of the app.
21 30
 define("SITE_TITLE", "NickelBox");
22 31
 

+ 91
- 0
static/js/bsalert.js Zobrazit soubor

@@ -0,0 +1,91 @@
1
+/*
2
+ * This Source Code Form is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ */
6
+
7
+function bsprompt(title, message, okbtn, cancelbtn, type, callback) {
8
+    var html = '<div class="modal fade" id="bsprompt">'
9
+            + '  <div class="modal-dialog">'
10
+            + '    <div class="modal-content">'
11
+            + '      <div class="modal-header">'
12
+            + '        <h5 class="modal-title" id="bsprompt-title"></h5>'
13
+            + '        <button type="button" class="close" data-dismiss="modal" aria-label="Close">'
14
+            + '          <span aria-hidden="true">&times;</span>'
15
+            + '        </button>'
16
+            + '      </div>'
17
+            + '      <div class="modal-body" id="bsprompt-body">'
18
+            + '        <div id="bsprompt-message"></div>'
19
+            + '        <input id="bsprompt-input" class="form-control" />'
20
+            + '      </div>'
21
+            + '      <div class="modal-footer">'
22
+            + '        <button type="button" class="btn btn-secondary" data-dismiss="modal" id="bsprompt-cancel">Cancel</button>'
23
+            + '        <button type="button" class="btn btn-primary" id="bsprompt-ok">OK</button>'
24
+            + '      </div>'
25
+            + '    </div>'
26
+            + '  </div>'
27
+            + '</div>';
28
+    $("body").append(html);
29
+    $("#bsprompt-title").text(title);
30
+    $("#bsprompt-message").text(message);
31
+    $("#bsprompt-ok").text(okbtn);
32
+    $("#bsprompt-cancel").text(cancelbtn);
33
+    $("#bsprompt-input").attr("type", type);
34
+    $("#bsprompt-input").on("keypress", function (e) {
35
+        if (e.which === 13) {
36
+            callback($("#bsprompt-input").val());
37
+            $("#bsprompt").modal("hide");
38
+        }
39
+    });
40
+    $("#bsprompt-ok").on("click", function () {
41
+        callback($("#bsprompt-input").val());
42
+        $("#bsprompt").modal("hide");
43
+    });
44
+    $("#bsprompt").on("shown.bs.modal", function () {
45
+        $("#bsprompt-input").focus();
46
+    });
47
+    $("#bsprompt").on("hidden.bs.modal", function () {
48
+        $("#bsprompt").remove();
49
+    });
50
+    $("#bsprompt").modal("show");
51
+}
52
+
53
+function bschoices(title, message, options, cancelbtn, callback) {
54
+    var html = '<div class="modal fade" id="bschoices">'
55
+            + '  <div class="modal-dialog">'
56
+            + '    <div class="modal-content">'
57
+            + '      <div class="modal-header">'
58
+            + '        <h5 class="modal-title" id="bschoices-title"></h5>'
59
+            + '        <button type="button" class="close" data-dismiss="modal" aria-label="Close">'
60
+            + '          <span aria-hidden="true">&times;</span>'
61
+            + '        </button>'
62
+            + '      </div>'
63
+            + '      <div class="modal-body" id="bschoices-body">'
64
+            + '        <div id="bschoices-message" class="mb-2"></div>'
65
+            + '        <div class="list-group" id="bschoices-list"></div>'
66
+            + '      </div>'
67
+            + '      <div class="modal-footer">'
68
+            + '        <button type="button" class="btn btn-secondary" data-dismiss="modal" id="bschoices-cancel">Cancel</button>'
69
+            + '      </div>'
70
+            + '    </div>'
71
+            + '  </div>'
72
+            + '</div>';
73
+    $("body").append(html);
74
+    $("#bschoices-title").text(title);
75
+    $("#bschoices-message").text(message);
76
+    $("#bschoices-cancel").text(cancelbtn);
77
+    for (var i = 0; i < options.length; i++) {
78
+        var text = options[i]["text"];
79
+        var val = options[i]["val"];
80
+        $("#bschoices-list").append('<div class="list-group-item bschoices-option" data-value="' + val + '">' + text + '</div>');
81
+    }
82
+    $(".bschoices-option").css("cursor", "pointer");
83
+    $(".bschoices-option").on("click", function () {
84
+        callback($(this).data("value"));
85
+        $("#bschoices").modal("hide");
86
+    });
87
+    $("#bschoices").on("hidden.bs.modal", function () {
88
+        $("#bschoices").remove();
89
+    });
90
+    $("#bschoices").modal("show");
91
+}

+ 115
- 7
static/js/pos.js Zobrazit soubor

@@ -9,13 +9,14 @@ function addItem(name, code, price) {
9 9
         updateQty($(".list-group-item[data-code='" + code + "']").find(".qty-plus"), 1);
10 10
         return;
11 11
     }
12
+    price = (price * 1.0).toFixed(2);
12 13
     $("#pos-lines-box").append('<div class="list-group-item" data-code="' + code + '">'
13 14
             + '<div class="d-flex w-100 justify-content-between mb-2">'
14 15
             + '<h5 class="item-name">'
15 16
             + name
16 17
             + '</h5>'
17 18
             + '<h5>'
18
-            + '<small class="item-code">' + code + '</small>'
19
+            + '<small class="item-code mr-1">' + code + '</small>'
19 20
             + '<span class="badge badge-light">'
20 21
             + '$<span class="line-total">'
21 22
             + price
@@ -24,16 +25,16 @@ function addItem(name, code, price) {
24 25
             + '</h5>'
25 26
             + '</div>'
26 27
             + '<div class="d-inline-flex">'
27
-            + '<div class="input-group input-group-sm qty-control">'
28
+            + '<div class="input-group qty-control">'
28 29
             + '<div class="input-group-prepend">'
29
-            + '<span class="input-group-text mx-0 px-0"><b>$</b></span>'
30
+            + '<span class="input-group-text pr-1"><b>$</b></span>'
30 31
             + '</div>'
31
-            + '<input type="number" class="form-control item-price" value="' + price + '"/>'
32
+            + '<input type="money" class="form-control item-price" value="' + price + '"/>'
32 33
             + '<div class="input-group-prepend">'
33
-            + '<span class="input-group-text"><i class="fas fa-times"></i></span>'
34
+            + '<span class="input-group-text px-2"><i class="fas fa-times"></i></span>'
34 35
             + '<button class="btn btn-red qty-minus" type="button"><i class="fas fa-trash"></i></button>'
35 36
             + '</div>'
36
-            + '<input type="number" class="form-control item-qty" value="1" />'
37
+            + '<input type="number" class="form-control item-qty px-2" value="1" />'
37 38
             + '<div class="input-group-append">'
38 39
             + '<button class="btn btn-light-green qty-plus" type="button"><i class="fas fa-plus"></i></button>'
39 40
             + '</div>'
@@ -42,7 +43,81 @@ function addItem(name, code, price) {
42 43
             + '</div>');
43 44
 }
44 45
 
46
+function findItem(q) {
47
+    function decodeThenAddItem(item) {
48
+        var code = item.code1;
49
+        console.log(code);
50
+        if (code == "" && item["code2"] != "") {
51
+            code = item["code2"];
52
+        } else if (code == "") {
53
+            code = "---";
54
+        }
55
+        var price = item['price'];
56
+        if (price == null || price == "" || price == 0) {
57
+            if (!$(".list-group-item[data-code='" + code + "']").length) {
58
+                bsprompt("Enter Price",
59
+                        "No price set.  Enter a price for this item:",
60
+                        "Add Item",
61
+                        "Cancel",
62
+                        "number",
63
+                        function (result) {
64
+                            addItem(item['name'], code, result);
65
+                        });
66
+                return;
67
+            }
68
+        }
69
+        addItem(item['name'], code, price);
70
+        $("#barcode").val("");
71
+    }
72
+    if (q == "") {
73
+        return;
74
+    }
75
+    $.get("action.php", {
76
+        action: "itemsearch",
77
+        q: q
78
+    }, function (data) {
79
+        if (data['items'].length == 1) {
80
+            decodeThenAddItem(data['items'][0]);
81
+        } else if (data['items'].length > 1) {
82
+            var options = [];
83
+            for (var i = 0; i < data['items'].length; i++) {
84
+                var text = data['items'][i]['name'];
85
+                if (data['items'][i]['price'] != null) {
86
+                    text += " ($" + data['items'][i]['price'] + ")";
87
+                }
88
+                options.push({"text": text, "val": data['items'][i]['id']});
89
+            }
90
+            bschoices(
91
+                    "Multiple Results",
92
+                    "More than one item match the query.  Pick the correct one:",
93
+                    options,
94
+                    "Cancel",
95
+                    function (result) {
96
+                        for (var i = 0; i < data['items'].length; i++) {
97
+                            if (data['items'][i]['id'] == result) {
98
+                                decodeThenAddItem(data['items'][i]);
99
+                                break;
100
+                            }
101
+                        }
102
+                    }
103
+            );
104
+        }
105
+    }).fail(function () {
106
+        alert("Error");
107
+    });
108
+}
109
+
110
+function removezero() {
111
+    $("#pos-lines-box .list-group-item").each(function () {
112
+        var qty = $(".item-qty", this).val() * 1.0;
113
+        if (qty == 0) {
114
+            $(this).remove();
115
+        }
116
+    });
117
+}
118
+
45 119
 function recalculate() {
120
+    removezero();
46 121
     var total = 0.0;
47 122
     $("#pos-lines-box .list-group-item").each(function () {
48 123
         var each = $(".item-price", this).val() * 1.0;
@@ -50,6 +125,7 @@ function recalculate() {
50 125
         var line = each * qty;
51 126
         $(".line-total", this).text(line.toFixed(2));
52 127
         $(".item-price", this).val(each.toFixed(2));
128
+        console.log(each.toFixed(2));
53 129
         total += line;
54 130
     });
55 131
     $(".grand-total").text(total.toFixed(2));
@@ -83,4 +159,36 @@ $("#pos-lines-box").on("click", ".qty-plus", function () {
83 159
 
84 160
 $("#pos-lines-box").on("change", ".item-qty,.item-price", function () {
85 161
     recalculate();
86
-});
162
+});
163
+
164
+$("#pos-lines-box").on("keypress", ".item-qty,.item-price", function (e) {
165
+    if (e.which === 13) {
166
+        recalculate();
167
+    }
168
+});
169
+
170
+$("#barcode").on('keypress', function (e) {
171
+    if (e.which === 13) {
172
+        findItem($("#barcode").val());
173
+    }
174
+});
175
+
176
+$("#barcodebtn").on("click", function () {
177
+    findItem($("#barcode").val());
178
+});
179
+
180
+$("body").on("keypress", "input[type=money],input[type=number]", function (e) {
181
+    //console.log(String.fromCharCode(e.which) + "|" + e.which);
182
+    var c = String.fromCharCode(e.which);
183
+    var k = e.which;
184
+    if (/[0-9]|[\.]/.test(c)) {
185
+        // Numbers and period
186
+    } else if (k == 0 || k == 8) {
187
+        // Delete, backspace, etc
188
+    } else {
189
+        e.preventDefault();
190
+        return false;
191
+    }
192
+});
193
+
194
+$("#barcode").focus();

Načítá se…
Zrušit
Uložit