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

684 lines
37 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}Inventory Management - 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 Inventory Management</h4>
<h6>Comprehensive medication inventory tracking and management system</h6>
</div>
<div class="page-btn">
<div class="btn-group">
<a href="{% url 'pharmacy:add_inventory_item' %}" class="btn btn-primary">
<i class="fa fa-plus"></i> Add Item
</a>
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#receiveShipmentModal">
<i class="fa fa-truck"></i> Receive Shipment
</button>
<button type="button" class="btn btn-warning" onclick="generatePurchaseOrders()">
<i class="fa fa-shopping-cart"></i> Generate POs
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Inventory Summary Cards -->
<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-boxes"></i>
</span>
<div class="dash-count">
<h3>{{ inventory_stats.total_items|default:1247 }}</h3>
</div>
</div>
<div class="dash-widget-info">
<h6 class="text-muted">Total Items</h6>
<div class="progress progress-sm">
<div class="progress-bar bg-primary" style="width: 85%"></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>{{ inventory_stats.low_stock|default:23 }}</h3>
</div>
</div>
<div class="dash-widget-info">
<h6 class="text-muted">Low Stock Items</h6>
<div class="progress progress-sm">
<div class="progress-bar bg-warning" style="width: {{ inventory_stats.low_stock_percentage|default:15 }}%"></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-danger border-danger">
<i class="fa fa-calendar-times"></i>
</span>
<div class="dash-count">
<h3>{{ inventory_stats.expiring_soon|default:8 }}</h3>
</div>
</div>
<div class="dash-widget-info">
<h6 class="text-muted">Expiring Soon</h6>
<div class="progress progress-sm">
<div class="progress-bar bg-danger" style="width: {{ inventory_stats.expiring_percentage|default:5 }}%"></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-dollar-sign"></i>
</span>
<div class="dash-count">
<h3>${{ inventory_stats.total_value|default:245000|floatformat:0 }}</h3>
</div>
</div>
<div class="dash-widget-info">
<h6 class="text-muted">Inventory Value</h6>
<div class="progress progress-sm">
<div class="progress-bar bg-success" style="width: 92%"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Filters and Search -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="card-title">Inventory Filters</h5>
</div>
<div class="card-body">
<form method="get" class="row g-3">
<div class="col-md-3">
<label class="form-label">Search</label>
<input type="text" name="search" class="form-control"
placeholder="Drug name, NDC, or lot number" value="{{ request.GET.search }}">
</div>
<div class="col-md-2">
<label class="form-label">Category</label>
<select name="category" class="form-select">
<option value="">All Categories</option>
<option value="antibiotics" {% if request.GET.category == 'antibiotics' %}selected{% endif %}>Antibiotics</option>
<option value="cardiovascular" {% if request.GET.category == 'cardiovascular' %}selected{% endif %}>Cardiovascular</option>
<option value="diabetes" {% if request.GET.category == 'diabetes' %}selected{% endif %}>Diabetes</option>
<option value="pain_management" {% if request.GET.category == 'pain_management' %}selected{% endif %}>Pain Management</option>
<option value="controlled" {% if request.GET.category == 'controlled' %}selected{% endif %}>Controlled Substances</option>
</select>
</div>
<div class="col-md-2">
<label class="form-label">Stock Status</label>
<select name="stock_status" class="form-select">
<option value="">All Status</option>
<option value="in_stock" {% if request.GET.stock_status == 'in_stock' %}selected{% endif %}>In Stock</option>
<option value="low_stock" {% if request.GET.stock_status == 'low_stock' %}selected{% endif %}>Low Stock</option>
<option value="out_of_stock" {% if request.GET.stock_status == 'out_of_stock' %}selected{% endif %}>Out of Stock</option>
<option value="expiring" {% if request.GET.stock_status == 'expiring' %}selected{% endif %}>Expiring Soon</option>
</select>
</div>
<div class="col-md-2">
<label class="form-label">Location</label>
<select name="location" class="form-select">
<option value="">All Locations</option>
<option value="main_pharmacy" {% if request.GET.location == 'main_pharmacy' %}selected{% endif %}>Main Pharmacy</option>
<option value="satellite_1" {% if request.GET.location == 'satellite_1' %}selected{% endif %}>Satellite 1</option>
<option value="emergency" {% if request.GET.location == 'emergency' %}selected{% endif %}>Emergency</option>
<option value="refrigerated" {% if request.GET.location == 'refrigerated' %}selected{% endif %}>Refrigerated</option>
<option value="controlled_vault" {% if request.GET.location == 'controlled_vault' %}selected{% endif %}>Controlled Vault</option>
</select>
</div>
<div class="col-md-2">
<label class="form-label">Supplier</label>
<select name="supplier" class="form-select">
<option value="">All Suppliers</option>
{% for supplier in suppliers %}
<option value="{{ supplier.id }}"
{% if request.GET.supplier == supplier.id|stringformat:"s" %}selected{% endif %}>
{{ supplier.name }}
</option>
{% endfor %}
</select>
</div>
<div class="col-md-1">
<label class="form-label">&nbsp;</label>
<button type="submit" class="btn btn-primary d-block">
<i class="fa fa-search"></i>
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Inventory Table -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="card-title">
Inventory Items
<span class="badge bg-primary">{{ inventory_items.count|default:0 }} items</span>
</h5>
<div class="card-tools">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-primary dropdown-toggle" data-bs-toggle="dropdown">
<i class="fa fa-download"></i> Export
</button>
<ul class="dropdown-menu">
<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>
<li><a class="dropdown-item" href="#"><i class="fa fa-file-pdf"></i> Inventory Report</a></li>
</ul>
</div>
</div>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>
<input type="checkbox" id="selectAll" class="form-check-input">
</th>
<th>Medication</th>
<th>NDC</th>
<th>Lot Number</th>
<th>Quantity</th>
<th>Unit Cost</th>
<th>Total Value</th>
<th>Expiration</th>
<th>Location</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for item in inventory_items %}
<tr class="{% if item.is_expired %}table-danger{% elif item.is_expiring_soon %}table-warning{% elif item.is_low_stock %}table-info{% endif %}">
<td>
<input type="checkbox" name="selected_items"
value="{{ item.id }}" class="form-check-input">
</td>
<td>
<div>
<strong>{{ item.medication.name }}</strong><br>
<small class="text-muted">{{ item.medication.generic_name }}</small>
{% if item.medication.controlled_substance %}
<br><span class="badge bg-warning">Controlled</span>
{% endif %}
</div>
</td>
<td>{{ item.ndc_number }}</td>
<td>{{ item.lot_number }}</td>
<td>
<div>
<strong>{{ item.quantity_on_hand }}</strong> {{ item.unit_of_measure }}<br>
<small class="text-muted">Min: {{ item.minimum_quantity }}</small>
</div>
</td>
<td>${{ item.unit_cost|floatformat:2 }}</td>
<td>${{ item.total_value|floatformat:2 }}</td>
<td>
{{ item.expiration_date|date:"M d, Y" }}
{% if item.days_until_expiration <= 30 %}
<br><small class="text-danger">{{ item.days_until_expiration }} days</small>
{% endif %}
</td>
<td>{{ item.storage_location|title }}</td>
<td>
{% if item.is_expired %}
<span class="badge bg-danger">Expired</span>
{% elif item.is_expiring_soon %}
<span class="badge bg-warning">Expiring Soon</span>
{% elif item.is_low_stock %}
<span class="badge bg-info">Low Stock</span>
{% elif item.is_out_of_stock %}
<span class="badge bg-danger">Out of Stock</span>
{% else %}
<span class="badge bg-success">In Stock</span>
{% endif %}
</td>
<td>
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-primary"
onclick="adjustQuantity({{ item.id }})" title="Adjust Quantity">
<i class="fa fa-edit"></i>
</button>
<button type="button" class="btn btn-sm btn-outline-success"
onclick="transferItem({{ item.id }})" title="Transfer">
<i class="fa fa-exchange-alt"></i>
</button>
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-secondary dropdown-toggle"
data-bs-toggle="dropdown" title="More Actions">
<i class="fa fa-ellipsis-v"></i>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#"><i class="fa fa-eye"></i> View Details</a></li>
<li><a class="dropdown-item" href="#"><i class="fa fa-history"></i> Transaction History</a></li>
<li><a class="dropdown-item" href="#"><i class="fa fa-print"></i> Print Label</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item text-danger" href="#"><i class="fa fa-trash"></i> Remove</a></li>
</ul>
</div>
</div>
</td>
</tr>
{% empty %}
<tr>
<td colspan="11" class="text-center text-muted">
<i class="fa fa-boxes fa-3x mb-3"></i>
<p>No inventory items found</p>
<a href="{% url 'pharmacy:add_inventory_item' %}" class="btn btn-primary">
<i class="fa fa-plus"></i> Add First Item
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Pagination -->
{% if inventory_items.has_other_pages %}
<nav aria-label="Inventory pagination">
<ul class="pagination justify-content-center">
{% if inventory_items.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ inventory_items.previous_page_number }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">Previous</a>
</li>
{% endif %}
{% for num in inventory_items.paginator.page_range %}
{% if inventory_items.number == num %}
<li class="page-item active">
<span class="page-link">{{ num }}</span>
</li>
{% elif num > inventory_items.number|add:'-3' and num < inventory_items.number|add:'3' %}
<li class="page-item">
<a class="page-link" href="?page={{ num }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">{{ num }}</a>
</li>
{% endif %}
{% endfor %}
{% if inventory_items.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ inventory_items.next_page_number }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">Next</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Bulk Actions -->
{% if inventory_items %}
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="card-title">Bulk Actions</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-8">
<div class="btn-group">
<button type="button" class="btn btn-outline-primary" id="bulkAdjustBtn">
<i class="fa fa-edit"></i> Bulk Adjust
</button>
<button type="button" class="btn btn-outline-success" id="bulkTransferBtn">
<i class="fa fa-exchange-alt"></i> Bulk Transfer
</button>
<button type="button" class="btn btn-outline-warning" id="bulkOrderBtn">
<i class="fa fa-shopping-cart"></i> Create Purchase Order
</button>
<button type="button" class="btn btn-outline-info" id="bulkPrintBtn">
<i class="fa fa-print"></i> Print Labels
</button>
</div>
</div>
<div class="col-md-4 text-end">
<span id="selectedCount" class="text-muted">0 items selected</span>
</div>
</div>
</div>
</div>
</div>
</div>
{% endif %}
<!-- Recent Transactions -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="card-title">Recent Inventory Transactions</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th>Time</th>
<th>Type</th>
<th>Medication</th>
<th>Quantity</th>
<th>User</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
{% for transaction in recent_transactions %}
<tr>
<td>{{ transaction.timestamp|date:"H:i" }}</td>
<td>
<span class="badge bg-{{ transaction.type_color }}">
{{ transaction.transaction_type|title }}
</span>
</td>
<td>{{ transaction.medication.name }}</td>
<td>
{% if transaction.transaction_type == 'dispensed' or transaction.transaction_type == 'adjustment_out' %}
-{{ transaction.quantity }}
{% else %}
+{{ transaction.quantity }}
{% endif %}
{{ transaction.unit_of_measure }}
</td>
<td>{{ transaction.user.get_full_name }}</td>
<td>{{ transaction.reference_number|default:"-" }}</td>
</tr>
{% empty %}
<tr>
<td colspan="6" class="text-center text-muted">No recent transactions</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Receive Shipment Modal -->
<div class="modal fade" id="receiveShipmentModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Receive Shipment</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form id="receiveShipmentForm">
<div class="modal-body">
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Purchase Order Number</label>
<input type="text" name="po_number" class="form-control" required>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Supplier</label>
<select name="supplier" class="form-select" required>
<option value="">Select Supplier</option>
{% for supplier in suppliers %}
<option value="{{ supplier.id }}">{{ supplier.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Invoice Number</label>
<input type="text" name="invoice_number" class="form-control">
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Received Date</label>
<input type="date" name="received_date" class="form-control" required>
</div>
</div>
<div class="col-12">
<div class="mb-3">
<label class="form-label">Notes</label>
<textarea name="notes" class="form-control" rows="3"
placeholder="Any notes about the shipment..."></textarea>
</div>
</div>
</div>
<h6>Shipment Items</h6>
<div id="shipmentItems">
<div class="shipment-item border rounded p-3 mb-3">
<div class="row">
<div class="col-md-4">
<label class="form-label">Medication</label>
<select name="medication[]" class="form-select" required>
<option value="">Select Medication</option>
{% for medication in medications %}
<option value="{{ medication.id }}">{{ medication.name }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-2">
<label class="form-label">Quantity</label>
<input type="number" name="quantity[]" class="form-control" required>
</div>
<div class="col-md-2">
<label class="form-label">Lot Number</label>
<input type="text" name="lot_number[]" class="form-control" required>
</div>
<div class="col-md-3">
<label class="form-label">Expiration Date</label>
<input type="date" name="expiration_date[]" class="form-control" required>
</div>
<div class="col-md-1">
<label class="form-label">&nbsp;</label>
<button type="button" class="btn btn-outline-danger d-block" onclick="removeShipmentItem(this)">
<i class="fa fa-times"></i>
</button>
</div>
</div>
</div>
</div>
<button type="button" class="btn btn-outline-primary" onclick="addShipmentItem()">
<i class="fa fa-plus"></i> Add Item
</button>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-success">Receive Shipment</button>
</div>
</form>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Set today's date as default for received date
document.querySelector('input[name="received_date"]').value = new Date().toISOString().split('T')[0];
// Select all functionality
const selectAllCheckbox = document.getElementById('selectAll');
const itemCheckboxes = document.querySelectorAll('input[name="selected_items"]');
const selectedCountElement = document.getElementById('selectedCount');
function updateSelectedCount() {
const selectedCount = document.querySelectorAll('input[name="selected_items"]:checked').length;
selectedCountElement.textContent = `${selectedCount} item${selectedCount !== 1 ? 's' : ''} selected`;
// Enable/disable bulk action buttons
const bulkButtons = document.querySelectorAll('[id^="bulk"]');
bulkButtons.forEach(button => {
button.disabled = selectedCount === 0;
});
}
selectAllCheckbox.addEventListener('change', function() {
itemCheckboxes.forEach(checkbox => {
checkbox.checked = this.checked;
});
updateSelectedCount();
});
itemCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', function() {
const allChecked = Array.from(itemCheckboxes).every(cb => cb.checked);
const noneChecked = Array.from(itemCheckboxes).every(cb => !cb.checked);
selectAllCheckbox.checked = allChecked;
selectAllCheckbox.indeterminate = !allChecked && !noneChecked;
updateSelectedCount();
});
});
// Initialize count
updateSelectedCount();
// Receive shipment form handler
document.getElementById('receiveShipmentForm').addEventListener('submit', function(e) {
e.preventDefault();
if (confirm('Confirm receipt of this shipment? This will update inventory quantities.')) {
// Handle shipment receipt
console.log('Processing shipment receipt...');
// Close modal
bootstrap.Modal.getInstance(document.getElementById('receiveShipmentModal')).hide();
// Show success message
alert('Shipment received successfully!');
}
});
});
function addShipmentItem() {
const container = document.getElementById('shipmentItems');
const template = container.querySelector('.shipment-item').cloneNode(true);
// Clear values
template.querySelectorAll('input, select').forEach(input => {
input.value = '';
});
container.appendChild(template);
}
function removeShipmentItem(button) {
const container = document.getElementById('shipmentItems');
if (container.children.length > 1) {
button.closest('.shipment-item').remove();
} else {
alert('At least one item is required');
}
}
function adjustQuantity(itemId) {
const newQuantity = prompt('Enter new quantity:');
if (newQuantity !== null && !isNaN(newQuantity) && newQuantity >= 0) {
// Handle quantity adjustment
console.log(`Adjusting item ${itemId} to quantity ${newQuantity}`);
// In real implementation, make AJAX call to update quantity
alert('Quantity updated successfully!');
location.reload();
}
}
function transferItem(itemId) {
const newLocation = prompt('Enter destination location:');
if (newLocation !== null && newLocation.trim() !== '') {
// Handle item transfer
console.log(`Transferring item ${itemId} to ${newLocation}`);
// In real implementation, make AJAX call to transfer item
alert('Item transferred successfully!');
location.reload();
}
}
function generatePurchaseOrders() {
if (confirm('Generate purchase orders for all low stock items?')) {
// Handle PO generation
console.log('Generating purchase orders...');
alert('Purchase orders generated successfully!');
}
}
// Bulk action handlers
document.getElementById('bulkAdjustBtn').addEventListener('click', function() {
const selected = getSelectedItems();
if (selected.length > 0) {
const adjustment = prompt('Enter quantity adjustment (use + or - prefix):');
if (adjustment !== null) {
console.log('Bulk adjusting items:', selected, 'by', adjustment);
alert('Bulk adjustment completed!');
}
}
});
document.getElementById('bulkTransferBtn').addEventListener('click', function() {
const selected = getSelectedItems();
if (selected.length > 0) {
const location = prompt('Enter destination location:');
if (location !== null && location.trim() !== '') {
console.log('Bulk transferring items:', selected, 'to', location);
alert('Bulk transfer completed!');
}
}
});
function getSelectedItems() {
return Array.from(document.querySelectorAll('input[name="selected_items"]:checked'))
.map(checkbox => checkbox.value);
}
</script>
{% endblock %}