Browse Source

Add basic stock management

stock_management
João Andrade 2 years ago
parent
commit
8964202a1a
  1. 60
      action.php
  2. 22
      database.sql
  3. 4
      langs/en/actions.json
  4. 6
      langs/en/items.json
  5. 4
      langs/en/messages.json
  6. 8
      langs/messages.php
  7. 4
      lib/getitemtable.php
  8. 22
      pages.php
  9. 77
      pages/addstock.php
  10. 14
      pages/edititem.php
  11. 77
      pages/removestock.php
  12. 4
      static/js/items.js

60
action.php

@ -363,4 +363,64 @@ switch ($VARS['action']) {
session_destroy();
header('Location: index.php?logout=1');
die("Logged out.");
case "addstock":
$insert = true;
if (empty($VARS['stock'])) {
$VARS['stock'] = 1;
} else if (!is_numeric($VARS['stock'])) {
returnToSender('field_nan');
}
$user = $_SESSION['uid'];
$data = [
'itemid' => $VARS['itemid'],
'stock' => $VARS['stock'],
'text1' => $VARS['text1'],
'userid' => $user
];
$database->insert('stock', $data);
$currentqty = $database->get('items', 'qty', ['itemid' => $VARS['itemid']]);
$newqty = $currentqty + $VARS['stock'];
$data = [
'qty' => $newqty
];
$database->update('items', $data, ['itemid' => $VARS['itemid']]);
returnToSender("stock_added");
case "removestock":
$insert = true;
if (empty($VARS['stock'])) {
$VARS['stock'] = -1;
} else if (!is_numeric($VARS['stock'])) {
returnToSender('field_nan');
}
$user = $_SESSION['uid'];
$data = [
'itemid' => $VARS['itemid'],
'stock' => -$VARS['stock'],
'text1' => $VARS['text1'],
'userid' => $user
];
$database->insert('stock', $data);
$currentqty = $database->get('items', 'qty', ['itemid' => $VARS['itemid']]);
$newqty = $currentqty - $VARS['stock'];
$data = [
'qty' => $newqty
];
$database->update('items', $data, ['itemid' => $VARS['itemid']]);
returnToSender("stock_removed");
}

22
database.sql

