hospital-management/templates/pharmacy/pharmacy_stats.html
2025-08-12 13:33:25 +03:00

557 lines
25 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}Pharmacy Statistics - Pharmacy{% endblock %}
{% block content %}
<div class="content">
<div class="container-fluid">
<!-- Page Header -->
<div class="row">
<div class="col-12">
<div class="page-header">
<div class="page-title">
<h4>Pharmacy Statistics Dashboard</h4>
<h6>Comprehensive pharmacy operations analytics and performance metrics</h6>
</div>
<div class="page-btn">
<div class="btn-group">
<button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown">
<i class="fa fa-download"></i> Export Reports
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#"><i class="fa fa-file-pdf"></i> PDF Report</a></li>
<li><a class="dropdown-item" href="#"><i class="fa fa-file-excel"></i> Excel Report</a></li>
<li><a class="dropdown-item" href="#"><i class="fa fa-file-csv"></i> CSV Data</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Key Performance Indicators -->
<div class="row">
<div class="col-xl-3 col-sm-6 col-12">
<div class="card">
<div class="card-body">
<div class="dash-widget-header">
<span class="dash-widget-icon text-primary border-primary">
<i class="fa fa-pills"></i>
</span>
<div class="dash-count">
<h3>{{ stats.prescriptions_today|default:0 }}</h3>
</div>
</div>
<div class="dash-widget-info">
<h6 class="text-muted">Prescriptions Today</h6>
<div class="progress progress-sm">
<div class="progress-bar bg-primary" style="width: {{ stats.prescriptions_progress|default:0 }}%"></div>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-sm-6 col-12">
<div class="card">
<div class="card-body">
<div class="dash-widget-header">
<span class="dash-widget-icon text-success border-success">
<i class="fa fa-check-circle"></i>
</span>
<div class="dash-count">
<h3>{{ stats.dispensed_today|default:0 }}</h3>
</div>
</div>
<div class="dash-widget-info">
<h6 class="text-muted">Medications Dispensed</h6>
<div class="progress progress-sm">
<div class="progress-bar bg-success" style="width: {{ stats.dispensed_progress|default:0 }}%"></div>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-sm-6 col-12">
<div class="card">
<div class="card-body">
<div class="dash-widget-header">
<span class="dash-widget-icon text-warning border-warning">
<i class="fa fa-exclamation-triangle"></i>
</span>
<div class="dash-count">
<h3>{{ stats.low_stock_items|default:0 }}</h3>
</div>
</div>
<div class="dash-widget-info">
<h6 class="text-muted">Low Stock Alerts</h6>
<div class="progress progress-sm">
<div class="progress-bar bg-warning" style="width: {{ stats.stock_alert_level|default:0 }}%"></div>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-sm-6 col-12">
<div class="card">
<div class="card-body">
<div class="dash-widget-header">
<span class="dash-widget-icon text-info border-info">
<i class="fa fa-dollar-sign"></i>
</span>
<div class="dash-count">
<h3>${{ stats.revenue_today|default:0|floatformat:0 }}</h3>
</div>
</div>
<div class="dash-widget-info">
<h6 class="text-muted">Revenue Today</h6>
<div class="progress progress-sm">
<div class="progress-bar bg-info" style="width: {{ stats.revenue_progress|default:0 }}%"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Time Period Selector -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="card-title">Analytics Period</h5>
</div>
<div class="card-body">
<form method="get" class="row g-3">
<div class="col-md-3">
<label class="form-label">Time Period</label>
<select name="period" class="form-select">
<option value="today" {% if request.GET.period == 'today' %}selected{% endif %}>Today</option>
<option value="week" {% if request.GET.period == 'week' %}selected{% endif %}>This Week</option>
<option value="month" {% if request.GET.period == 'month' %}selected{% endif %}>This Month</option>
<option value="quarter" {% if request.GET.period == 'quarter' %}selected{% endif %}>This Quarter</option>
<option value="year" {% if request.GET.period == 'year' %}selected{% endif %}>This Year</option>
<option value="custom" {% if request.GET.period == 'custom' %}selected{% endif %}>Custom Range</option>
</select>
</div>
<div class="col-md-3">
<label class="form-label">Start Date</label>
<input type="date" name="start_date" class="form-control" value="{{ request.GET.start_date }}">
</div>
<div class="col-md-3">
<label class="form-label">End Date</label>
<input type="date" name="end_date" class="form-control" value="{{ request.GET.end_date }}">
</div>
<div class="col-md-3">
<label class="form-label">&nbsp;</label>
<button type="submit" class="btn btn-primary d-block">
<i class="fa fa-search"></i> Update Analytics
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Charts Row -->
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h5 class="card-title">Prescription Trends</h5>
</div>
<div class="card-body">
<canvas id="prescriptionTrendsChart" height="300"></canvas>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h5 class="card-title">Top Medications</h5>
</div>
<div class="card-body">
<canvas id="topMedicationsChart" height="300"></canvas>
</div>
</div>
</div>
</div>
<!-- Detailed Statistics -->
<div class="row">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<h5 class="card-title">Pharmacy Performance Metrics</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Metric</th>
<th>Current Period</th>
<th>Previous Period</th>
<th>Change</th>
<th>Target</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Total Prescriptions</strong></td>
<td>{{ metrics.total_prescriptions|default:0 }}</td>
<td>{{ metrics.prev_total_prescriptions|default:0 }}</td>
<td>
<span class="badge bg-{{ metrics.prescriptions_trend_color }}">
{{ metrics.prescriptions_change|default:0 }}%
</span>
</td>
<td>{{ metrics.prescriptions_target|default:0 }}</td>
<td>
<span class="badge bg-{{ metrics.prescriptions_status_color }}">
{{ metrics.prescriptions_status|default:"On Track" }}
</span>
</td>
</tr>
<tr>
<td><strong>Dispensing Accuracy</strong></td>
<td>{{ metrics.dispensing_accuracy|default:99.5 }}%</td>
<td>{{ metrics.prev_dispensing_accuracy|default:99.2 }}%</td>
<td>
<span class="badge bg-{{ metrics.accuracy_trend_color }}">
+{{ metrics.accuracy_change|default:0.3 }}%
</span>
</td>
<td>99.0%</td>
<td>
<span class="badge bg-success">Excellent</span>
</td>
</tr>
<tr>
<td><strong>Average Wait Time</strong></td>
<td>{{ metrics.avg_wait_time|default:12 }} min</td>
<td>{{ metrics.prev_avg_wait_time|default:15 }} min</td>
<td>
<span class="badge bg-success">-3 min</span>
</td>
<td>15 min</td>
<td>
<span class="badge bg-success">Good</span>
</td>
</tr>
<tr>
<td><strong>Stock Turnover Rate</strong></td>
<td>{{ metrics.stock_turnover|default:8.5 }}x</td>
<td>{{ metrics.prev_stock_turnover|default:7.8 }}x</td>
<td>
<span class="badge bg-success">+0.7x</span>
</td>
<td>8.0x</td>
<td>
<span class="badge bg-success">Excellent</span>
</td>
</tr>
<tr>
<td><strong>Revenue per Prescription</strong></td>
<td>${{ metrics.revenue_per_rx|default:45.50 }}</td>
<td>${{ metrics.prev_revenue_per_rx|default:42.30 }}</td>
<td>
<span class="badge bg-success">+$3.20</span>
</td>
<td>${{ metrics.revenue_target|default:40.00 }}</td>
<td>
<span class="badge bg-success">Above Target</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header">
<h5 class="card-title">Prescription Categories</h5>
</div>
<div class="card-body">
<canvas id="prescriptionCategoriesChart" height="250"></canvas>
</div>
</div>
</div>
</div>
<!-- Inventory and Financial Analytics -->
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h5 class="card-title">Inventory Status</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-6">
<div class="text-center">
<h4 class="text-success">{{ inventory.in_stock|default:1250 }}</h4>
<p class="text-muted">Items In Stock</p>
</div>
</div>
<div class="col-6">
<div class="text-center">
<h4 class="text-warning">{{ inventory.low_stock|default:45 }}</h4>
<p class="text-muted">Low Stock Items</p>
</div>
</div>
<div class="col-6">
<div class="text-center">
<h4 class="text-danger">{{ inventory.out_of_stock|default:8 }}</h4>
<p class="text-muted">Out of Stock</p>
</div>
</div>
<div class="col-6">
<div class="text-center">
<h4 class="text-info">{{ inventory.expiring_soon|default:23 }}</h4>
<p class="text-muted">Expiring Soon</p>
</div>
</div>
</div>
<div class="mt-3">
<canvas id="inventoryStatusChart" height="150"></canvas>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h5 class="card-title">Financial Summary</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-6">
<div class="text-center">
<h4 class="text-primary">${{ financial.total_revenue|default:125000|floatformat:0 }}</h4>
<p class="text-muted">Total Revenue</p>
</div>
</div>
<div class="col-6">
<div class="text-center">
<h4 class="text-success">${{ financial.gross_profit|default:45000|floatformat:0 }}</h4>
<p class="text-muted">Gross Profit</p>
</div>
</div>
<div class="col-6">
<div class="text-center">
<h4 class="text-info">${{ financial.cost_of_goods|default:80000|floatformat:0 }}</h4>
<p class="text-muted">Cost of Goods</p>
</div>
</div>
<div class="col-6">
<div class="text-center">
<h4 class="text-warning">{{ financial.profit_margin|default:36 }}%</h4>
<p class="text-muted">Profit Margin</p>
</div>
</div>
</div>
<div class="mt-3">
<canvas id="revenueChart" height="150"></canvas>
</div>
</div>
</div>
</div>
</div>
<!-- Recent Activity -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="card-title">Recent Pharmacy Activity</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Time</th>
<th>Activity</th>
<th>Patient/Item</th>
<th>Pharmacist</th>
<th>Status</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
{% for activity in recent_activities %}
<tr>
<td>{{ activity.timestamp|date:"H:i" }}</td>
<td>{{ activity.activity_type|title }}</td>
<td>{{ activity.description }}</td>
<td>{{ activity.pharmacist.get_full_name|default:"System" }}</td>
<td>
<span class="badge bg-{{ activity.status_color }}">{{ activity.status|title }}</span>
</td>
<td>
{% if activity.amount %}
${{ activity.amount|floatformat:2 }}
{% else %}
-
{% endif %}
</td>
</tr>
{% empty %}
<tr>
<td colspan="6" class="text-center text-muted">No recent activity</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// Prescription Trends Chart
const prescriptionCtx = document.getElementById('prescriptionTrendsChart').getContext('2d');
new Chart(prescriptionCtx, {
type: 'line',
data: {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
datasets: [{
label: 'Prescriptions',
data: [45, 52, 48, 61, 55, 42, 38],
borderColor: 'rgb(75, 192, 192)',
backgroundColor: 'rgba(75, 192, 192, 0.1)',
tension: 0.1
}, {
label: 'Dispensed',
data: [42, 49, 45, 58, 52, 39, 35],
borderColor: 'rgb(54, 162, 235)',
backgroundColor: 'rgba(54, 162, 235, 0.1)',
tension: 0.1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true
}
}
}
});
// Top Medications Chart
const topMedsCtx = document.getElementById('topMedicationsChart').getContext('2d');
new Chart(topMedsCtx, {
type: 'bar',
data: {
labels: ['Lisinopril', 'Metformin', 'Amlodipine', 'Atorvastatin', 'Omeprazole'],
datasets: [{
label: 'Prescriptions',
data: [85, 72, 68, 61, 55],
backgroundColor: [
'rgba(255, 99, 132, 0.8)',
'rgba(54, 162, 235, 0.8)',
'rgba(255, 205, 86, 0.8)',
'rgba(75, 192, 192, 0.8)',
'rgba(153, 102, 255, 0.8)'
]
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true
}
}
}
});
// Prescription Categories Chart
const categoriesCtx = document.getElementById('prescriptionCategoriesChart').getContext('2d');
new Chart(categoriesCtx, {
type: 'doughnut',
data: {
labels: ['Cardiovascular', 'Diabetes', 'Antibiotics', 'Pain Management', 'Mental Health'],
datasets: [{
data: [30, 25, 20, 15, 10],
backgroundColor: [
'#FF6384',
'#36A2EB',
'#FFCE56',
'#4BC0C0',
'#9966FF'
]
}]
},
options: {
responsive: true,
maintainAspectRatio: false
}
});
// Inventory Status Chart
const inventoryCtx = document.getElementById('inventoryStatusChart').getContext('2d');
new Chart(inventoryCtx, {
type: 'doughnut',
data: {
labels: ['In Stock', 'Low Stock', 'Out of Stock', 'Expiring'],
datasets: [{
data: [{{ inventory.in_stock|default:1250 }}, {{ inventory.low_stock|default:45 }}, {{ inventory.out_of_stock|default:8 }}, {{ inventory.expiring_soon|default:23 }}],
backgroundColor: ['#28a745', '#ffc107', '#dc3545', '#17a2b8']
}]
},
options: {
responsive: true,
maintainAspectRatio: false
}
});
// Revenue Chart
const revenueCtx = document.getElementById('revenueChart').getContext('2d');
new Chart(revenueCtx, {
type: 'line',
data: {
labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4'],
datasets: [{
label: 'Revenue',
data: [28000, 32000, 31000, 34000],
borderColor: '#007bff',
backgroundColor: 'rgba(0, 123, 255, 0.1)',
tension: 0.1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
ticks: {
callback: function(value) {
return '$' + value.toLocaleString();
}
}
}
}
}
});
// Auto-refresh every 5 minutes
setInterval(function() {
location.reload();
}, 300000);
</script>
{% endblock %}