dashboart stats: as of date

This commit is contained in:
Thanakorn S
2026-05-13 09:49:15 +07:00
parent 3614b72924
commit 511360faa2
2 changed files with 27 additions and 62 deletions
@@ -3,24 +3,28 @@
require '../../../assets/utils/db_auth.php';
require '../../../assets/utils/classes/ReportManager.php';
$month = $data['month'] ?? date('Y-m');
$month = date('Y-m');
$report = new ReportManager($pdo2, $company_id);
$stats = $report->getDashboardStats($month);
// All-time stock totals
$sth = $pdo2->prepare(
"SELECT
ROUND(COALESCE(SUM(total_in), 0), 2) AS total_in,
ROUND(COALESCE(SUM(total_out), 0), 2) AS total_out
FROM warehouse_balance
WHERE company_id = :company_id"
);
$sth->execute([':company_id' => $company_id]);
$stock_stats = $sth->fetch(PDO::FETCH_ASSOC);
// Sales stats — query td_order and td_invoice directly
$month_start = $month . '-01';
$month_end = date('Y-m-t', strtotime($month_start));
// Total orders this month (excluding cancelled)
// All-time orders (excluding cancelled)
$sth = $pdo2->prepare(
"SELECT COUNT(*), COALESCE(SUM(grand_total), 0)
FROM td_order
WHERE company_id = :company_id
AND status != -1
AND order_date BETWEEN :start AND :end"
WHERE company_id = :company_id
AND status != -1"
);
$sth->execute([':company_id' => $company_id, ':start' => $month_start, ':end' => $month_end]);
$sth->execute([':company_id' => $company_id]);
[$total_orders, $total_revenue] = $sth->fetch(PDO::FETCH_NUM);
// Unpaid invoices (status=0 draft + status=1 issued + status=3 overdue)
@@ -50,9 +54,8 @@
$healthy_count = max(0, $total_in_stock - $critical_count - $warning_count);
$answer['output'] = [
'total_in' => $stats['total_in'],
'total_out' => $stats['total_out'],
'active_products' => $stats['active_products'],
'total_in' => $stock_stats['total_in'],
'total_out' => $stock_stats['total_out'],
'low_stock' => count($low_stock_items),
'total_orders' => (int)$total_orders,
'total_revenue' => (float)$total_revenue,
@@ -62,7 +65,6 @@
'most_moved' => $report->getMostMovedProducts($month),
'low_stock_items' => $low_stock_items,
'recent_activity' => $report->getRecentActivity(10),
'months' => $report->getAvailableMonths(),
'stock_health' => [
'healthy' => $healthy_count,
'warning' => $warning_count,
+10 -47
View File
@@ -20,13 +20,6 @@
<h1 class="fs-3 mb-1">Dashboard</h1>
<p class="mb-0">Inventory overview across all warehouses</p>
</div>
<div class="d-flex align-items-center gap-3">
<label class="mb-0 text-nowrap fw-semibold">Month</label>
<div class="input-group" style="min-width:160px;">
<span class="input-group-text"><i class="ti ti-calendar"></i></span>
<input type="text" id="month_filter" class="form-control" readonly placeholder="Select month" style="cursor:pointer;">
</div>
</div>
</div>
</div>
</div>
@@ -42,7 +35,7 @@
<div>
<h2 class="mb-3 fs-6">Total Stock In</h2>
<h3 class="fw-bold mb-0" id="stat_total_in">—</h3>
<p class="text-warning mb-0 small">Units received this month</p>
<p class="text-warning mb-0 small">Total units received</p>
</div>
</div>
<div class="card-loader-overlay" id="overlay_in">
@@ -59,7 +52,7 @@
<div>
<h2 class="mb-3 fs-6">Total Stock Out</h2>
<h3 class="fw-bold mb-0" id="stat_total_out">—</h3>
<p class="text-danger mb-0 small">Units dispatched this month</p>
<p class="text-danger mb-0 small">Total units dispatched</p>
</div>
</div>
<div class="card-loader-overlay" id="overlay_out">
@@ -76,7 +69,7 @@
<div>
<h2 class="mb-3 fs-6">Total Orders</h2>
<h3 class="fw-bold mb-0" id="stat_total_orders">—</h3>
<p class="text-success mb-0 small">Orders this month</p>
<p class="text-success mb-0 small">All orders to date</p>
</div>
</div>
<div class="card-loader-overlay" id="overlay_orders">
@@ -93,7 +86,7 @@
<div>
<h2 class="mb-3 fs-6">Total Revenue</h2>
<h3 class="fw-bold mb-0" id="stat_total_revenue">—</h3>
<p class="text-info mb-0 small">Grand total this month</p>
<p class="text-info mb-0 small">Grand total to date</p>
</div>
</div>
<div class="card-loader-overlay" id="overlay_revenue">
@@ -233,7 +226,7 @@
<div class="card h-100" style="position:relative;">
<div class="card-header bg-white d-flex justify-content-between align-items-center px-4 py-3">
<h4 class="mb-0 h5">Most Moved Products</h4>
<span class="small text-muted" id="most_moved_month"></span>
<span class="small text-muted">This Month</span>
</div>
<ul class="list-group list-group-flush" id="list_most_moved">
<li class="list-group-item text-center text-muted py-5">Loading...</li>
@@ -295,7 +288,7 @@
// ── Render all sections ───────────────────────────────────────────────
async function render(d, month) {
async function render(d) {
// Stats — top row
$('#stat_total_in').text(format_number(d.total_in, 2));
@@ -305,7 +298,6 @@
$('#overlay_in, #overlay_out, #overlay_orders, #overlay_revenue').hide();
// Stats — secondary row
$('#stat_active_products').text(format_number(d.active_products));
$('#stat_low_stock_count').text(format_number(d.low_stock));
$('#stat_unpaid_invoices').text(format_number(d.unpaid_invoices));
$('#stat_pending_returns').text(format_number(d.pending_returns));
@@ -355,7 +347,7 @@
$('#stat_total_contacts').text(format_number(d.total_contacts || 0));
$('#stat_total_wh').text(format_number(d.total_warehouses || 0));
var sh_series = [healthy_pct, critical_pct];
var sh_series = [healthy_pct, warning_pct + critical_pct];
if (overallChart) {
await overallChart.updateSeries(sh_series);
} else {
@@ -402,14 +394,13 @@
}
},
stroke: { lineCap: 'round' },
labels: ['Healthy', 'Critical']
labels: ['Healthy', 'Warning']
});
await overallChart.render();
}
$('#overlay_overall').hide();
// Most Moved Products
$('#most_moved_month').text(format_month(month));
var moved_html = '';
if (!d.most_moved || d.most_moved.length === 0) {
moved_html = '<li class="list-group-item text-center text-muted py-4">No data for this month.</li>';
@@ -490,11 +481,6 @@
// ── Fetch + render ────────────────────────────────────────────────────
function retrieve_dashboard() {
var fpDate = monthPicker.selectedDates[0];
var month = fpDate
? fpDate.getFullYear() + '-' + String(fpDate.getMonth() + 1).padStart(2, '0')
: '<?php echo date('Y-m'); ?>';
show_overlays();
return ajax_request({
@@ -502,22 +488,15 @@
autoPrepare: true,
checkRequired: 0,
action: 'read',
data: { "month": month },
data: {},
onSuccess: async function(res) {
await render(res.output, month);
await render(res.output);
}
});
}
// ── Helpers ───────────────────────────────────────────────────────────
function format_month(ym) {
if (!ym) return '';
var parts = ym.split('-');
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
return months[parseInt(parts[1]) - 1] + ' ' + parts[0];
}
function time_ago(dateStr) {
if (!dateStr) return '';
var diff = Math.floor((new Date() - new Date(dateStr.replace(/-/g,'/'))) / 1000);
@@ -530,22 +509,6 @@
// ── Boot ─────────────────────────────────────────────────────────────
var monthPicker = flatpickr('#month_filter', {
plugins: [
new monthSelectPlugin({
shorthand: true,
dateFormat: 'M Y',
altFormat: 'M Y',
theme: 'light'
})
],
disableMobile: true,
onChange: function() {
retrieve_dashboard();
}
});
monthPicker.setDate('<?php echo date('M Y'); ?>', false); // false = don't trigger onChange
$(async function() {
try {
show_overlays();