@ -70,6 +70,27 @@ CREATE TABLE IF NOT EXISTS `items` (
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `stock`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `stock` (
`stockid` INT NOT NULL AUTO_INCREMENT,
`timestamp` TIMESTAMP,
`itemid` INT NOT NULL,
`stock` INT NOT NULL,
`text1` TEXT(500) NOT NULL,
`userid` INT NOT NULL,
PRIMARY KEY (`stockid`),
-- INDEX `fk_items_stock_idx` (`stockid` ASC),
UNIQUE INDEX `stockid_UNIQUE` (`stockid` ASC),
CONSTRAINT `fk_items_stock`
FOREIGN KEY (`itemid`)
REFERENCES `items` (`itemid`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `labels`
-- -----------------------------------------------------
@ -148,4 +169,3 @@ INSERT INTO `labels` (`rowid`, `name`, `value`) VALUES (8, 'itemtext3', 'Text Va
INSERT INTO `labels` (`rowid`, `name`, `value`) VALUES (9, 'catname', 'Category Name');
COMMIT;

4
langs/en/actions.json

@ -4,5 +4,7 @@
"save": "Save",
"delete": "Delete",
"view": "View",
"show all items": "Show All Items"
"show all items": "Show All Items",
"addstock": "Add",
"removestock": "Remove"
}

6
langs/en/items.json

@ -9,5 +9,9 @@
"cloning item": "Copying {oitem} <i class=\"fa fa-angle-right\"></i> {nitem}",
"itemid": "Item ID",
"id": "ID",
"Edit Item": "Edit Item"
"Edit Item": "Edit Item",
"Adding stock": "Adding stock",
"adding stock": "Adding stock for {item}",
"Removing stock": "Removing stock",
"removing stock": "Removing stock from {item}"
}

4
langs/en/messages.json

@ -17,5 +17,7 @@
"only showing understocked": "Only showing understocked items.",
"missing name": "You need to enter a name.",
"use the dropdowns": "Whoops, you need to use the category and location autocomplete boxes.",
"make categories and locations": "Please create at least one category and location before adding an item."
"make categories and locations": "Please create at least one category and location before adding an item.",
"stock added": "Stock added.",
"stock removed": "Stock removed."
}

8
langs/messages.php

@ -96,5 +96,13 @@ define("MESSAGES", [
"upload_success" => [
"string" => "Image uploaded.",
"type" => "success"
],
"stock_added" => [
"string" => "stock added",
"type" => "success"
],
"stock_removed" => [
"string" => "stock removed",
"type" => "success"
]
]);

4
lib/getitemtable.php

@ -118,8 +118,12 @@ for ($i = 0; $i < count($items); $i++) {
$user = new User($_SESSION['uid']);
if ($user->hasPermission("INV_EDIT")) {
$items[$i]["editbtn"] = '<a class="btn btn-primary" href="app.php?page=edititem&id=' . $items[$i]['itemid'] . '"><i class="fas fa-edit"></i> ' . $Strings->get("edit", false) . '</a>';
$items[$i]["addstockbtn"] = '<a class="btn btn-success" href="app.php?page=addstock&id=' . $items[$i]['itemid'] . '"><i class="fas fa-plus"></i> ' . $Strings->get("addstock", false) . '</a>';
$items[$i]["removestockbtn"] = '<a class="btn btn-danger" href="app.php?page=removestock&id=' . $items[$i]['itemid'] . '"><i class="fas fa-minus"></i> ' . $Strings->get("removestock", false) . '</a>';
} else {
$items[$i]["editbtn"] = '';
$items[$i]["addstockbtn"] = '';
$items[$i]["removestockbtn"] = '';
}
$items[$i]["viewbtn"] = '<a class="btn btn-info" href="app.php?page=item&id=' . $items[$i]['itemid'] . '"><i class="fas fa-eye"></i> ' . $Strings->get("view", false) . '</a>';
if (is_null($items[$i]['userid'])) {

22
pages.php

@ -99,5 +99,27 @@ define("PAGES", [
],
"404" => [
"title" => "404 error"
],
"addstock" => [
"title" => "Add stock",
"navbar" => false,
"styles" => [
"static/css/easy-autocomplete.min.css"
],
"scripts" => [
"static/js/jquery.easy-autocomplete.min.js",
"static/js/edititem.js"
],
],
"removestock" => [
"title" => "Remove stock",
"navbar" => false,
"styles" => [
"static/css/easy-autocomplete.min.css"
],
"scripts" => [
"static/js/jquery.easy-autocomplete.min.js",
"static/js/edititem.js"
],
]
]);

77
pages/addstock.php

@ -0,0 +1,77 @@
<?php
/* 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/. */
require_once __DIR__ . '/../required.php';
redirectifnotloggedin();
if ($database->count("locations") == 0 || $database->count("categories") == 0) {
header('Location: app.php?page=items&msg=noloccat');
die();
}
$itemdata = [
'text1' => '',
'qty' => ''];
if (!empty($VARS['id'])) {
if ($database->has('items', ['itemid' => $VARS['id']])) {
$itemdata = $database->select(
'items', [
'name',
'qty',
], [
'itemid' => $VARS['id']
])[0];
} else {
// item id is invalid, redirect to a page that won't cause an error when pressing Save
header('Location: app.php?page=addstock');
die();
}
}
?>
<form role="form" action="action.php" method="POST">
<div class="card border-green">
<h3 class="card-header text-green">
<i class="fas fa-edit"></i> <?php $Strings->build("adding stock", ['item' => "<span id=\"name_title\">" . htmlspecialchars($itemdata['name']) . "</span>"]); ?>
</h3>
<div class="card-body">
<div class="row">
<div class="col-12 col-md-3">
<div class="form-group">
<label for="stock"><i class="fas fa-hashtag"></i> <?php $Strings->get('quantity'); ?></label>
<input type="number" min="1" class="form-control" id="stock" name="stock" required="required" placeholder="<?php echo $itemdata['qty']; ?>" />
</div>
</div>
</div>
<div class="row">
<div class="col-12 col-md-6">
<div class="form-group">
<label for="info1"><i class="fas fa-info"></i> <?php $Strings->get("Description"); ?></label>
<textarea class="form-control" id="info1" name="text1" required="required"></textarea>
</div>
</div>
</div>
</div>
<input type="hidden" name="itemid" value="<?php
echo htmlspecialchars($VARS['id']);
?>" />
<input type="hidden" name="action" value="addstock" />
<?php
if (isset($_GET['source']) && $_GET['source'] === "item") {
echo '<input type="hidden" name="source" value="item" />';
} else {
echo '<input type="hidden" name="source" value="items" />';
}
?>
<div class="card-footer d-flex">
<button type="submit" class="btn btn-success mr-1"><i class="fas fa-save"></i> <?php $Strings->get("save"); ?></button>
</div>
</div>
</form>

14
pages/edititem.php

@ -164,7 +164,17 @@ if (!empty($VARS['id'])) {
<div class="col-12 col-md-3">
<div class="form-group">
<label for="qty"><i class="fas fa-hashtag"></i> <?php $Strings->get('quantity'); ?></label>
<input type="number" class="form-control" id="qty" name="qty" placeholder="1" value="<?php echo $itemdata['qty']; ?>" />
<?php
if ($editing) {
?>
<input type="text" class="form-control" id="qty" name="qty" readonly value="<?php echo $itemdata['qty']; ?>" />
<?php
} else {
?>
<input type="number" class="form-control" id="qty" name="qty" placeholder="1" value="<?php echo $itemdata['qty']; ?>" />
<?php
}
?>
</div>
</div>
<div class="col-12 col-md-3">
@ -263,4 +273,4 @@ if (!empty($VARS['id'])) {
?>
</div>
</div>
</form>
</form>

77
pages/removestock.php

@ -0,0 +1,77 @@
<?php
/* 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/. */
require_once __DIR__ . '/../required.php';
redirectifnotloggedin();
if ($database->count("locations") == 0 || $database->count("categories") == 0) {
header('Location: app.php?page=items&msg=noloccat');
die();
}
$itemdata = [
'text1' => '',
'qty' => ''];
if (!empty($VARS['id'])) {
if ($database->has('items', ['itemid' => $VARS['id']])) {
$itemdata = $database->select(
'items', [
'name',
'qty',
], [
'itemid' => $VARS['id']
])[0];
} else {
// item id is invalid, redirect to a page that won't cause an error when pressing Save
header('Location: app.php?page=removestock');
die();
}
}
?>
<form role="form" action="action.php" method="POST">
<div class="card border-green">
<h3 class="card-header text-green">
<i class="fas fa-edit"></i> <?php $Strings->build("removing stock", ['item' => "<span id=\"name_title\">" . htmlspecialchars($itemdata['name']) . "</span>"]); ?>
</h3>
<div class="card-body">
<div class="row">
<div class="col-12 col-md-3">
<div class="form-group">
<label for="stock"><i class="fas fa-hashtag"></i> <?php $Strings->get('quantity'); ?></label>
<input type="number" min="1" class="form-control" id="stock" name="stock" required="required" placeholder="<?php echo $itemdata['qty']; ?>" />
</div>
</div>
</div>
<div class="row">
<div class="col-12 col-md-6">
<div class="form-group">
<label for="info1"><i class="fas fa-info"></i> <?php $Strings->get("Description"); ?></label>
<textarea class="form-control" id="info1" name="text1" required="required"></textarea>
</div>
</div>
</div>
</div>
<input type="hidden" name="itemid" value="<?php
echo htmlspecialchars($VARS['id']);
?>" />
<input type="hidden" name="action" value="removestock" />
<?php
if (isset($_GET['source']) && $_GET['source'] === "item") {
echo '<input type="hidden" name="source" value="item" />';
} else {
echo '<input type="hidden" name="source" value="items" />';
}
?>
<div class="card-footer d-flex">
<button type="submit" class="btn btn-success mr-1"><i class="fas fa-save"></i> <?php $Strings->get("save"); ?></button>
</div>
</div>
</form>

4
static/js/items.js

@ -49,7 +49,7 @@ var itemtable = $('#itemtable').DataTable({
json.items.forEach(function (row) {
json.data.push([
"",
"<span class='btn-group-vertical btn-group-sm'>" + row.viewbtn + " " + row.editbtn + "</span>",
"<span class='btn-group btn-group-sm'>" + row.viewbtn + " " + row.editbtn + " " + row.addstockbtn + " " + row.removestockbtn + "</span>"
row.name,
row.catname,
row.locname + " (" + row.loccode + ")",
@ -74,4 +74,4 @@ $(document).ready(function () {
$(searchInput).trigger("input");
$(searchInput).trigger("change");
}
});
});
Loading…
Cancel
Save