671 lines
29 KiB
HTML
671 lines
29 KiB
HTML
{% extends "base.html" %}
|
|
{% load static %}
|
|
|
|
{% block title %}Dispensing Records - Pharmacy{% endblock %}
|
|
|
|
{% block content %}
|
|
<!-- BEGIN breadcrumb -->
|
|
<ol class="breadcrumb float-xl-end">
|
|
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
|
|
<li class="breadcrumb-item"><a href="{% url 'pharmacy:dashboard' %}">Pharmacy</a></li>
|
|
<li class="breadcrumb-item active">Dispensing</li>
|
|
</ol>
|
|
<!-- END breadcrumb -->
|
|
|
|
<!-- BEGIN page-header -->
|
|
<h1 class="page-header">
|
|
Dispensing Records
|
|
<small>Medication dispensing and fulfillment tracking</small>
|
|
</h1>
|
|
<!-- END page-header -->
|
|
|
|
<!-- BEGIN statistics -->
|
|
<div class="row mb-3">
|
|
<div class="col-xl-3 col-md-6">
|
|
<div class="widget widget-stats bg-blue">
|
|
<div class="stats-icon"><i class="fa fa-pills"></i></div>
|
|
<div class="stats-info">
|
|
<h4>{{ stats.total_dispensed }}</h4>
|
|
<p>Total Dispensed</p>
|
|
</div>
|
|
<div class="stats-link">
|
|
<a href="javascript:;" onclick="filterByStatus('dispensed')">View Details <i class="fa fa-arrow-alt-circle-right"></i></a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xl-3 col-md-6">
|
|
<div class="widget widget-stats bg-info">
|
|
<div class="stats-icon"><i class="fa fa-clock"></i></div>
|
|
<div class="stats-info">
|
|
<h4>{{ stats.pending_dispensing }}</h4>
|
|
<p>Pending Dispensing</p>
|
|
</div>
|
|
<div class="stats-link">
|
|
<a href="javascript:;" onclick="filterByStatus('pending')">View Details <i class="fa fa-arrow-alt-circle-right"></i></a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xl-3 col-md-6">
|
|
<div class="widget widget-stats bg-orange">
|
|
<div class="stats-icon"><i class="fa fa-exclamation-triangle"></i></div>
|
|
<div class="stats-info">
|
|
<h4>{{ stats.partial_fills }}</h4>
|
|
<p>Partial Fills</p>
|
|
</div>
|
|
<div class="stats-link">
|
|
<a href="javascript:;" onclick="filterByStatus('partial')">View Details <i class="fa fa-arrow-alt-circle-right"></i></a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xl-3 col-md-6">
|
|
<div class="widget widget-stats bg-red">
|
|
<div class="stats-icon"><i class="fa fa-ban"></i></div>
|
|
<div class="stats-info">
|
|
<h4>{{ stats.rejected }}</h4>
|
|
<p>Rejected</p>
|
|
</div>
|
|
<div class="stats-link">
|
|
<a href="javascript:;" onclick="filterByStatus('rejected')">View Details <i class="fa fa-arrow-alt-circle-right"></i></a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END statistics -->
|
|
|
|
<!-- BEGIN panel -->
|
|
<div class="panel panel-inverse">
|
|
<div class="panel-heading">
|
|
<h4 class="panel-title">Dispensing Records</h4>
|
|
<div class="panel-heading-btn">
|
|
<button type="button" class="btn btn-sm btn-primary me-2" data-bs-toggle="modal" data-bs-target="#newDispensingModal">
|
|
<i class="fa fa-plus me-1"></i>New Dispensing
|
|
</button>
|
|
<button type="button" class="btn btn-sm btn-info me-2" onclick="refreshData()">
|
|
<i class="fa fa-refresh me-1"></i>Refresh
|
|
</button>
|
|
<div class="btn-group me-2">
|
|
<button type="button" class="btn btn-sm btn-secondary dropdown-toggle" data-bs-toggle="dropdown">
|
|
<i class="fa fa-download me-1"></i>Export
|
|
</button>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="javascript:;" onclick="exportData('csv')">Export as CSV</a></li>
|
|
<li><a class="dropdown-item" href="javascript:;" onclick="exportData('excel')">Export as Excel</a></li>
|
|
<li><a class="dropdown-item" href="javascript:;" onclick="exportData('pdf')">Export as PDF</a></li>
|
|
</ul>
|
|
</div>
|
|
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
|
|
</div>
|
|
</div>
|
|
<div class="panel-body">
|
|
<!-- Filters -->
|
|
<div class="row mb-3">
|
|
<div class="col-md-3">
|
|
<div class="form-floating">
|
|
<select class="form-select" id="status-filter">
|
|
<option value="">All Statuses</option>
|
|
<option value="pending">Pending</option>
|
|
<option value="in_progress">In Progress</option>
|
|
<option value="dispensed">Dispensed</option>
|
|
<option value="partial">Partial Fill</option>
|
|
<option value="rejected">Rejected</option>
|
|
<option value="cancelled">Cancelled</option>
|
|
</select>
|
|
<label for="status-filter">Status</label>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="form-floating">
|
|
<select class="form-select" id="priority-filter">
|
|
<option value="">All Priorities</option>
|
|
<option value="urgent">Urgent</option>
|
|
<option value="high">High</option>
|
|
<option value="normal">Normal</option>
|
|
<option value="low">Low</option>
|
|
</select>
|
|
<label for="priority-filter">Priority</label>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="form-floating">
|
|
<input type="date" class="form-control" id="date-filter" value="{{ today|date:'Y-m-d' }}">
|
|
<label for="date-filter">Date</label>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="form-floating">
|
|
<input type="text" class="form-control" id="search-filter" placeholder="Search...">
|
|
<label for="search-filter">Search</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bulk Actions -->
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<div class="btn-group">
|
|
<button type="button" class="btn btn-sm btn-outline-primary" onclick="selectAll()">
|
|
<i class="fa fa-check-square me-1"></i>Select All
|
|
</button>
|
|
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="clearSelection()">
|
|
<i class="fa fa-square me-1"></i>Clear Selection
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6 text-end">
|
|
<div class="btn-group" id="bulk-actions" style="display: none;">
|
|
<button type="button" class="btn btn-sm btn-success" onclick="bulkDispense()">
|
|
<i class="fa fa-check me-1"></i>Dispense Selected
|
|
</button>
|
|
<button type="button" class="btn btn-sm btn-warning" onclick="bulkPrint()">
|
|
<i class="fa fa-print me-1"></i>Print Labels
|
|
</button>
|
|
<button type="button" class="btn btn-sm btn-info" onclick="bulkNotify()">
|
|
<i class="fa fa-bell me-1"></i>Notify Patients
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Dispensing Table -->
|
|
<div class="table-responsive">
|
|
<table class="table table-striped table-bordered align-middle" id="dispensing-table">
|
|
<thead>
|
|
<tr>
|
|
<th width="30">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="select-all-checkbox">
|
|
</div>
|
|
</th>
|
|
<th>Prescription</th>
|
|
<th>Patient</th>
|
|
<th>Medication</th>
|
|
<th>Quantity</th>
|
|
<th>Status</th>
|
|
<th>Priority</th>
|
|
<th>Pharmacist</th>
|
|
<th>Date</th>
|
|
<th width="120">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for dispensing in dispensing_list %}
|
|
<tr data-id="{{ dispensing.id }}" data-status="{{ dispensing.status }}">
|
|
<td>
|
|
<div class="form-check">
|
|
<input class="form-check-input row-checkbox" type="checkbox" value="{{ dispensing.id }}">
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div class="d-flex align-items-center">
|
|
<div>
|
|
<div class="fw-bold">{{ dispensing.prescription.prescription_number }}</div>
|
|
<div class="small text-muted">{{ dispensing.prescription.prescriber.get_full_name }}</div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div>
|
|
<div class="fw-bold">{{ dispensing.prescription.patient.get_full_name }}</div>
|
|
<div class="small text-muted">DOB: {{ dispensing.prescription.patient.date_of_birth|date:"M d, Y" }}</div>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div>
|
|
<div class="fw-bold">{{ dispensing.medication.generic_name }}</div>
|
|
<div class="small text-muted">{{ dispensing.medication.strength }} - {{ dispensing.medication.dosage_form }}</div>
|
|
{% if dispensing.medication.is_controlled %}
|
|
<span class="badge bg-warning text-dark">
|
|
<i class="fa fa-shield me-1"></i>Controlled
|
|
</span>
|
|
{% endif %}
|
|
{% if dispensing.medication.is_high_alert %}
|
|
<span class="badge bg-danger">
|
|
<i class="fa fa-exclamation-triangle me-1"></i>High Alert
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div>
|
|
<div class="fw-bold">{{ dispensing.quantity_dispensed }}/{{ dispensing.quantity_prescribed }}</div>
|
|
<div class="small text-muted">{{ dispensing.medication.unit }}</div>
|
|
{% if dispensing.is_partial_fill %}
|
|
<span class="badge bg-warning text-dark">Partial</span>
|
|
{% endif %}
|
|
</div>
|
|
</td>
|
|
<td>
|
|
{% if dispensing.status == 'pending' %}
|
|
<span class="badge bg-info">
|
|
<i class="fa fa-clock me-1"></i>Pending
|
|
</span>
|
|
{% elif dispensing.status == 'in_progress' %}
|
|
<span class="badge bg-warning text-dark">
|
|
<i class="fa fa-spinner me-1"></i>In Progress
|
|
</span>
|
|
{% elif dispensing.status == 'dispensed' %}
|
|
<span class="badge bg-success">
|
|
<i class="fa fa-check me-1"></i>Dispensed
|
|
</span>
|
|
{% elif dispensing.status == 'partial' %}
|
|
<span class="badge bg-warning text-dark">
|
|
<i class="fa fa-exclamation-triangle me-1"></i>Partial
|
|
</span>
|
|
{% elif dispensing.status == 'rejected' %}
|
|
<span class="badge bg-danger">
|
|
<i class="fa fa-times me-1"></i>Rejected
|
|
</span>
|
|
{% elif dispensing.status == 'cancelled' %}
|
|
<span class="badge bg-secondary">
|
|
<i class="fa fa-ban me-1"></i>Cancelled
|
|
</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if dispensing.priority == 'urgent' %}
|
|
<span class="badge bg-danger">
|
|
<i class="fa fa-exclamation-circle me-1"></i>Urgent
|
|
</span>
|
|
{% elif dispensing.priority == 'high' %}
|
|
<span class="badge bg-warning text-dark">
|
|
<i class="fa fa-arrow-up me-1"></i>High
|
|
</span>
|
|
{% elif dispensing.priority == 'normal' %}
|
|
<span class="badge bg-primary">
|
|
<i class="fa fa-minus me-1"></i>Normal
|
|
</span>
|
|
{% elif dispensing.priority == 'low' %}
|
|
<span class="badge bg-secondary">
|
|
<i class="fa fa-arrow-down me-1"></i>Low
|
|
</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
<div>
|
|
{% if dispensing.pharmacist %}
|
|
<div class="fw-bold">{{ dispensing.pharmacist.get_full_name }}</div>
|
|
<div class="small text-muted">{{ dispensing.pharmacist.license_number }}</div>
|
|
{% else %}
|
|
<span class="text-muted">Not assigned</span>
|
|
{% endif %}
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div>
|
|
<div class="fw-bold">{{ dispensing.dispensed_date|date:"M d, Y" }}</div>
|
|
<div class="small text-muted">{{ dispensing.dispensed_date|time:"H:i" }}</div>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div class="btn-group">
|
|
<a href="{% url 'pharmacy:dispensing_detail' dispensing.pk %}" class="btn btn-sm btn-outline-primary" title="View Details">
|
|
<i class="fa fa-eye"></i>
|
|
</a>
|
|
{% if dispensing.status == 'pending' or dispensing.status == 'in_progress' %}
|
|
<a href="{% url 'pharmacy:dispensing_edit' dispensing.pk %}" class="btn btn-sm btn-outline-secondary" title="Edit">
|
|
<i class="fa fa-edit"></i>
|
|
</a>
|
|
{% endif %}
|
|
{% if dispensing.status == 'pending' %}
|
|
<button type="button" class="btn btn-sm btn-outline-success" onclick="quickDispense({{ dispensing.pk }})" title="Quick Dispense">
|
|
<i class="fa fa-check"></i>
|
|
</button>
|
|
{% endif %}
|
|
<button type="button" class="btn btn-sm btn-outline-info" onclick="printLabel({{ dispensing.pk }})" title="Print Label">
|
|
<i class="fa fa-print"></i>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% empty %}
|
|
<tr>
|
|
<td colspan="10" class="text-center text-muted py-4">
|
|
<i class="fa fa-pills fa-3x mb-3"></i>
|
|
<div>No dispensing records found</div>
|
|
<div class="small">Try adjusting your filters or create a new dispensing record</div>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Pagination -->
|
|
{% if is_paginated %}
|
|
<div class="d-flex justify-content-between align-items-center mt-3">
|
|
<div class="small text-muted">
|
|
Showing {{ page_obj.start_index }} to {{ page_obj.end_index }} of {{ page_obj.paginator.count }} entries
|
|
</div>
|
|
<nav aria-label="Dispensing pagination">
|
|
<ul class="pagination pagination-sm mb-0">
|
|
{% if page_obj.has_previous %}
|
|
<li class="page-item">
|
|
<a class="page-link" href="?page=1{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}">First</a>
|
|
</li>
|
|
<li class="page-item">
|
|
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}">Previous</a>
|
|
</li>
|
|
{% endif %}
|
|
|
|
{% for num in page_obj.paginator.page_range %}
|
|
{% if page_obj.number == num %}
|
|
<li class="page-item active">
|
|
<span class="page-link">{{ num }}</span>
|
|
</li>
|
|
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
|
|
<li class="page-item">
|
|
<a class="page-link" href="?page={{ num }}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}">{{ num }}</a>
|
|
</li>
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
{% if page_obj.has_next %}
|
|
<li class="page-item">
|
|
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}">Next</a>
|
|
</li>
|
|
<li class="page-item">
|
|
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}{% if request.GET.status %}&status={{ request.GET.status }}{% endif %}{% if request.GET.search %}&search={{ request.GET.search }}{% endif %}">Last</a>
|
|
</li>
|
|
{% endif %}
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<!-- END panel -->
|
|
|
|
<!-- New Dispensing Modal -->
|
|
<div class="modal fade" id="newDispensingModal" tabindex="-1">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">New Dispensing Record</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form id="new-dispensing-form">
|
|
{% csrf_token %}
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-floating mb-3">
|
|
<select class="form-select" id="prescription-select" required>
|
|
<option value="">Select prescription...</option>
|
|
{% for prescription in pending_prescriptions %}
|
|
<option value="{{ prescription.id }}">{{ prescription.prescription_number }} - {{ prescription.patient.get_full_name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
<label for="prescription-select">Prescription</label>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-floating mb-3">
|
|
<select class="form-select" id="pharmacist-select" required>
|
|
<option value="">Select pharmacist...</option>
|
|
{% for pharmacist in pharmacists %}
|
|
<option value="{{ pharmacist.id }}">{{ pharmacist.get_full_name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
<label for="pharmacist-select">Pharmacist</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-floating mb-3">
|
|
<input type="number" class="form-control" id="quantity-dispensed" min="1" required>
|
|
<label for="quantity-dispensed">Quantity to Dispense</label>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-floating mb-3">
|
|
<select class="form-select" id="priority-select">
|
|
<option value="normal">Normal</option>
|
|
<option value="high">High</option>
|
|
<option value="urgent">Urgent</option>
|
|
<option value="low">Low</option>
|
|
</select>
|
|
<label for="priority-select">Priority</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="dispensing-notes" class="form-label">Notes</label>
|
|
<textarea class="form-control" id="dispensing-notes" rows="3"></textarea>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-primary" onclick="createDispensing()">Create Dispensing Record</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block js %}
|
|
<script>
|
|
var selectedRows = [];
|
|
var autoRefreshTimer;
|
|
|
|
$(document).ready(function() {
|
|
// Initialize filters
|
|
initializeFilters();
|
|
|
|
// Auto-refresh every 30 seconds
|
|
autoRefreshTimer = setInterval(function() {
|
|
refreshData();
|
|
}, 30000);
|
|
|
|
// Row selection
|
|
$('.row-checkbox').on('change', function() {
|
|
updateSelection();
|
|
});
|
|
|
|
$('#select-all-checkbox').on('change', function() {
|
|
if ($(this).is(':checked')) {
|
|
selectAll();
|
|
} else {
|
|
clearSelection();
|
|
}
|
|
});
|
|
});
|
|
|
|
function initializeFilters() {
|
|
$('#status-filter, #priority-filter, #date-filter, #search-filter').on('change input', function() {
|
|
filterData();
|
|
});
|
|
}
|
|
|
|
function filterData() {
|
|
var status = $('#status-filter').val();
|
|
var priority = $('#priority-filter').val();
|
|
var date = $('#date-filter').val();
|
|
var search = $('#search-filter').val();
|
|
|
|
var url = new URL(window.location.href);
|
|
url.searchParams.set('status', status);
|
|
url.searchParams.set('priority', priority);
|
|
url.searchParams.set('date', date);
|
|
url.searchParams.set('search', search);
|
|
url.searchParams.set('page', '1');
|
|
|
|
window.location.href = url.toString();
|
|
}
|
|
|
|
function filterByStatus(status) {
|
|
$('#status-filter').val(status);
|
|
filterData();
|
|
}
|
|
|
|
function refreshData() {
|
|
location.reload();
|
|
}
|
|
|
|
function selectAll() {
|
|
$('.row-checkbox').prop('checked', true);
|
|
updateSelection();
|
|
}
|
|
|
|
function clearSelection() {
|
|
$('.row-checkbox').prop('checked', false);
|
|
updateSelection();
|
|
}
|
|
|
|
function updateSelection() {
|
|
selectedRows = [];
|
|
$('.row-checkbox:checked').each(function() {
|
|
selectedRows.push($(this).val());
|
|
});
|
|
|
|
if (selectedRows.length > 0) {
|
|
$('#bulk-actions').show();
|
|
} else {
|
|
$('#bulk-actions').hide();
|
|
}
|
|
|
|
$('#select-all-checkbox').prop('checked', selectedRows.length === $('.row-checkbox').length);
|
|
}
|
|
|
|
function bulkDispense() {
|
|
if (selectedRows.length === 0) {
|
|
toastr.warning('Please select dispensing records to process');
|
|
return;
|
|
}
|
|
|
|
if (confirm('Are you sure you want to dispense ' + selectedRows.length + ' selected record(s)?')) {
|
|
$.ajax({
|
|
url: '{% url "pharmacy:bulk_dispense" %}',
|
|
method: 'POST',
|
|
data: {
|
|
'dispensing_ids': selectedRows,
|
|
'csrfmiddlewaretoken': '{{ csrf_token }}'
|
|
},
|
|
success: function(response) {
|
|
toastr.success('Successfully dispensed ' + response.dispensed_count + ' record(s)');
|
|
refreshData();
|
|
},
|
|
error: function() {
|
|
toastr.error('Failed to process bulk dispensing');
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function bulkPrint() {
|
|
if (selectedRows.length === 0) {
|
|
toastr.warning('Please select dispensing records to print');
|
|
return;
|
|
}
|
|
|
|
var printUrl = '{% url "pharmacy:bulk_print_labels" %}?ids=' + selectedRows.join(',');
|
|
window.open(printUrl, '_blank');
|
|
}
|
|
|
|
function bulkNotify() {
|
|
if (selectedRows.length === 0) {
|
|
toastr.warning('Please select dispensing records to notify');
|
|
return;
|
|
}
|
|
|
|
$.ajax({
|
|
url: '{% url "pharmacy:bulk_notify_patients" %}',
|
|
method: 'POST',
|
|
data: {
|
|
'dispensing_ids': selectedRows,
|
|
'csrfmiddlewaretoken': '{{ csrf_token }}'
|
|
},
|
|
success: function(response) {
|
|
toastr.success('Notifications sent for ' + response.notified_count + ' patient(s)');
|
|
},
|
|
error: function() {
|
|
toastr.error('Failed to send notifications');
|
|
}
|
|
});
|
|
}
|
|
|
|
function quickDispense(dispensingId) {
|
|
if (confirm('Are you sure you want to dispense this medication?')) {
|
|
$.ajax({
|
|
url: '{% url "pharmacy:quick_dispense" %}',
|
|
method: 'POST',
|
|
data: {
|
|
'dispensing_id': dispensingId,
|
|
'csrfmiddlewaretoken': '{{ csrf_token }}'
|
|
},
|
|
success: function(response) {
|
|
toastr.success('Medication dispensed successfully');
|
|
refreshData();
|
|
},
|
|
error: function() {
|
|
toastr.error('Failed to dispense medication');
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function printLabel(dispensingId) {
|
|
var printUrl = '{% url "pharmacy:print_dispensing_label" %}?id=' + dispensingId;
|
|
window.open(printUrl, '_blank');
|
|
}
|
|
|
|
function createDispensing() {
|
|
var prescriptionId = $('#prescription-select').val();
|
|
var pharmacistId = $('#pharmacist-select').val();
|
|
var quantity = $('#quantity-dispensed').val();
|
|
var priority = $('#priority-select').val();
|
|
var notes = $('#dispensing-notes').val();
|
|
|
|
if (!prescriptionId || !pharmacistId || !quantity) {
|
|
toastr.error('Please fill in all required fields');
|
|
return;
|
|
}
|
|
|
|
$.ajax({
|
|
url: '{% url "pharmacy:create_dispensing" %}',
|
|
method: 'POST',
|
|
data: {
|
|
'prescription_id': prescriptionId,
|
|
'pharmacist_id': pharmacistId,
|
|
'quantity': quantity,
|
|
'priority': priority,
|
|
'notes': notes,
|
|
'csrfmiddlewaretoken': '{{ csrf_token }}'
|
|
},
|
|
success: function(response) {
|
|
toastr.success('Dispensing record created successfully');
|
|
$('#newDispensingModal').modal('hide');
|
|
refreshData();
|
|
},
|
|
error: function() {
|
|
toastr.error('Failed to create dispensing record');
|
|
}
|
|
});
|
|
}
|
|
|
|
function exportData(format) {
|
|
var status = $('#status-filter').val();
|
|
var priority = $('#priority-filter').val();
|
|
var date = $('#date-filter').val();
|
|
var search = $('#search-filter').val();
|
|
|
|
var exportUrl = '{% url "pharmacy:export_dispensing" %}?format=' + format;
|
|
if (status) exportUrl += '&status=' + status;
|
|
if (priority) exportUrl += '&priority=' + priority;
|
|
if (date) exportUrl += '&date=' + date;
|
|
if (search) exportUrl += '&search=' + search;
|
|
|
|
window.open(exportUrl, '_blank');
|
|
}
|
|
|
|
// Cleanup on page unload
|
|
$(window).on('beforeunload', function() {
|
|
if (autoRefreshTimer) {
|
|
clearInterval(autoRefreshTimer);
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %}
|
|
|