more OOP and restructure utils

This commit is contained in:
Thanakorn S
2026-04-22 15:55:18 +07:00
parent 8834d672ba
commit 35dd1a9fce
31 changed files with 1417 additions and 494 deletions
+1
View File
@@ -2,6 +2,7 @@
session_start();
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/WarehouseManager.php';
try {
+1
View File
@@ -2,6 +2,7 @@
session_start();
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/WarehouseManager.php';
try {
@@ -2,6 +2,7 @@
session_start();
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/WarehouseManager.php';
try {
+3 -27
View File
@@ -2,35 +2,11 @@
session_start();
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/Reports.php';
$report = new Reports($pdo2, $company_id);
$sql = "SELECT SUM(total_in) as total_in, SUM(total_out) as total_out, b.min_stock
FROM warehouse_balance a
LEFT JOIN md_product b ON
a.company_id = b.company_id AND
a.product_sku = b.sku
WHERE
a.company_id = :company_id
GROUP BY a.product_sku
";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id
]);
db_check($sth, $answer);
$output = $sth->fetch(PDO::FETCH_ASSOC);
// calculate stock balance
$low_stock = 0;
foreach($output as $key => $value) {
$output[$key]["low_stock"] = ($value["total_in"] - $value["total_out"]) < $value["min_stock"]?true:false;
if ($output[$key]["low_stock"]) {
$low_stock++;
}
}
$answer["output"] = $output;
$answer["low_stock"] = $low_stock;
$answer["low_stock"] = $report->getLowStockCount();
$answer["success"] = 1;
exit(json_encode($answer));
@@ -2,6 +2,7 @@
session_start();
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/WarehouseManager.php';
$id = 0;
$warehouse_id = (int)$data['warehouse'];
@@ -2,6 +2,7 @@
session_start();
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/WarehouseManager.php';
$id = 0;
$warehouse_id = (int)$data['warehouse'];
@@ -2,6 +2,7 @@
session_start();
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/WarehouseManager.php';
$id = 0;
$warehouse_id = (int)$data['warehouse'];
+4 -14
View File
@@ -2,22 +2,12 @@
session_start();
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/Reports.php';
$report = new Reports($pdo2, $company_id);
$sql = "SELECT SUM(capacity) as total_capacity, count(*) as total_warehouse
FROM md_warehouse a
WHERE
a.company_id = :company_id
";
$sth = $pdo2->prepare($sql);
$sth->execute([
":company_id" => $company_id
]);
db_check($sth, $answer);
$output = $sth->fetch(PDO::FETCH_ASSOC);
$answer["output"] = $output;
$answer["total_capacity"] = $report->getTotalCapacity();
$answer["total_warehouse"] = $report->getTotalWarehouse();
$answer["success"] = 1;
exit(json_encode($answer));
+351
View File
@@ -0,0 +1,351 @@
<?php
session_start();
require '../config.php';
require '../include_header.php';
?>
<body>
<?php require '../include_topbar.php';?>
<?php require '../include_sidebar.php';?>
<!-- MAIN CONTENT -->
<main id="content" class="content py-15">
<div class="container-fluid">
<div class="row ">
<div class="col-12">
<div class="mb-6 ">
<h1 class="fs-3 mb-1">Expired / Near Expiry Products
</h1>
<p class="mb-0">Monitor and manage products approaching or past expiry dates</p>
</div>
</div>
</div>
<div class="row mb-5 g-5">
<div class="col-xl-3 col-md-6 col-12">
<div class="card bg-primary bg-opacity-10 border-primary border-opacity-25">
<div class="card-body p-5">
<div class="">
<span class="icon-shape icon-md bg-primary text-white rounded-2">
<i class="ti ti-trash fs-4"></i>
</span>
</div>
<div class="d-flex flex-column mt-3">
<span class="fs-2 fw-bold mb-0 d-block">3</span>
<span class="fs-5">Expired Products</span>
<small class="text-muted">
Requires immediate action</small>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 col-12">
<div class="card bg-primary bg-opacity-10 border-primary border-opacity-25">
<div class="card-body p-5">
<div class="">
<span class="icon-shape icon-md bg-primary text-white rounded-2">
<i class="ti ti-alert-triangle fs-4"></i>
</span>
</div>
<div class="d-flex flex-column mt-3">
<span class="fs-2 fw-bold mb-0 d-block">2</span>
<span class="fs-5">Critical (≤7 days)</span>
<small class="text-muted">
Expiring within a week</small>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 col-12">
<div class="card bg-primary bg-opacity-10 border-primary border-opacity-25">
<div class="card-body p-5">
<div class="">
<span class="icon-shape icon-md bg-primary text-white rounded-2">
<i class="ti ti-clock fs-4"></i>
</span>
</div>
<div class="d-flex flex-column mt-3">
<span class="fs-2 fw-bold mb-0 d-block">2</span>
<span class="fs-5">Warning (8-14 days)</span>
<small class="text-muted">
Expiring in 2 weeks</small>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 col-12">
<div class="card bg-primary bg-opacity-10 border-primary border-opacity-25">
<div class="card-body p-5">
<div class="">
<span class="icon-shape icon-md bg-primary text-white rounded-2">
<i class="ti ti-calendar-clock fs-4"></i>
</span>
</div>
<div class="d-flex flex-column mt-3">
<span class="fs-2 fw-bold mb-0 d-block">2</span>
<span class="fs-5">Caution (15-30 days)</span>
<small class="text-muted">
Monitor closely</small>
</div>
</div>
</div>
</div>
</div>
<div class="row g-5 mb-5">
<div class="col-12">
<div class="card">
<div class="card-body p-5">
<h2 class="fs-4 mb-4">Filter Products</h2>
<div class="row g-5">
<div class="col-lg-7">
<div class="position-relative">
<input type="search" class="form-control ps-9" placeholder="Search by product name or SKU">
<span class="position-absolute top-25 ms-4">
<i class="ti ti-search text-muted"></i>
</span>
</div>
</div>
<div class="col-lg-5">
<div class="d-flex gap-3">
<select class="form-select">
<option selected>All Status</option>
<option value="Expired">Expired</option>
<option value="Critical">Critical</option>
<option value="Warning">Warning</option>
<option value="Caution">Caution</option>
</select>
<select class="form-select">
<option selected>All Categories</option>
<option value="Category 1">Category 1</option>
<option value="Category 2">Category 2</option>
<option value="Category 3">Category 3</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row g-5 mb-5">
<div class="col-12">
<div class="card ">
<div class="card-body p-5">
<div>
<h2 class="fs-4 mb-2">Expired Products</h2>
<p>Products that have passed their expiry date and need to be removed</p>
</div>
<div class="table-responsive">
<table class="table mb-0 text-nowrap table-hover table-centered">
<thead class="table-light">
<tr>
<th class="py-3">Product Name</th>
<th class="py-3">SKU</th>
<th class="py-3">Category</th>
<th class="py-3">Expiry Date</th>
<th class="py-3">Days Overdue</th>
<th class="py-3">Quantity</th>
<th class="py-3">Status</th>
<th class="py-3">Action</th>
</tr>
</thead>
<tbody>
<tr>
<td class="py-3">Wireless Mouse</td>
<td class="py-3">WM-001</td>
<td class="py-3">Electronics</td>
<td class="py-3">2025-11-15</td>
<td class="py-3">47 days</td>
<td class="py-3">12</td>
<td class="py-3"><span class="badge bg-danger">Expired</span></td>
<td class="py-3">
<a href="#" class="link-danger"><i class="ti ti-trash ms-2 fs-5"></i></a>
</td>
</tr>
<tr>
<td class="py-3">USB-C Cable</td>
<td class="py-3">UC-002</td>
<td class="py-3">Accessories</td>
<td class="py-3">2025-12-01</td>
<td class="py-3">31 days</td>
<td class="py-3">8</td>
<td class="py-3"><span class="badge bg-danger">Expired</span></td>
<td class="py-3">
<a href="#" class="link-danger"><i class="ti ti-trash ms-2 fs-5"></i></a>
</td>
</tr>
<tr>
<td class="py-3">Keyboard</td>
<td class="py-3">KB-004</td>
<td class="py-3">Electronics</td>
<td class="py-3">2025-12-20</td>
<td class="py-3">12 days</td>
<td class="py-3">5</td>
<td class="py-3"><span class="badge bg-danger">Expired</span></td>
<td class="py-3">
<a href="#" class="link-danger"><i class="ti ti-trash ms-2 fs-5"></i></a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="row g-5">
<div class="col-12">
<div class="card ">
<div class="card-body p-5">
<div>
<h2 class="fs-4 mb-2">Near Expiry Products</h2>
<p>Products approaching their expiry date that may need attention</p>
</div>
<div class="table-responsive">
<table class="table mb-0 text-nowrap table-hover table-centered">
<thead class="table-light">
<tr>
<th class="py-3">Product Name</th>
<th class="py-3">SKU</th>
<th class="py-3">Category</th>
<th class="py-3">Expiry Date</th>
<th class="py-3">Days Remaining</th>
<th class="py-3">Quantity</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td class="py-3">Laptop Stand</td>
<td class="py-3">LS-003</td>
<td class="py-3">Furniture</td>
<td class="py-3">2026-01-05</td>
<td class="py-3 text-primary">4 days</td>
<td class="py-3">15</td>
<td class="py-3"><span class="badge bg-primary">Critical (≤7 days)</span></td>
<td class="py-3">
<a href="#" class="btn btn-light">Mark For Sale</a>
</td>
</tr>
<tr>
<td class="py-3">Monitor</td>
<td class="py-3"> MN-005</td>
<td class="py-3">Electronics</td>
<td class="py-3">2026-01-08</td>
<td class="py-3">7 days</td>
<td class="py-3">10</td>
<td class="py-3"><span class="badge bg-primary">Critical (≤7 days)</span></td>
<td class="py-3">
<a href="#" class="btn btn-light">Mark For Sale</a>
</td>
</tr>
<tr>
<td class="py-3">Desk Lamp</td>
<td class="py-3">DL-006</td>
<td class="py-3">Furniture</td>
<td class="py-3">2026-01-12</td>
<td class="py-3">11 days</td>
<td class="py-3">20</td>
<td class="py-3"><span class="badge bg-warning">Warning (8-14 days)</span></td>
<td class="py-3">
<a href="#" class="btn btn-light">Mark For Sale</a>
</td>
</tr>
<tr>
<td class="py-3">Webcam HD</td>
<td class="py-3">WC-007</td>
<td class="py-3">Electronics</td>
<td class="py-3">2026-01-18</td>
<td class="py-3">17 days</td>
<td class="py-3">18</td>
<td class="py-3"><span class="badge bg-warning">Caution (15-30 days)</span></td>
<td class="py-3">
<a href="#" class="btn btn-light">Mark For Sale</a>
</td>
</tr>
<tr>
<td class="py-3">HDMI Cable</td>
<td class="py-3">HD-008</td>
<td class="py-3">Accessories</td>
<td class="py-3">2026-01-25</td>
<td class="py-3">24 days</td>
<td class="py-3">30</td>
<td class="py-3"><span class="badge bg-warning">Caution (15-30 days)</span></td>
<td class="py-3">
<a href="#" class="btn btn-light">Mark For Sale</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<footer class="text-center py-2 mt-6 text-secondary ">
<p class="mb-0">Copyright © 2026 InApp Inventory Dashboard. Developed by <a href="https://codescandy.com/"
target="_blank" class="text-primary">CodesCandy</a> </p>
</footer>
</div>
</div>
<div class="position-fixed end-0 bottom-0 m-4">
<a href="https://codescandy.com/template/inventory-admin-dashboard-template/" class="btn btn-dark"
target="_blank"> Download Now</a>
</div>
</div>
</main>
<?php require "../include_ending.php";?>
<!-- Bootstrap JS -->
</body>
</html>
+203
View File
@@ -0,0 +1,203 @@
<?php
session_start();
require '../config.php';
require '../include_header.php';
?>
<body>
<?php require '../include_topbar.php';?>
<?php require '../include_sidebar.php';?>
<!-- MAIN CONTENT -->
<main id="content" class="content py-15">
<div class="container-fluid">
<div class="row ">
<div class="col-12">
<div class="mb-6 d-flex justify-content-between align-items-center">
<h1 class="fs-3 mb-0">Low Stock Products
</h1>
<a href="#!" class="btn btn-primary">
<span><i class="ti ti-plus"></i></span>
<span>Restock All</span></a>
</div>
</div>
</div>
<div class="row mb-5 g-5">
<div class="col-lg-4 col-12">
<div class="card border border-warning border-opacity-25">
<div class="card-body p-5">
<div class="d-flex justify-content-between align-items-center">
<span>Total Low Stock</span>
<span>
<i class="ti ti-alert-triangle fs-3 text-warning"></i>
</span>
</div>
<div class="d-flex flex-column mt-3">
<span class="fs-3 fw-bold mb-0 d-block text-warning">6</span>
<small class="text-muted">
Products need attention</small>
</div>
</div>
</div>
</div>
<div class="col-lg-4 col-12">
<div class="card border border-danger border-opacity-25">
<div class="card-body p-5">
<div class="d-flex justify-content-between align-items-center">
<span>Critical Level</span>
<span>
<i class="ti ti-activity-heartbeat fs-3 text-danger"></i>
</span>
</div>
<div class="d-flex flex-column mt-3">
<span class="fs-3 fw-bold mb-0 d-block text-danger">3</span>
<small class="text-muted">
Immediate restock needed</small>
</div>
</div>
</div>
</div>
<div class="col-lg-4 col-12">
<div class="card border border-success border-opacity-25">
<div class="card-body p-5">
<div class="d-flex justify-content-between align-items-center">
<span>Warning Level</span>
<span>
<i class="ti ti-box-seam fs-3 text-success"></i>
</span>
</div>
<div class="d-flex flex-column mt-3">
<span class="fs-3 fw-bold mb-0 d-block text-success">3</span>
<small class="text-muted">
Restock soon</small>
</div>
</div>
</div>
</div>
</div>
<div class="row g-5">
<div class="col-12">
<div class="card">
<div class="card-body p-5">
<h2 class="mb-4 fs-5">Low Stock Items</h2>
<div class="table-responsive">
<table class="table table-hover mb-0 table-centered">
<thead class="table-light">
<tr>
<th>Product</th>
<th>SKU</th>
<th>Current Stock</th>
<th>Min Stock</th>
<th>Warehouse</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td class="py-3">Product A</td>
<td class="py-3 text-secondary">SKU-001</td>
<td class="py-3 text-danger">5</td>
<td class="py-3">20</td>
<td class="py-3">Main Warehouse</td>
<td class="py-3"><span class="badge bg-danger rounded-pill">Critical</span></td>
<td class="py-3"><a href="#!" class="btn btn-sm btn-secondary">Restock</a></td>
</tr>
</td>
</tr>
<tr>
<td class="py-3">Product B</td>
<td class="py-3 text-secondary">SKU-002</td>
<td class="py-3 text-warning">12</td>
<td class="py-3">25</td>
<td class="py-3">Main Warehouse</td>
<td class="py-3"><span
class="badge bg-secondary bg-opacity-10 text-dark rounded-pill">Warning</span></td>
<td class="py-3"><a href="#!" class="btn btn-sm btn-secondary">Restock</a></td>
</tr>
</td>
</tr>
<tr>
<td class="py-3">Product C</td>
<td class="py-3 text-secondary">SKU-003</td>
<td class="py-3 text-danger">3</td>
<td class="py-3">15</td>
<td class="py-3">Secondary Warehouse</td>
<td class="py-3"><span class="badge bg-danger rounded-pill">Critical</span></td>
<td class="py-3"><a href="#!" class="btn btn-sm btn-secondary">Restock</a></td>
</tr>
</td>
</tr>
<tr>
<td class="py-3">Product D</td>
<td class="py-3 text-secondary">SKU-004</td>
<td class="py-3 text-warning">18</td>
<td class="py-3">30</td>
<td class="py-3">Main Warehouse</td>
<td class="py-3"><span
class="badge bg-secondary bg-opacity-10 text-dark rounded-pill">Warning</span></td>
<td class="py-3"><a href="#!" class="btn btn-sm btn-secondary">Restock</a></td>
</tr>
</td>
</tr>
<tr>
<td class="py-3">Product E</td>
<td class="py-3 text-secondary">SKU-005</td>
<td class="py-3 text-danger">2</td>
<td class="py-3">10</td>
<td class="py-3">Secondary Warehouse</td>
<td class="py-3"><span class="badge bg-danger rounded-pill">Critical</span></td>
<td class="py-3"><a href="#!" class="btn btn-sm btn-secondary">Restock</a></td>
</tr>
</td>
</tr>
<tr>
<td class="py-3">Product F</td>
<td class="py-3 text-secondary">SKU-006</td>
<td class="py-3 text-warning">8</td>
<td class="py-3">20</td>
<td class="py-3">Main Warehouse</td>
<td class="py-3"><span
class="badge bg-secondary bg-opacity-10 text-dark rounded-pill">Warning</span></td>
<td class="py-3"><a href="#!" class="btn btn-sm btn-secondary">Restock</a></td>
</tr>
</td>
</tr>
<!-- Table rows will be dynamically populated here -->
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<?php require "../include_ending.php";?>
<!-- Bootstrap JS -->
</body>
</html>
+2 -4
View File
@@ -198,8 +198,8 @@
action: 'read',
onSuccess: function(res) {
$("#capacity h3").text(format_number(res.output.total_capacity, 2));
$("#capacity p").text("Accross " + format_number(res.output.total_warehouse) + " warehouses");
$("#capacity h3").text(format_number(res.total_capacity, 2));
$("#capacity p").text("Accross " + format_number(res.total_warehouse) + " warehouses");
$("#capacity .card-loader-overlay").hide();
}
@@ -219,8 +219,6 @@
action: 'read',
onSuccess: function(res) {
console.log(res);
$("#total_stock_in h3").text(format_number(res.output.total_in, 2));
$("#total_stock_in p").text("Accross " + format_number(res.output.total_warehouse) + " warehouses");
$("#total_stock_in .card-loader-overlay").hide();