update
This commit is contained in:
parent
99858b4075
commit
193ee7f34a
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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'
|
||||
)
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
# """
|
||||
|
||||
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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,
|
||||
|
||||
@ -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
@ -284,7 +284,7 @@
|
||||
{% elif admission.admission_type == 'DIRECT' %}red
|
||||
{% else %}secondary
|
||||
{% endif %}">
|
||||
{{ admission.admission_type }}
|
||||
{{ admission.get_admission_type_display }}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
@ -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 %}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user