This commit is contained in:
Marwan Alwali 2025-08-24 12:00:10 +03:00
parent 99858b4075
commit 193ee7f34a
19 changed files with 2445 additions and 239 deletions

View File

@ -15,7 +15,43 @@ class User(AbstractUser):
"""
Extended user model for hospital management system.
"""
ROLE_CHOICES = [
('SUPER_ADMIN', 'Super Administrator'),
('ADMIN', 'Administrator'),
('PHYSICIAN', 'Physician'),
('NURSE', 'Nurse'),
('NURSE_PRACTITIONER', 'Nurse Practitioner'),
('PHYSICIAN_ASSISTANT', 'Physician Assistant'),
('PHARMACIST', 'Pharmacist'),
('PHARMACY_TECH', 'Pharmacy Technician'),
('LAB_TECH', 'Laboratory Technician'),
('RADIOLOGIST', 'Radiologist'),
('RAD_TECH', 'Radiology Technician'),
('THERAPIST', 'Therapist'),
('SOCIAL_WORKER', 'Social Worker'),
('CASE_MANAGER', 'Case Manager'),
('BILLING_SPECIALIST', 'Billing Specialist'),
('REGISTRATION', 'Registration Staff'),
('SCHEDULER', 'Scheduler'),
('MEDICAL_ASSISTANT', 'Medical Assistant'),
('CLERICAL', 'Clerical Staff'),
('IT_SUPPORT', 'IT Support'),
('QUALITY_ASSURANCE', 'Quality Assurance'),
('COMPLIANCE', 'Compliance Officer'),
('SECURITY', 'Security'),
('MAINTENANCE', 'Maintenance'),
('VOLUNTEER', 'Volunteer'),
('STUDENT', 'Student'),
('RESEARCHER', 'Researcher'),
('CONSULTANT', 'Consultant'),
('VENDOR', 'Vendor'),
('GUEST', 'Guest'),
]
THEME_CHOICES = [
('LIGHT', 'Light'),
('DARK', 'Dark'),
('AUTO', 'Auto'),
]
# Basic Information
user_id = models.UUIDField(
default=uuid.uuid4,
@ -91,38 +127,7 @@ class User(AbstractUser):
# Role and Permissions
role = models.CharField(
max_length=50,
choices=[
('SUPER_ADMIN', 'Super Administrator'),
('ADMIN', 'Administrator'),
('PHYSICIAN', 'Physician'),
('NURSE', 'Nurse'),
('NURSE_PRACTITIONER', 'Nurse Practitioner'),
('PHYSICIAN_ASSISTANT', 'Physician Assistant'),
('PHARMACIST', 'Pharmacist'),
('PHARMACY_TECH', 'Pharmacy Technician'),
('LAB_TECH', 'Laboratory Technician'),
('RADIOLOGIST', 'Radiologist'),
('RAD_TECH', 'Radiology Technician'),
('THERAPIST', 'Therapist'),
('SOCIAL_WORKER', 'Social Worker'),
('CASE_MANAGER', 'Case Manager'),
('BILLING_SPECIALIST', 'Billing Specialist'),
('REGISTRATION', 'Registration Staff'),
('SCHEDULER', 'Scheduler'),
('MEDICAL_ASSISTANT', 'Medical Assistant'),
('CLERICAL', 'Clerical Staff'),
('IT_SUPPORT', 'IT Support'),
('QUALITY_ASSURANCE', 'Quality Assurance'),
('COMPLIANCE', 'Compliance Officer'),
('SECURITY', 'Security'),
('MAINTENANCE', 'Maintenance'),
('VOLUNTEER', 'Volunteer'),
('STUDENT', 'Student'),
('RESEARCHER', 'Researcher'),
('CONSULTANT', 'Consultant'),
('VENDOR', 'Vendor'),
('GUEST', 'Guest'),
],
choices=ROLE_CHOICES,
default='CLERICAL'
)
@ -204,11 +209,7 @@ class User(AbstractUser):
)
theme = models.CharField(
max_length=20,
choices=[
('LIGHT', 'Light'),
('DARK', 'Dark'),
('AUTO', 'Auto'),
],
choices=THEME_CHOICES,
default='LIGHT'
)

