Files
YMS/webgui/inventory.php
T
2024-04-30 19:38:28 +02:00

414 lines
14 KiB
PHP

<?php
/******************************************************************************
* YMS - Yacht Management Software
* Copyright (C) 2024 Thomas Hooge
*
* SPDX-License-Identifier: WTFPL
******************************************************************************/
require 'globals.inc';
$pagetitle=_('Inventory');
$id = gpc_get_int($_REQUEST, 'id', 0);
$opt_storage = db_get_opt_storage($user->vid);
$opt_box = db_get_opt_box($user->vid);
$opt_invcond = db_load_enum('inventory', 'invcond', true, true);
// ========== ACTIONS START ===================================================
switch ($submit = form_get_action()) {
case NULL: break;
case 'add': $action = ACT_ADD; break;
case 'view': $action = ACT_VIEW; break;
case 'edit': $action = ACT_EDIT; break;
case 'del': $action = ACT_DELETE; break;
case 'filter':
$flt = array();
$flt['stor'] = gpc_get_string($_POST, 'flt_stor');
//$flt['box'] = gpc_get_string($_POST, 'flt_box');
$flt['cond'] = gpc_get_string($_POST, 'flt_cond');
$flt['txt'] = gpc_get_string($_POST, 'flt_txt');
db_save_filter($flt, 201);
$action = ACT_DEFAULT;
break;
case 'insert':
$p[':invname'] = gpc_get_string($_POST, 'invname');
$p[':number'] = gpc_get_int($_POST, 'number');
$p[':conttype'] = gpc_get_string($_POST, 'conttype');
$p[':sid'] = gpc_get_int($_POST, 'sid');
$p[':boxid'] = gpc_get_int($_POST, 'boxid');
$p[':invcond'] = 'good';
$id = db_exec_insert('inventory', $p);
$action = ACT_VIEW;
break;
case 'update':
$p[':invid'] = $id;
$p[':invname'] = gpc_get_string($_POST, 'invname');
$p[':number'] = gpc_get_int($_POST, 'number');
$p[':conttype'] = gpc_get_string($_POST, 'conttype');
$p[':sid'] = gpc_get_int($_POST, 'sid');
$p[':boxid'] = gpc_get_int($_POST, 'boxid');
$p[':weight'] = min(gpc_get_float($_POST, 'weight'), 999.99); // limit max value
$p[':price'] = gpc_get_currency($_POST, 'price');
$p[':purchdate'] = gpc_get_date($_POST, 'purchdate');
$p[':invcond'] = gpc_get_string($_POST, 'invcond');
$p[':remarks'] = gpc_get_string($_POST, 'remarks', 150);
db_exec_update('inventory', $p, 'invid');
$action = ACT_VIEW;
break;
case 'delete':
// Security token needed!
if (gpc_get_string($_POST, 'token', 16) != $_SESSION['token']) {
$g_error->Add(_('Delete prohibited, invalid security token!'));
$action = ACT_VIEW;
break;
}
unset($_SESSION['token']);
$sth = $pdo->prepare("DELETE FROM inventory WHERE invid=?");
$sth->execute([$id]);
$g_message->Add(sprintf(_('Deleted inventory no. %d'), $id));
$action = ACT_DEFAULT;
break;
default:
$g_error->Add(sprintf(_('Unknown function!'), $submit));
$valid = FALSE;
}
// ========== ACTIONS END =====================================================
require 'header.php';
// ========== PAGE CONTENT ====================================================
if ($action == ACT_DEFAULT):
// ========== VARIANT: default behavior =======================================
$flt = db_get_filter($user->id, 201);
/*
The only way to find out whether the inventory is on the current boat is to use
the box assignment. But this is also intentional to allow easy rearrangement.
*/
echo "<h1>$pagetitle</h1>\n";
$w = array('vid=:vid');
$p = array(':vid' => $user->vid);
if ($flt->stor == -1) {
$w[] = 'i.sid IS NULL';
} elseif ($flt->stor > 0) {
$w[] = 'i.sid=:sid';
$p[':sid'] = $flt->stor;
}
/*if ($flt->cond <> 'all') {
$w[] = 'indcond=:indcond';
$p[':indcond'] = $flt->cond;
}*/
if (strlen($flt->txt) > 1) {
$w[] = 'invname LIKE :txt';
$p[':txt'] = '%'.$flt->txt.'%';
}
$where = join(' AND ', $w);
$order = ' ORDER BY invname';
$sql = "SELECT i.invid, i.invname, i.number, i.invcond, s.sname AS container "
. "FROM inventory AS i JOIN storage AS s ON (i.conttype='storage' AND i.sid=s.sid)";
$sql .= ' WHERE ' . $where;
$sql .= " UNION SELECT i.invid, i.invname, i.number, i.invcond, b.label AS container "
. "FROM inventory AS i JOIN box AS b ON (i.conttype='box' AND i.boxid=b.boxid) "
. " JOIN storage AS s ON (b.sid=s.sid) ";
$sql .= ' WHERE ' . $where;
$sql .= $order;
$sth = $pdo->prepare($sql);
try {
$sth->execute($p);
} catch(PDOException $e) {
$g_error->Add($e->getMessage());
$g_error->Add($sql);
$g_error->Add(print_r($p, true));
}
$res = $sth->fetchAll();
// Filter
$opt_special = array(
-2 => _('&horbar; all &horbar;'),
-1 => _('&horbar; none &horbar;')
);
?>
<form method="post" action="<?=$g_scriptname?>">
<div id="filter" class="card">
<div class="card-header">Filter</div>
<div class="card-body">
<?php
// page specific filter start
// - selection for storage
// - selection for box
// page specific filter end
?>
<label for="flt_stor"><?=_('Storage')?></label>
<select id="flt_stor" name="flt_stor">
<?php
foreach ($opt_special + $opt_storage as $k => $v) {
echo '<option value="', $k,'"';
if ($k == $flt->stor) {
echo ' selected';
}
echo '>', $v, '</option>';
}
?>
</select>
<label for="flt_cond"><?=_('Condition')?></label>
<select id="flt_cond" name="flt_cond">
<?php
foreach ($opt_special + $opt_invcond as $k => $v) {
echo '<option value="', $k,'"';
if ($k == $flt->cond) {
echo ' selected';
}
echo '>', $v, '</option>';
}
?>
</select>
<label for="flt_txt">Text</label>
<input type="text" name="flt_txt" size="15" maxlength="30" value="<?=$flt->txt?>">
<button name="submit[filter]" class="btn btn-sm btn-primary" title="<?=_('Apply')?>"><?=_('Go')?></button>
</div>
</div>
</form>
<?php
echo '<table class="table table-striped">', "\n";
echo "<thead>\n";
echo "<tr>\n";
echo "<th>", _('Name'), "</th>\n";
echo "<th>", _('Container'), "</th>\n";
echo "<th>", _('Number'), "</th>\n";
echo "<th>", _('Condition'), "</th>\n";
echo "<th>", _('Tags'), "</th>\n";
echo "<td></td>\n";
echo "</tr>\n";
echo "</thead>\n";
foreach ($res as $row) {
echo "<tr>\n";
echo '<td>', $row['invname'], "</td>\n";
echo "<td>", $row['container'], "</td>\n";
echo "<td>", $row['number'], "</td>\n";
echo "<td>", ($opt_invcond[$row['invcond']] ?? ''), "</td>\n";
echo "<td>", _('No tags assigned'), "</td>\n";
form_action_buttons($g_scriptname, $row['invid']);
echo "</tr>\n";
}
// Table summary
echo "<tfoot>\n";
echo '<tr><td colspan="5">', sprintf(_('%d records'), count($res)), '</td></tr>', "\n";
echo "</tfoot>\n";
echo "</table>\n";
form_add_button($g_scriptname);
elseif ($action == ACT_ADD):
// ========== VARIANT: add record =============================================
echo '<h2>', _('Add Inventory'), "</h2>\n";
?>
<form method="post" action="<?=$g_scriptname?>">
<div class="mb-3">
<label for="invname" class="form-label"><?=_('Name')?></label>
<input type="text" class="form-control" id="invname" name="invname">
</div>
<div class="mb-3">
<label for="number" class="form-label"><?=_('Number')?></label>
<input type="number" class="form-control" id="number" name="number" value="1">
</div>
<div class="mb-3">
<label for="conttype" class="form-label"><?=_('Container type')?></label>
<select class="form-select" name="conttype" id="conttype">
<option value="box"><?=_('Box')?></option>
<option value="storage"><?=_('Storage')?></option>
</select>
</div>
<?php
form_create_select('sid', _('Storage'), $opt_storage);
form_create_select('boxid', _('Box'), $opt_box);
?>
<div class="container-fluid px-0 my-3">
<button type="submit" name="submit[insert]" class="btn btn-primary"><?=_('Save')?></button>
<a href="<?=$g_scriptname?>" class="btn btn-secondary"><?=_('Back')?></a>
</div>
</form>
<?php
elseif ($action == ACT_VIEW):
// ========== VARIANT: view single record =====================================
$sql = "SELECT invname, conttype, sid, boxid, number, weight, price, purchdate,"
. " invcond, remarks "
. "FROM inventory "
. "WHERE invid=?";
$sth = $pdo->prepare($sql);
$sth->execute([$id]);
$inventory = $sth->fetch(PDO::FETCH_OBJ);
// container type can be storage or box
switch ($inventory->conttype) {
case 'storage':
$sql = "SELECT sname, vid FROM storage WHERE sid=?";
$sth = $pdo->prepare($sql);
$sth->execute([$inventory->sid]);
$row = $sth->fetch();
$storagename = $row['sname'];
$vid = $row['vid'];
break;
case 'box':
// Future: Boxes can also be nested!
// Recursive Function "get_storage_for_box()"
$sql = "SELECT sid, label FROM box WHERE boxid=?";
// TODO Load additional box data
$sth = $pdo->prepare($sql);
$sth->execute([$inventory->boxid]);
$box = $sth->fetch();
$sql = "SELECT sname, vid FROM storage WHERE sid=?";
$sth = $pdo->prepare($sql);
$sth->execute([$box['sid']]);
$row = $sth->fetch();
$storagename = $row['sname'];
$vid = $row['vid'];
break;
}
echo '<h2>', $inventory->invname, "</h2>\n";
echo '<table class="table">', "\n";
echo '<tr><th style="width:20%">', _('Box type'),"</th><td>", $inventory->conttype, "</td></tr>\n";
// Container with link
echo "<tr><th>", _('Container'),"</th><td>", sprintf(_('%s in %s'), $box['label'], $storagename);
echo "</td></tr>\n";
echo "<tr><th>", _('Location ID'), "</th><td>", $inventory->locationid, "</td></tr>\n";
echo "<tr><th>", _('Number'), "</th><td>", $inventory->number, "</td></tr>\n";
echo "<tr><th>", _('Weight'), "</th><td>", format_float($inventory->weight, 2, 'kg'), "</td></tr>\n";
echo "<tr><th>", _('Price'), "</th><td>", format_currency($inventory->price), "</td></tr>\n";
echo "<tr><th>", _('Purchase date'), "</th><td>", $inventory->purchdate, "</td></tr>\n";
echo "<tr><th>", _('Condition'), "</th><td>", $inventory->invcond, "</td></tr>\n";
echo "<tr><th>", _('Remarks'), "</th><td>", $inventory->remarks, "</td></tr>\n";
form_tag_assignment($g_scriptname, $id);
echo "</table>\n";
form_view_buttons($g_scriptname, $id);
elseif ($action == ACT_EDIT):
// ========== VARIANT: edit single record =====================================
$sql = "SELECT invname, conttype, sid, boxid, number, weight, price, purchdate, "
. " invcond, remarks "
. "FROM inventory "
. "WHERE invid=?";
$sth = $pdo->prepare($sql);
$sth->execute([$id]);
$inventory = $sth->fetch(PDO::FETCH_OBJ);
?>
<h2><?=_('Edit Inventory')?></h2>
<form method="post" action="<?=$g_scriptname?>">
<input type="hidden" name="id" value="<?=$id?>">
<div class="mb-3">
<label for="invname" class="form-label"><?=_('Name')?></label>
<input type="text" class="form-control" id="invname" name="invname" value="<?=$inventory->invname ?>">
</div>
<div class="mb-3">
<label for="number" class="form-label"><?=_('Number')?></label>
<input type="number" class="form-control" id="number" name="number" value="<?=$inventory->number ?>">
</div>
<div class="mb-3">
<label for="weight" class="form-label"><?=_('Weight, kg')?></label>
<input type="text" class="form-control" id="weight" name="weight" value="<?=format_float($inventory->weight); ?>">
</div>
<div class="mb-3">
<label for="conttype" class="form-label"><?=_('Container type')?></label>
<select class="form-select" name="conttype" id="conttype">
<option value="box"><?=_('Box')?></option>
<option value="storage"><?=_('Storage')?></option>
</select>
</div>
<?php
form_create_select('sid', _('Storage'), $opt_storage, $inventory->sid);
form_create_select('boxid', _('Box'), $opt_box, $inventory->boxid);
?>
<div class="mb-3">
<label for="price" class="form-label"><?=sprintf(_('Price, %s'), $g_lconv['currency_symbol']); ?></label>
<input type="text" class="form-control" id="price" name="price" value="<?=format_float($inventory->price) ?>">
</div>
<div class="mb-3">
<label for="purchdate"><?=_('Purchase date')?></label>
<input type="date" class="form-control" id="purchdate" name="purchdate" value="<?=$inventory->purchdate ?>">
</div>
<div class="mb-3">
<label for="invcond" class="form-label"><?=_('Condition')?></label>
<select name="invcond" id="invcond" class="form-control">
<?php
$cond = array(
'good' => _('Good'),
'normal' => _('Normal'),
'bad' => _('Bad'),
'repairable' => _('Repairable'),
'defect' => _('Defect'),
'unknown' => _('Unknown')
);
foreach ($cond as $k => $v) {
echo '<option value="', $k, '"';
if ($k == $inventory->invcond) {
echo ' selected';
}
echo '>', $v. "</option>\n";
}
?>
</select>
</div>
<div class="mb-3">
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
<textarea class="form-control" id="remarks" name="remarks" rows="3"><?=$inventory->remarks ?></textarea>
</div>
<?php
form_edit_buttons($g_scriptname, $id);
echo "</form>\n";
elseif ($action == ACT_DELETE):
// ========== VARIANT: delete record ==========================================
$sql = "SELECT invname FROM inventory WHERE invid=?";
$sth = $pdo->prepare($sql);
$sth->execute([$id]);
$inventory = $sth->fetch(PDO::FETCH_OBJ);
echo '<h2>', _('Delete Inventory'), "</h2>\n";
echo '<p>', sprintf(_('Record no. %d'), $id), "</p>\n";
echo '<p>Name: ', $inventory->invname, "</p>";
echo '<p>', _('Deleting an inventory item is final. There is no way back. Only delete if you are absolute sure.'), "</p>\n";
$_SESSION['token'] = bin2hex(random_bytes(8));
form_delete_buttons($g_scriptname, $id, $_SESSION['token']);
else:
// ========== ERROR UNKNOWN VARIANT ===========================================
echo '<p>', _('Unknown function call: Please report to system development!'), "</p>\n";
endif; // $action == ...
// ========== END OF VARIANTS =================================================
include 'footer.php';