Add editing of customer-specific pricing (#6)
This commit is contained in:
parent
9f639727a7
commit
bdc32dfd50
35
action.php
35
action.php
@ -312,10 +312,45 @@ END;
|
||||
'notes' => $VARS['notes']
|
||||
];
|
||||
|
||||
$customerid = null;
|
||||
if ($insert) {
|
||||
$database->insert('customers', $data);
|
||||
$customerid = $database->id();
|
||||
} else {
|
||||
$database->update('customers', $data, ['customerid' => $VARS['id']]);
|
||||
$customerid = $VARS['id'];
|
||||
}
|
||||
|
||||
if (!is_null($customerid)) {
|
||||
$custprices = $VARS['pricing'];
|
||||
$newcustprices = [];
|
||||
$oldcustprices = $database->select('customer_pricing', ['itemid (item)', 'price'], ['customerid' => $customerid]);
|
||||
foreach ($custprices as $cp) {
|
||||
if (!$binstack->has('items', ['itemid' => $cp['item']])) {
|
||||
continue;
|
||||
}
|
||||
if (!is_numeric($cp['price'])) {
|
||||
continue;
|
||||
}
|
||||
$newcustprices[] = $cp;
|
||||
$oldcustprices = array_filter($oldcustprices, function ($var) {
|
||||
if ($cp['item'] == $var['item']) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
foreach ($oldcustprices as $cp) {
|
||||
$database->delete('customer_pricing', ['AND' => ['itemid' => $cp['item'], 'customerid' => $customerid]]);
|
||||
}
|
||||
foreach ($newcustprices as $cp) {
|
||||
if ($database->has('customer_pricing', ['AND' => ['itemid' => $cp['item'], 'customerid' => $customerid]])) {
|
||||
$database->update('customer_pricing', ['price' => $cp['price']], ['AND' => ['itemid' => $cp['item'], 'customerid' => $customerid]]);
|
||||
} else {
|
||||
$database->insert('customer_pricing', ['price' => $cp['price'], 'itemid' => $cp['item'], 'customerid' => $customerid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
returnToSender("customer_saved");
|
||||
|
@ -62,4 +62,14 @@ define("STRINGS", [
|
||||
"save" => "Save",
|
||||
"customer saved" => "Customer saved.",
|
||||
"invalid customer id" => "Invalid customer ID",
|
||||
"customer pricing" => "Customer Pricing",
|
||||
"item" => "Item",
|
||||
"cost" => "Cost",
|
||||
"normal price" => "Normal Price",
|
||||
"customer price" => "Customer Price",
|
||||
"add price" => "Add Price",
|
||||
"add customer price" => "Add Customer Price",
|
||||
"delete" => "Delete",
|
||||
"cancel" => "Cancel",
|
||||
"price" => "Price"
|
||||
]);
|
@ -19,6 +19,7 @@ define("PAGES", [
|
||||
"static/css/pos.css",
|
||||
],
|
||||
"scripts" => [
|
||||
"static/js/input_type_money.js",
|
||||
"static/js/bsalert.js",
|
||||
"static/js/pos_items.js",
|
||||
"static/js/pos_customer.js",
|
||||
@ -43,7 +44,14 @@ define("PAGES", [
|
||||
"editcustomer" => [
|
||||
"title" => "edit customer",
|
||||
"navbar" => false,
|
||||
"styles" => [
|
||||
"static/css/datatables.min.css",
|
||||
"static/css/tables.css"
|
||||
],
|
||||
"scripts" => [
|
||||
"static/js/input_type_money.js",
|
||||
"static/js/bsalert.js",
|
||||
"static/js/datatables.min.js",
|
||||
"static/js/editcustomer.js"
|
||||
]
|
||||
],
|
||||
|
@ -36,10 +36,69 @@ if (!empty($VARS['id']) && !is_empty($VARS['id'])) {
|
||||
// customer id is invalid, redirect to a version of the page that won't
|
||||
// cause an error when pressing Save
|
||||
header('Location: app.php?page=editcustomer');
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
$pricing = [];
|
||||
|
||||
if ($editing) {
|
||||
$pricing = $database->select('customer_pricing', ['itemid', 'price'], ['customerid' => $custdata['id']]);
|
||||
for ($i = 0; $i < count($pricing); $i++) {
|
||||
$pricing[$i]['item'] = $binstack->get('items', ['itemid', 'name', 'code1', 'code2', 'cost', 'price'], ['itemid' => $pricing[$i]['itemid']]);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="modal fade" tabindex="-1" role="dialog" id="pricemodal">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fas fa-user-tag"></i> <?php lang("add customer price"); ?></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text px-2"><i class="fas fa-barcode"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" id="pricemodalitem" placeholder="<?php lang("barcode or search"); ?>" />
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-link" type="button" id="pricemodalsearch"><i class="fas fa-search"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-2">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title"><i class="fas fa-box"></i> <?php lang("item"); ?></h5>
|
||||
<p>
|
||||
<?php lang("name"); ?>: <span id="pricemodalitemname">---</span><br />
|
||||
<?php lang("cost"); ?>: <span id="pricemodalitemcost">---</span><br />
|
||||
<?php lang("price"); ?>: <span id="pricemodalitemprice">---</span><br />
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h5 class="card-title"><i class="fas fa-user-tag"></i> <?php lang("customer price"); ?></h5>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">$</span>
|
||||
</div>
|
||||
<input class="form-control" id="pricemodalcustomerprice" type="money" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal"><?php lang("cancel"); ?></button>
|
||||
<button type="button" class="btn btn-primary" id="pricemodalsave"><?php lang("save"); ?></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form role="form" action="action.php" method="POST">
|
||||
<div class="card border-green">
|
||||
<h3 class="card-header text-green">
|
||||
@ -78,6 +137,55 @@ if (!empty($VARS['id']) && !is_empty($VARS['id'])) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="card-body">
|
||||
<h5 class="card-title"><?php lang("customer pricing"); ?></h5>
|
||||
<div class="btn-toolbar">
|
||||
<div class="btn btn-success" id="addcustomerpricebtn">
|
||||
<i class="fas fa-plus"></i> <?php lang("add price"); ?>
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-hover table-sm" id="pricingtable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-priority="0"></th>
|
||||
<th data-priority="1"><?php lang('actions'); ?></th>
|
||||
<th data-priority="1"><?php lang("item"); ?></th>
|
||||
<th data-priority="4"><?php lang("cost"); ?></th>
|
||||
<th data-priority="3"><?php lang("normal price"); ?></th>
|
||||
<th data-priority="2"><?php lang("customer price"); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$i = 0;
|
||||
foreach ($pricing as $p) {
|
||||
?>
|
||||
<tr data-itemid="<?php echo $p['itemid']; ?>">
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="btn btn-sm btn-danger deletepricebtn" data-itemid="<?php echo $p['itemid']; ?>"><i class="fas fa-trash"></i> <?php lang("delete"); ?></div>
|
||||
</td>
|
||||
<td>
|
||||
<input type="hidden" name="pricing[<?php echo $i; ?>][item]" value="<?php echo $p['itemid']; ?>" />
|
||||
<?php echo $p['item']['name']; ?>
|
||||
</td>
|
||||
<td><?php echo $p['item']['cost']; ?></td>
|
||||
<td><?php echo $p['item']['price']; ?></td>
|
||||
<td>
|
||||
<input type="hidden" name="pricing[<?php echo $i; ?>][price]" value="<?php echo $p['price']; ?>" />
|
||||
<?php echo $p['price']; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
$i++;
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="id" value="<?php echo htmlspecialchars($custdata['id']); ?>" />
|
||||
<input type="hidden" name="action" value="editcustomer" />
|
||||
<input type="hidden" name="source" value="customers" />
|
||||
|
@ -7,4 +7,137 @@
|
||||
|
||||
$('#name').on('input propertychange paste', function () {
|
||||
$('#name_title').text($('#name').val());
|
||||
});
|
||||
});
|
||||
|
||||
var pricingtable = $('#pricingtable').DataTable({
|
||||
responsive: {
|
||||
details: {
|
||||
display: $.fn.dataTable.Responsive.display.modal({
|
||||
header: function (row) {
|
||||
var data = row.data();
|
||||
return "<i class=\"fas fa-box fa-fw\"></i> " + data[2];
|
||||
}
|
||||
}),
|
||||
renderer: $.fn.dataTable.Responsive.renderer.tableAll({
|
||||
tableClass: 'table'
|
||||
}),
|
||||
type: "column"
|
||||
}
|
||||
},
|
||||
columnDefs: [
|
||||
{
|
||||
targets: 0,
|
||||
className: 'control',
|
||||
orderable: false
|
||||
},
|
||||
{
|
||||
targets: 1,
|
||||
orderable: false
|
||||
}
|
||||
],
|
||||
order: [
|
||||
[2, 'asc']
|
||||
]
|
||||
});
|
||||
|
||||
$("#pricingtable").on("click", ".deletepricebtn", function () {
|
||||
pricingtable.row($("#pricingtable tr[data-itemid=" + $(this).data("itemid") + "]")).remove();
|
||||
pricingtable.draw();
|
||||
});
|
||||
|
||||
function findItem(q) {
|
||||
function decodeThenSetItem(item) {
|
||||
var name = item['name'];
|
||||
var id = item['id'];
|
||||
var price = item['price'];
|
||||
var cost = item['price'];
|
||||
|
||||
$("#pricemodal").data("itemid", id);
|
||||
$("#pricemodalitemname").text(name);
|
||||
$("#pricemodalitemcost").text(cost);
|
||||
$("#pricemodalitemprice").text(price);
|
||||
$("#pricemodalcustomerprice").val(price);
|
||||
}
|
||||
if (q == "") {
|
||||
return;
|
||||
}
|
||||
$.get("action.php", {
|
||||
action: "itemsearch",
|
||||
q: q
|
||||
}, function (data) {
|
||||
if (data['items'].length == 1) {
|
||||
decodeThenSetItem(data['items'][0]);
|
||||
} else if (data['items'].length > 1) {
|
||||
var options = [];
|
||||
for (var i = 0; i < data['items'].length; i++) {
|
||||
var text = data['items'][i]['name'];
|
||||
if (data['items'][i]['price'] != null) {
|
||||
text += " <span class=\"ml-auto\">$" + data['items'][i]['price'] + "</span>";
|
||||
}
|
||||
options.push({"text": text, "val": data['items'][i]['id']});
|
||||
}
|
||||
bschoices(
|
||||
"Multiple Results",
|
||||
"More than one item match the query. Pick the correct one:",
|
||||
options,
|
||||
"Cancel",
|
||||
function (result) {
|
||||
for (var i = 0; i < data['items'].length; i++) {
|
||||
if (data['items'][i]['id'] == result) {
|
||||
decodeThenSetItem(data['items'][i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}).fail(function () {
|
||||
alert("Error");
|
||||
});
|
||||
}
|
||||
|
||||
$("#pricemodalitem").on('keypress', function (e) {
|
||||
if (e.which === 13) {
|
||||
findItem($("#pricemodalitem").val());
|
||||
$("#pricemodalitem").val("");
|
||||
}
|
||||
});
|
||||
|
||||
$("#pricemodalsearch").on("click", function () {
|
||||
findItem($("#pricemodalitem").val());
|
||||
$("#pricemodalitem").val("");
|
||||
});
|
||||
|
||||
$("#addcustomerpricebtn").click(function () {
|
||||
$("#pricemodal").data("itemid", "");
|
||||
$("#pricemodal").modal();
|
||||
});
|
||||
|
||||
$("#pricemodalsave").click(function () {
|
||||
var itemid = $("#pricemodal").data("itemid");
|
||||
var name = $("#pricemodalitemname").text();
|
||||
var cost = $("#pricemodalitemcost").text();
|
||||
var price = $("#pricemodalitemprice").text();
|
||||
var custprice = $("#pricemodalcustomerprice").val();
|
||||
var rownumber = $("#pricingtable tbody tr").length;
|
||||
var html = ''
|
||||
+ '<tr data-itemid="' + itemid + '">'
|
||||
+ ' <td></td>'
|
||||
+ ' <td>'
|
||||
+ ' <div class="btn btn-sm btn-danger deletepricebtn" data-itemid="' + itemid + '"><i class="fas fa-trash"></i> Delete</div>'
|
||||
+ ' </td>'
|
||||
+ ' <td>'
|
||||
+ ' <input type="hidden" name="pricing[' + rownumber + '][item]" value="' + itemid + '" />'
|
||||
+ ' ' + name
|
||||
+ ' </td>'
|
||||
+ ' <td>' + cost + '</td>'
|
||||
+ ' <td>' + price + '</td>'
|
||||
+ ' <td>'
|
||||
+ ' <input type="hidden" name="pricing[' + rownumber + '][price]" value="' + custprice + '" />'
|
||||
+ ' ' + custprice
|
||||
+ ' </td>'
|
||||
+ '</tr>';
|
||||
pricingtable.row.add($(html));
|
||||
pricingtable.draw();
|
||||
$("#pricemodal").modal("hide");
|
||||
})
|
20
static/js/input_type_money.js
Normal file
20
static/js/input_type_money.js
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
$("body").on("keypress", "input[type=money],input[type=number]", function (e) {
|
||||
//console.log(String.fromCharCode(e.which) + "|" + e.which);
|
||||
var c = String.fromCharCode(e.which);
|
||||
var k = e.which;
|
||||
if (/[0-9]|[\.]/.test(c)) {
|
||||
// Numbers and period
|
||||
} else if (k == 0 || k == 8) {
|
||||
// Delete, backspace, etc
|
||||
} else {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
@ -53,21 +53,6 @@ function recalculate() {
|
||||
$("#receiptchange").text(change.toFixed(2));
|
||||
}
|
||||
|
||||
|
||||
$("body").on("keypress", "input[type=money],input[type=number]", function (e) {
|
||||
//console.log(String.fromCharCode(e.which) + "|" + e.which);
|
||||
var c = String.fromCharCode(e.which);
|
||||
var k = e.which;
|
||||
if (/[0-9]|[\.]/.test(c)) {
|
||||
// Numbers and period
|
||||
} else if (k == 0 || k == 8) {
|
||||
// Delete, backspace, etc
|
||||
} else {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Make sure the session doesn't expire
|
||||
setInterval(function () {
|
||||
$.get("action.php", {action: "session_keepalive"});
|
||||
|
Loading…
x
Reference in New Issue
Block a user