View File

@ -19,6 +19,8 @@ urlpatterns = [
path('users/<int:pk>/', views.UserDetailView.as_view(), name='user_detail'),
path('profile/', views.UserProfileView.as_view(), name='user_profile'),
path('sessions/', views.SessionManagementView.as_view(), name='session_management'),
# path('reset-password/', views.ResetPasswordView.as_view(), name='reset_password'),
path('profile-picture/', views.upload_avatar, name='upload_avatar'),
# HTMX views

View File

@ -1,6 +1,8 @@
"""
Accounts app views for hospital management system with comprehensive CRUD operations.
"""
import os
from allauth.account.views import LoginView
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth import authenticate, login, logout
@ -1211,6 +1213,59 @@ def reset_user_password(request, pk):
return redirect('accounts:user_detail', pk=pk)
def upload_avatar(request, pk):
tenant = getattr(request, 'tenant', None)
if not tenant:
messages.error(request, 'No tenant found.')
return redirect('accounts:user_list')
user = get_object_or_404(User, pk=pk, tenant=tenant)
if request.method == 'POST':
if 'profile_picture' in request.FILES:
# Delete old profile picture if it exists
if user.profile_picture:
old_picture_path = user.profile_picture.path
if os.path.exists(old_picture_path):
os.remove(old_picture_path)
# Save new profile picture
user.profile_picture = request.FILES['profile_picture']
user.save()
# Log the upload
AuditLogger.log_event(
tenant=tenant,
event_type='UPDATE',
event_category='USER_MANAGEMENT',
action='Upload Profile Picture',
description=f'Uploaded profile picture for user: {user.username}',
user=request.user,
content_object=user,
request=request
)
messages.success(request, f'Profile picture updated successfully for "{user.username}".')
if request.headers.get('HX-Request'):
# Return HTMX response with updated image
return render(request, 'account/partials/profile_picture.html', {
'user_profile': user
})
return redirect('accounts:user_detail', pk=pk)
else:
messages.error(request, 'No image file was uploaded.')
# For GET requests, return the upload form
if request.headers.get('HX-Request'):
return render(request, 'account/partials/upload_avatar_form.html', {
'user_profile': user
})
return redirect('accounts:user_detail', pk=pk)
# """
# Accounts app views for hospital management system with comprehensive CRUD operations.
# """

Binary file not shown.

View File

@ -326,9 +326,9 @@ class DischargeSummaryForm(forms.ModelForm):
if user and hasattr(user, 'tenant'):
self.fields['admission'].queryset = Admission.objects.filter(
tenant=user.tenant,
status__in=['ADMITTED', 'READY_FOR_DISCHARGE']
status='ADMITTED'
).select_related('patient', 'current_ward', 'current_bed').order_by('patient__last_name', 'patient__first_name')
self.fields['discharging_physician'].queryset = User.objects.filter(
tenant=user.tenant,
is_active=True,

View File

@ -592,7 +592,7 @@ class AdmissionListView(LoginRequiredMixin, ListView):
def get_queryset(self):
queryset = Admission.objects.filter(tenant=self.request.user.tenant)
# Filter by status
status = self.request.GET.get('status')
if status:
@ -625,10 +625,15 @@ class AdmissionListView(LoginRequiredMixin, ListView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
tenant = self.request.user.tenant
total_admissions = Admission.objects.filter(tenant=tenant).count()
active_admissions = Admission.objects.filter(tenant=tenant, status='ADMITTED').count()
context.update({
'admission_statuses': Admission.STATUS_CHOICES,
'admission_types': Admission.ADMISSION_TYPE_CHOICES,
'wards': Ward.objects.filter(tenant=self.request.user.tenant, is_active=True),
'wards': Ward.objects.filter(tenant=tenant, is_active=True),
'total_admissions': total_admissions,
'active_admissions': active_admissions,
})
return context
@ -909,7 +914,7 @@ def surgery_calendar(request):
'operating_rooms': sorted(set(surgery.operating_room for surgery in surgeries))
}
return render(request, 'inpatients/partials/surgery_calendar.html', context)
return render(request, 'inpatients/surgery_schedule.html', context)
@login_required
@ -950,7 +955,7 @@ def transfer_patient(request, admission_id):
transfer.save()
# Log the action
AuditLogger.log(
AuditLogger.log_event(
actor=request.user,
action='TRANSFER_REQUESTED',
target=admission,
@ -978,7 +983,7 @@ def transfer_patient(request, admission_id):
'priorities': Transfer._meta.get_field('priority').choices
}
return render(request, 'inpatients/partials/transfer_form.html', context)
return render(request, 'inpatients/patient_transfer.html', context)
@login_required
@ -986,6 +991,7 @@ def approve_transfer(request, transfer_id):
"""
HTMX endpoint for approving a transfer.
"""
print("transfer clicked")
transfer = get_object_or_404(Transfer, id=transfer_id, admission__tenant=request.user.tenant)
if request.method == 'POST':
@ -1008,7 +1014,7 @@ def approve_transfer(request, transfer_id):
transfer.save()
# Log the action
AuditLogger.log(
AuditLogger.log_event(
actor=request.user,
action='TRANSFER_APPROVED',
target=transfer,
@ -1075,7 +1081,7 @@ def complete_transfer(request, transfer_id):
admission.save()
# Log the action
AuditLogger.log(
AuditLogger.log_event(
actor=request.user,
action='TRANSFER_COMPLETED',
target=transfer,
@ -1124,7 +1130,7 @@ def update_bed_status(request, bed_id):
bed.save()
# Log the action
AuditLogger.log(
AuditLogger.log_event(
actor=request.user,
action='BED_STATUS_UPDATED',
target=bed,
@ -1559,62 +1565,62 @@ def maintenance_bed(request, pk):
# return context
#
#
class WardDetailView(LoginRequiredMixin, DetailView):
"""
Detail view for a ward.
"""
model = Ward
template_name = 'inpatients/ward_detail.html'
context_object_name = 'ward'
def get_queryset(self):
"""Filter wards by tenant."""
return Ward.objects.filter(
tenant=self.request.user.tenant
).select_related('nurse_manager')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
ward = self.get_object()
# Get beds for this ward with patient information
context['beds'] = Bed.objects.filter(
ward=ward
).select_related(
'current_patient', 'current_admission'
).order_by('room_number', 'bed_number')
# Group beds by room for display
rooms = {}
for bed in context['beds']:
room_num = bed.room_number
if room_num not in rooms:
rooms[room_num] = []
rooms[room_num].append(bed)
context['rooms'] = rooms
# Get ward statistics
context['total_beds'] = context['beds'].count()
context['available_beds'] = context['beds'].filter(status='AVAILABLE').count()
context['occupied_beds'] = context['beds'].filter(status='OCCUPIED').count()
context['maintenance_beds'] = context['beds'].filter(
status__in=['MAINTENANCE', 'OUT_OF_ORDER', 'CLEANING']
).count()
if context['total_beds'] > 0:
context['occupancy_rate'] = (context['occupied_beds'] / context['total_beds']) * 100
else:
context['occupancy_rate'] = 0
# Get recent admissions to this ward
context['recent_admissions'] = Admission.objects.filter(
Q(initial_ward=ward) | Q(current_bed__ward=ward),
status__in=['ADMITTED', 'READY_FOR_DISCHARGE']
).select_related(
'patient', 'admitting_physician'
).order_by('-admitted_at')[:10]
return context
# class WardDetailView(LoginRequiredMixin, DetailView):
# """
# Detail view for a ward.
# """
# model = Ward
# template_name = 'inpatients/ward_detail.html'
# context_object_name = 'ward'
#
# def get_queryset(self):
# """Filter wards by tenant."""
# return Ward.objects.filter(
# tenant=self.request.user.tenant
# ).select_related('nurse_manager')
#
# def get_context_data(self, **kwargs):
# context = super().get_context_data(**kwargs)
# ward = self.get_object()
#
# # Get beds for this ward with patient information
# context['beds'] = Bed.objects.filter(
# ward=ward
# ).select_related(
# 'current_patient', 'current_admission'
# ).order_by('room_number', 'bed_number')
#
# # Group beds by room for display
# rooms = {}
# for bed in context['beds']:
# room_num = bed.room_number
# if room_num not in rooms:
# rooms[room_num] = []
# rooms[room_num].append(bed)
# context['rooms'] = rooms
#
# # Get ward statistics
# context['total_beds'] = context['beds'].count()
# context['available_beds'] = context['beds'].filter(status='AVAILABLE').count()
# context['occupied_beds'] = context['beds'].filter(status='OCCUPIED').count()
# context['maintenance_beds'] = context['beds'].filter(
# status__in=['MAINTENANCE', 'OUT_OF_ORDER', 'CLEANING']
# ).count()
#
# if context['total_beds'] > 0:
# context['occupancy_rate'] = (context['occupied_beds'] / context['total_beds']) * 100
# else:
# context['occupancy_rate'] = 0
#
# # Get recent admissions to this ward
# context['recent_admissions'] = Admission.objects.filter(
# Q(initial_ward=ward) | Q(current_bed__ward=ward),
# status__in=['ADMITTED', 'READY_FOR_DISCHARGE']
# ).select_related(
# 'patient', 'admitting_physician'
# ).order_by('-admitted_at')[:10]
#
# return context
#
#
# class WardCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
@ -2139,10 +2145,10 @@ def discharge_patient(request, pk):
pk=pk,
tenant=request.user.tenant
)
print(admission)
print(admission.status)
# Only admitted patients can be discharged
if admission.status not in ['ADMITTED', 'READY_FOR_DISCHARGE']:
if not admission.status == 'ADMITTED':
messages.error(request, _('Only admitted patients or patients ready for discharge can be discharged'))
return redirect('inpatients:admission_detail', pk=admission.pk)
@ -2156,6 +2162,7 @@ def discharge_patient(request, pk):
if summary_form.is_valid():
summary = summary_form.save(commit=False)
summary.patient = admission.patient
summary.admission = admission
summary.created_by = request.user
summary.save()
@ -2168,41 +2175,42 @@ def discharge_patient(request, pk):
else:
initial = {
'patient': admission.patient,
'admission': admission,
'discharge_diagnosis': admission.admitting_diagnosis,
'doctor_name': request.user.get_full_name() if request.user.role in ['DOCTOR', 'SPECIALIST'] else ''
}
summary_form = DischargeSummaryForm(
initial=initial,
user=request.user,
admission=admission
# admission=admission
)
return render(request, 'inpatients/discharges/discharge_form.html', {
return render(request, 'inpatients/discharges/discharge_planning.html', {
'admission': admission,
'form': summary_form
})
#
#
# @login_required
@login_required
# @permission_required('inpatients.change_admission')
# def mark_ready_for_discharge(request, pk):
# """
# Mark a patient as ready for discharge.
# """
# admission = get_object_or_404(
# Admission,
# pk=pk,
# tenant=request.user.tenant
# )
#
# # Only admitted patients can be marked ready for discharge
# if admission.status != 'ADMITTED':
# messages.error(request, _('Only admitted patients can be marked ready for discharge'))
# return redirect('inpatients:admission_detail', pk=admission.pk)
#
# admission.mark_ready_for_discharge()
# messages.success(request, _('Patient marked ready for discharge'))
# return redirect('inpatients:admission_detail', pk=admission.pk)
def mark_ready_for_discharge(request, pk):
"""
Mark a patient as ready for discharge.
"""
admission = get_object_or_404(
Admission,
pk=pk,
tenant=request.user.tenant
)
# Only admitted patients can be marked ready for discharge
if admission.status != 'ADMITTED':
messages.error(request, _('Only admitted patients can be marked ready for discharge'))
return redirect('inpatients:admission_detail', pk=admission.pk)
admission.mark_ready_for_discharge()
messages.success(request, _('Patient marked ready for discharge'))
return redirect('inpatients:admission_detail', pk=admission.pk)
#
#
# class TransferListView(LoginRequiredMixin, ListView):
@ -2977,36 +2985,36 @@ def discharge_patient(request, pk):
# return redirect('inpatients:bed_detail', pk=bed.pk)
#
#
@login_required
# @login_required
# @permission_required('inpatients.change_bed')
def maintenance_bed(request, pk):
"""
Mark a bed for maintenance.
"""
bed = get_object_or_404(
Bed,
pk=pk,
ward__tenant=request.user.tenant
)
# Only available beds can be marked for maintenance
if bed.status != 'AVAILABLE':
messages.error(request, _('Only available beds can be marked for maintenance'))
return redirect('inpatients:bed_detail', pk=bed.pk)
if request.method == 'POST':
notes = request.POST.get('notes')
# bed.mark_maintenance(notes)
bed.status = 'MAINTENANCE'
bed.notes = notes
bed.save()
messages.success(request, _('Bed marked for maintenance successfully'))
return redirect('inpatients:bed_detail', pk=bed.pk)
return render(request, 'inpatients/maintenance_bed.html', {
'bed': bed
})
# def maintenance_bed(request, pk):
# """
# Mark a bed for maintenance.
# """
# bed = get_object_or_404(
# Bed,
# pk=pk,
# ward__tenant=request.user.tenant
# )
#
# # Only available beds can be marked for maintenance
# if bed.status != 'AVAILABLE':
# messages.error(request, _('Only available beds can be marked for maintenance'))
# return redirect('inpatients:bed_detail', pk=bed.pk)
#
# if request.method == 'POST':
# notes = request.POST.get('notes')
#
# # bed.mark_maintenance(notes)
# bed.status = 'MAINTENANCE'
# bed.notes = notes
# bed.save()
# messages.success(request, _('Bed marked for maintenance successfully'))
# return redirect('inpatients:bed_detail', pk=bed.pk)
#
# return render(request, 'inpatients/maintenance_bed.html', {
# 'bed': bed
# })
#
#
# @login_required

File diff suppressed because it is too large Load Diff

View File

@ -284,7 +284,7 @@
{% elif admission.admission_type == 'DIRECT' %}red
{% else %}secondary
{% endif %}">
{{ admission.admission_type }}
{{ admission.get_admission_type_display }}
</div>
</td>
<td>

View File

@ -50,7 +50,7 @@
color: #856404;
}
.bed-out_of_order {
background-color: #b6b4b4;
background-color: #c5c5c5;
color: #434242;
}
@ -437,27 +437,24 @@ color: #434242;
</span>
</div>
</div>
<div class="card-footer">
<div class="btn-group btn-group-sm">
<a class="btn btn-sm btn-primary" href="{% url 'inpatients:bed_detail' bed.id %}" title="View Details">
<a class="btn btn-sm btn-outline-primary" href="{% url 'inpatients:bed_detail' bed.id %}" title="View Details">
<i class="fa fa-eye"></i>
</a>
{# <button class="btn btn-outline-primary" onclick="viewBedDetails('{{ bed.id }}')" title="View Details">#}
{# <i class="fa fa-eye"></i>#}
{# </button>#}
<a class="btn btn-sm btn-secondary" href="{% url 'inpatients:bed_update' bed.id %}" title="Edit">
<a class="btn btn-sm btn-outline-secondary" href="{% url 'inpatients:bed_update' bed.id %}" title="Edit">
<i class="fa fa-edit"></i>
</a>
{% if bed.status == 'AVAILABLE' %}
<a class="btn btn-sm btn-success" href="{% url 'inpatients:admission_create' %}" title="Assign Patient">
<a class="btn btn-sm btn-outline-success" href="{% url 'inpatients:admission_create' %}" title="Assign Patient">
<i class="fa fa-user-plus"></i>
</a>
{% elif bed.status == 'OCCUPIED' %}
{% if bed.current_admission %}
<a class="btn btn-sm btn-warning" href="{% url 'inpatients:discharge_patient' bed.current_admission.id %}" title="Discharge">
<a class="btn btn-sm btn-outline-warning" href="{% url 'inpatients:discharge_patient' bed.current_admission.id %}" title="Discharge">
<i class="fa fa-sign-out-alt"></i>
</a>
{% endif %}
@ -615,8 +612,8 @@ color: #434242;
</div>
</div>
</div>
</div>
</div>
<!-- Bed Details Modal -->
<div class="modal fade" id="bedDetailsModal" tabindex="-1">
@ -685,7 +682,8 @@ color: #434242;
</form>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}

View File

@ -176,17 +176,20 @@
<div class="planning-header">
<div class="row">
<div class="col-md-8">
<h5><i class="fas fa-user"></i> Patient: Robert Davis</h5>
<p><strong>MRN:</strong> MRN456789 | <strong>Age:</strong> 68 years | <strong>Gender:</strong> Male</p>
<p><strong>Admission Date:</strong> January 15, 2024 | <strong>Length of Stay:</strong> 5 days</p>
<p><strong>Primary Diagnosis:</strong> Acute Myocardial Infarction | <strong>Attending:</strong> Dr. Johnson</p>
<h5><i class="fas fa-user"></i> Patient: {{ admission.patient.get_full_name }}</h5>
<p><strong>MRN:</strong> {{ admission.patient.mrn }} | <strong>Age:</strong> {{ admission.patient.age }} | <strong>Gender:</strong>
{{ admission.patient.get_gender_display }}</p>
<p><strong>Admission Date:</strong> {{ admission.admission_datetime }} | <strong>Length of Stay:</strong> {{ admission.length_of_stay }} Days</p>
<p><strong>Admitting:</strong> {{ admission.admitting_physician.get_full_name }} | <strong>Attending:</strong>
{{ admission.attending_physician.get_full_name }}</p>
<p><strong>Primary Diagnosis:</strong> {{ admission.admitting_diagnosis }}</p>
</div>
<div class="col-md-4 text-end">
<div class="progress-bar-custom">
<div class="progress-fill" style="width: 75%"></div>
<div class="progress-text">75% Complete</div>
</div>
<p class="mt-2 mb-0">Expected Discharge: January 22, 2024</p>
<p class="mt-2 mb-0">Expected Discharge: {{ admission.anticipated_discharge_date}}</p>
</div>
</div>
</div>

View File

@ -4,8 +4,8 @@
{% block title %}Bed Maintenance Management{% endblock %}
{% block extra_css %}
<link href="{% static 'assets/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
<link href="{% static 'assets/plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
<link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
<link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
<style>
.maintenance-status-scheduled { color: #ffc107; }
.maintenance-status-in-progress { color: #17a2b8; }
@ -491,10 +491,10 @@
{% endblock %}
{% block extra_js %}
<script src="{% static 'assets/plugins/datatables.net/js/jquery.dataTables.min.js' %}"></script>
<script src="{% static 'assets/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
<script src="{% static 'assets/plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
<script src="{% static 'assets/plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
<script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
<script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
<script src="{% static 'plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
<script src="{% static 'plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
<script>
$(document).ready(function() {

View File

@ -86,7 +86,7 @@
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="rejectTransferForm" method="post" action="{% url 'inpatients:reject_transfer' transfer_id=transfer.id %}">
<form id="rejectTransferForm" method="post" action="">
{% csrf_token %}
<div class="mb-3">

View File

@ -79,7 +79,7 @@
<!-- Patient Information Card -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card mb-4">
<div class="card-header">
<h5><i class="fas fa-user"></i> Patient Information</h5>
<span class="discharge-status status-pending">Discharge in Progress</span>
@ -87,16 +87,16 @@
<div class="card-body">
<div class="row">
<div class="col-md-6">
<p><strong>Patient:</strong> {{ patient.full_name|default:"John Doe" }}</p>
<p><strong>MRN:</strong> {{ patient.medical_record_number|default:"MRN123456" }}</p>
<p><strong>DOB:</strong> {{ patient.date_of_birth|default:"1980-01-01" }}</p>
<p><strong>Gender:</strong> {{ patient.gender|default:"Male" }}</p>
<p><strong>Patient:</strong> {{ admission.patient.get_full_name }}</p>
<p><strong>MRN:</strong> {{ admission.patient.mrn }}</p>
<p><strong>DOB:</strong> {{ admission.patient.date_of_birth }}</p>
<p><strong>Gender:</strong> {{ admission.patient.gender }}</p>
</div>
<div class="col-md-6">
<p><strong>Admission Date:</strong> {{ admission.admission_date|default:"2024-01-15" }}</p>
<p><strong>Length of Stay:</strong> {{ admission.length_of_stay|default:"5 days" }}</p>
<p><strong>Attending Physician:</strong> {{ admission.attending_physician|default:"Dr. Smith" }}</p>
<p><strong>Ward/Room:</strong> {{ admission.bed.ward.name|default:"Ward A" }} - {{ admission.bed.room_number|default:"101" }}</p>
<p><strong>Admission Date:</strong> {{ admission.admission_datetime|date:'Y:m:d' }}</p>
<p><strong>Length of Stay:</strong> {{ admission.length_of_stay }}</p>
<p><strong>Attending Physician:</strong> {{ admission.attending_physician }}</p>
<p><strong>Ward/Room:</strong> {{ admission.current_bed.ward.name }} - {{ admission.current_bed.room_number }}</p>
</div>
</div>
</div>
@ -107,7 +107,7 @@
<!-- Discharge Checklist -->
<div class="row">
<div class="col-md-8">
<div class="card">
<div class="card mb-4">
<div class="card-header">
<h5><i class="fas fa-tasks"></i> Discharge Checklist</h5>
</div>
@ -182,7 +182,7 @@
</div>
<div class="col-md-4">
<div class="card">
<div class="card mb-4">
<div class="card-header">
<h5><i class="fas fa-clock"></i> Discharge Timeline</h5>
</div>
@ -192,14 +192,14 @@
<div class="timeline-marker"></div>
<div class="timeline-content">
<h6>Discharge Order</h6>
<p>09:00 AM - Dr. Smith</p>
<p>{{ admission.anticipated_discharge_date }}</p>
</div>
</div>
<div class="timeline-item completed">
<div class="timeline-marker"></div>
<div class="timeline-content">
<h6>Medication Review</h6>
<p>10:30 AM - Pharmacist</p>
<p>{{ admission.patient }}</p>
</div>
</div>
<div class="timeline-item active">

View File

@ -121,28 +121,26 @@
<td>
<div class="btn-group btn-group-sm">
{% if transfer.status == 'REQUESTED' %}
<button class="btn btn-outline-success"
<a class="btn btn-outline-success"
title="Approve"
hx-post="{% url 'inpatients:approve_transfer' transfer.id %}"
hx-confirm="Approve this transfer?"
hx-swap="none">
href="{% url 'inpatients:approve_transfer' transfer.id %}">
<i class="fas fa-check"></i>
</button>
<button class="btn btn-outline-danger"
title="Reject"
hx-post="{% url 'inpatients:reject_transfer' transfer.id %}"
hx-confirm="Reject this transfer?"
hx-swap="none">
<i class="fas fa-times"></i>
</button>
</a>
{# <button class="btn btn-outline-danger" #}
{# title="Reject"#}
{# hx-post="{% url 'inpatients:reject_transfer' transfer.id %}"#}
{# hx-confirm="Reject this transfer?"#}
{# hx-swap="none">#}
{# <i class="fas fa-times"></i>#}
{# </button>#}
{% elif transfer.status == 'APPROVED' or transfer.status == 'SCHEDULED' %}
<button class="btn btn-outline-primary"
title="Execute Transfer"
hx-post="{% url 'inpatients:execute_transfer' transfer.id %}"
hx-confirm="Execute this transfer?"
hx-swap="none">
<i class="fas fa-play"></i>
</button>
{# <button class="btn btn-outline-primary" #}
{# title="Execute Transfer"#}
{# hx-post="{% url 'inpatients:execute_transfer' transfer.id %}"#}
{# hx-confirm="Execute this transfer?"#}
{# hx-swap="none">#}
{# <i class="fas fa-play"></i>#}
{# </button>#}
{% endif %}
<button class="btn btn-outline-info" title="View Details">
@ -176,33 +174,7 @@
<!-- Pagination -->
{% if is_paginated %}
<nav aria-label="Transfer pagination">
<ul class="pagination justify-content-center">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page=1">First</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}">Previous</a>
</li>
{% endif %}
<li class="page-item active">
<span class="page-link">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}
</span>
</li>
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}">Next</a>
</li>
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.paginator.num_pages }}">Last</a>
</li>
{% endif %}
</ul>
</nav>
{% include 'partial/pagination.html'%}
{% endif %}
</div>
</div>