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.
|
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
|
# Basic Information
|
||||||
user_id = models.UUIDField(
|
user_id = models.UUIDField(
|
||||||
default=uuid.uuid4,
|
default=uuid.uuid4,
|
||||||
@ -91,38 +127,7 @@ class User(AbstractUser):
|
|||||||
# Role and Permissions
|
# Role and Permissions
|
||||||
role = models.CharField(
|
role = models.CharField(
|
||||||
max_length=50,
|
max_length=50,
|
||||||
choices=[
|
choices=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'),
|
|
||||||
],
|
|
||||||
default='CLERICAL'
|
default='CLERICAL'
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -204,11 +209,7 @@ class User(AbstractUser):
|
|||||||
)
|
)
|
||||||
theme = models.CharField(
|
theme = models.CharField(
|
||||||
max_length=20,
|
max_length=20,
|
||||||
choices=[
|
choices=THEME_CHOICES,
|
||||||
('LIGHT', 'Light'),
|
|
||||||
('DARK', 'Dark'),
|
|
||||||
('AUTO', 'Auto'),
|
|
||||||
],
|
|
||||||
default='LIGHT'
|
default='LIGHT'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,8 @@ urlpatterns = [
|
|||||||
path('users/<int:pk>/', views.UserDetailView.as_view(), name='user_detail'),
|
path('users/<int:pk>/', views.UserDetailView.as_view(), name='user_detail'),
|
||||||
path('profile/', views.UserProfileView.as_view(), name='user_profile'),
|
path('profile/', views.UserProfileView.as_view(), name='user_profile'),
|
||||||
path('sessions/', views.SessionManagementView.as_view(), name='session_management'),
|
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
|
# HTMX views
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
"""
|
"""
|
||||||
Accounts app views for hospital management system with comprehensive CRUD operations.
|
Accounts app views for hospital management system with comprehensive CRUD operations.
|
||||||
"""
|
"""
|
||||||
|
import os
|
||||||
|
|
||||||
from allauth.account.views import LoginView
|
from allauth.account.views import LoginView
|
||||||
from django.shortcuts import render, get_object_or_404, redirect
|
from django.shortcuts import render, get_object_or_404, redirect
|
||||||
from django.contrib.auth import authenticate, login, logout
|
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)
|
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.
|
# 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'):
|
if user and hasattr(user, 'tenant'):
|
||||||
self.fields['admission'].queryset = Admission.objects.filter(
|
self.fields['admission'].queryset = Admission.objects.filter(
|
||||||
tenant=user.tenant,
|
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')
|
).select_related('patient', 'current_ward', 'current_bed').order_by('patient__last_name', 'patient__first_name')
|
||||||
|
|
||||||
self.fields['discharging_physician'].queryset = User.objects.filter(
|
self.fields['discharging_physician'].queryset = User.objects.filter(
|
||||||
tenant=user.tenant,
|
tenant=user.tenant,
|
||||||
is_active=True,
|
is_active=True,
|
||||||
|
|||||||
@ -592,7 +592,7 @@ class AdmissionListView(LoginRequiredMixin, ListView):
|
|||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
queryset = Admission.objects.filter(tenant=self.request.user.tenant)
|
queryset = Admission.objects.filter(tenant=self.request.user.tenant)
|
||||||
|
|
||||||
# Filter by status
|
# Filter by status
|
||||||
status = self.request.GET.get('status')
|
status = self.request.GET.get('status')
|
||||||
if status:
|
if status:
|
||||||
@ -625,10 +625,15 @@ class AdmissionListView(LoginRequiredMixin, ListView):
|
|||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**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({
|
context.update({
|
||||||
'admission_statuses': Admission.STATUS_CHOICES,
|
'admission_statuses': Admission.STATUS_CHOICES,
|
||||||
'admission_types': Admission.ADMISSION_TYPE_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
|
return context
|
||||||
|
|
||||||
@ -909,7 +914,7 @@ def surgery_calendar(request):
|
|||||||
'operating_rooms': sorted(set(surgery.operating_room for surgery in surgeries))
|
'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
|
@login_required
|
||||||
@ -950,7 +955,7 @@ def transfer_patient(request, admission_id):
|
|||||||
transfer.save()
|
transfer.save()
|
||||||
|
|
||||||
# Log the action
|
# Log the action
|
||||||
AuditLogger.log(
|
AuditLogger.log_event(
|
||||||
actor=request.user,
|
actor=request.user,
|
||||||
action='TRANSFER_REQUESTED',
|
action='TRANSFER_REQUESTED',
|
||||||
target=admission,
|
target=admission,
|
||||||
@ -978,7 +983,7 @@ def transfer_patient(request, admission_id):
|
|||||||
'priorities': Transfer._meta.get_field('priority').choices
|
'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
|
@login_required
|
||||||
@ -986,6 +991,7 @@ def approve_transfer(request, transfer_id):
|
|||||||
"""
|
"""
|
||||||
HTMX endpoint for approving a transfer.
|
HTMX endpoint for approving a transfer.
|
||||||
"""
|
"""
|
||||||
|
print("transfer clicked")
|
||||||
transfer = get_object_or_404(Transfer, id=transfer_id, admission__tenant=request.user.tenant)
|
transfer = get_object_or_404(Transfer, id=transfer_id, admission__tenant=request.user.tenant)
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
@ -1008,7 +1014,7 @@ def approve_transfer(request, transfer_id):
|
|||||||
transfer.save()
|
transfer.save()
|
||||||
|
|
||||||
# Log the action
|
# Log the action
|
||||||
AuditLogger.log(
|
AuditLogger.log_event(
|
||||||
actor=request.user,
|
actor=request.user,
|
||||||
action='TRANSFER_APPROVED',
|
action='TRANSFER_APPROVED',
|
||||||
target=transfer,
|
target=transfer,
|
||||||
@ -1075,7 +1081,7 @@ def complete_transfer(request, transfer_id):
|
|||||||
admission.save()
|
admission.save()
|
||||||
|
|
||||||
# Log the action
|
# Log the action
|
||||||
AuditLogger.log(
|
AuditLogger.log_event(
|
||||||
actor=request.user,
|
actor=request.user,
|
||||||
action='TRANSFER_COMPLETED',
|
action='TRANSFER_COMPLETED',
|
||||||
target=transfer,
|
target=transfer,
|
||||||
@ -1124,7 +1130,7 @@ def update_bed_status(request, bed_id):
|
|||||||
bed.save()
|
bed.save()
|
||||||
|
|
||||||
# Log the action
|
# Log the action
|
||||||
AuditLogger.log(
|
AuditLogger.log_event(
|
||||||
actor=request.user,
|
actor=request.user,
|
||||||
action='BED_STATUS_UPDATED',
|
action='BED_STATUS_UPDATED',
|
||||||
target=bed,
|
target=bed,
|
||||||
@ -1559,62 +1565,62 @@ def maintenance_bed(request, pk):
|
|||||||
# return context
|
# return context
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
class WardDetailView(LoginRequiredMixin, DetailView):
|
# class WardDetailView(LoginRequiredMixin, DetailView):
|
||||||
"""
|
# """
|
||||||
Detail view for a ward.
|
# Detail view for a ward.
|
||||||
"""
|
# """
|
||||||
model = Ward
|
# model = Ward
|
||||||
template_name = 'inpatients/ward_detail.html'
|
# template_name = 'inpatients/ward_detail.html'
|
||||||
context_object_name = 'ward'
|
# context_object_name = 'ward'
|
||||||
|
#
|
||||||
def get_queryset(self):
|
# def get_queryset(self):
|
||||||
"""Filter wards by tenant."""
|
# """Filter wards by tenant."""
|
||||||
return Ward.objects.filter(
|
# return Ward.objects.filter(
|
||||||
tenant=self.request.user.tenant
|
# tenant=self.request.user.tenant
|
||||||
).select_related('nurse_manager')
|
# ).select_related('nurse_manager')
|
||||||
|
#
|
||||||
def get_context_data(self, **kwargs):
|
# def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
# context = super().get_context_data(**kwargs)
|
||||||
ward = self.get_object()
|
# ward = self.get_object()
|
||||||
|
#
|
||||||
# Get beds for this ward with patient information
|
# # Get beds for this ward with patient information
|
||||||
context['beds'] = Bed.objects.filter(
|
# context['beds'] = Bed.objects.filter(
|
||||||
ward=ward
|
# ward=ward
|
||||||
).select_related(
|
# ).select_related(
|
||||||
'current_patient', 'current_admission'
|
# 'current_patient', 'current_admission'
|
||||||
).order_by('room_number', 'bed_number')
|
# ).order_by('room_number', 'bed_number')
|
||||||
|
#
|
||||||
# Group beds by room for display
|
# # Group beds by room for display
|
||||||
rooms = {}
|
# rooms = {}
|
||||||
for bed in context['beds']:
|
# for bed in context['beds']:
|
||||||
room_num = bed.room_number
|
# room_num = bed.room_number
|
||||||
if room_num not in rooms:
|
# if room_num not in rooms:
|
||||||
rooms[room_num] = []
|
# rooms[room_num] = []
|
||||||
rooms[room_num].append(bed)
|
# rooms[room_num].append(bed)
|
||||||
context['rooms'] = rooms
|
# context['rooms'] = rooms
|
||||||
|
#
|
||||||
# Get ward statistics
|
# # Get ward statistics
|
||||||
context['total_beds'] = context['beds'].count()
|
# context['total_beds'] = context['beds'].count()
|
||||||
context['available_beds'] = context['beds'].filter(status='AVAILABLE').count()
|
# context['available_beds'] = context['beds'].filter(status='AVAILABLE').count()
|
||||||
context['occupied_beds'] = context['beds'].filter(status='OCCUPIED').count()
|
# context['occupied_beds'] = context['beds'].filter(status='OCCUPIED').count()
|
||||||
context['maintenance_beds'] = context['beds'].filter(
|
# context['maintenance_beds'] = context['beds'].filter(
|
||||||
status__in=['MAINTENANCE', 'OUT_OF_ORDER', 'CLEANING']
|
# status__in=['MAINTENANCE', 'OUT_OF_ORDER', 'CLEANING']
|
||||||
).count()
|
# ).count()
|
||||||
|
#
|
||||||
if context['total_beds'] > 0:
|
# if context['total_beds'] > 0:
|
||||||
context['occupancy_rate'] = (context['occupied_beds'] / context['total_beds']) * 100
|
# context['occupancy_rate'] = (context['occupied_beds'] / context['total_beds']) * 100
|
||||||
else:
|
# else:
|
||||||
context['occupancy_rate'] = 0
|
# context['occupancy_rate'] = 0
|
||||||
|
#
|
||||||
# Get recent admissions to this ward
|
# # Get recent admissions to this ward
|
||||||
context['recent_admissions'] = Admission.objects.filter(
|
# context['recent_admissions'] = Admission.objects.filter(
|
||||||
Q(initial_ward=ward) | Q(current_bed__ward=ward),
|
# Q(initial_ward=ward) | Q(current_bed__ward=ward),
|
||||||
status__in=['ADMITTED', 'READY_FOR_DISCHARGE']
|
# status__in=['ADMITTED', 'READY_FOR_DISCHARGE']
|
||||||
).select_related(
|
# ).select_related(
|
||||||
'patient', 'admitting_physician'
|
# 'patient', 'admitting_physician'
|
||||||
).order_by('-admitted_at')[:10]
|
# ).order_by('-admitted_at')[:10]
|
||||||
|
#
|
||||||
return context
|
# return context
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# class WardCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
|
# class WardCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
|
||||||
@ -2139,10 +2145,10 @@ def discharge_patient(request, pk):
|
|||||||
pk=pk,
|
pk=pk,
|
||||||
tenant=request.user.tenant
|
tenant=request.user.tenant
|
||||||
)
|
)
|
||||||
print(admission)
|
print(admission.status)
|
||||||
|
|
||||||
# Only admitted patients can be discharged
|
# 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'))
|
messages.error(request, _('Only admitted patients or patients ready for discharge can be discharged'))
|
||||||
return redirect('inpatients:admission_detail', pk=admission.pk)
|
return redirect('inpatients:admission_detail', pk=admission.pk)
|
||||||
|
|
||||||
@ -2156,6 +2162,7 @@ def discharge_patient(request, pk):
|
|||||||
if summary_form.is_valid():
|
if summary_form.is_valid():
|
||||||
summary = summary_form.save(commit=False)
|
summary = summary_form.save(commit=False)
|
||||||
summary.patient = admission.patient
|
summary.patient = admission.patient
|
||||||
|
summary.admission = admission
|
||||||
summary.created_by = request.user
|
summary.created_by = request.user
|
||||||
summary.save()
|
summary.save()
|
||||||
|
|
||||||
@ -2168,41 +2175,42 @@ def discharge_patient(request, pk):
|
|||||||
else:
|
else:
|
||||||
initial = {
|
initial = {
|
||||||
'patient': admission.patient,
|
'patient': admission.patient,
|
||||||
|
'admission': admission,
|
||||||
'discharge_diagnosis': admission.admitting_diagnosis,
|
'discharge_diagnosis': admission.admitting_diagnosis,
|
||||||
'doctor_name': request.user.get_full_name() if request.user.role in ['DOCTOR', 'SPECIALIST'] else ''
|
'doctor_name': request.user.get_full_name() if request.user.role in ['DOCTOR', 'SPECIALIST'] else ''
|
||||||
}
|
}
|
||||||
summary_form = DischargeSummaryForm(
|
summary_form = DischargeSummaryForm(
|
||||||
initial=initial,
|
initial=initial,
|
||||||
user=request.user,
|
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,
|
'admission': admission,
|
||||||
'form': summary_form
|
'form': summary_form
|
||||||
})
|
})
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# @login_required
|
@login_required
|
||||||
# @permission_required('inpatients.change_admission')
|
# @permission_required('inpatients.change_admission')
|
||||||
# def mark_ready_for_discharge(request, pk):
|
def mark_ready_for_discharge(request, pk):
|
||||||
# """
|
"""
|
||||||
# Mark a patient as ready for discharge.
|
Mark a patient as ready for discharge.
|
||||||
# """
|
"""
|
||||||
# admission = get_object_or_404(
|
admission = get_object_or_404(
|
||||||
# Admission,
|
Admission,
|
||||||
# pk=pk,
|
pk=pk,
|
||||||
# tenant=request.user.tenant
|
tenant=request.user.tenant
|
||||||
# )
|
)
|
||||||
#
|
|
||||||
# # Only admitted patients can be marked ready for discharge
|
# Only admitted patients can be marked ready for discharge
|
||||||
# if admission.status != 'ADMITTED':
|
if admission.status != 'ADMITTED':
|
||||||
# messages.error(request, _('Only admitted patients can be marked ready for discharge'))
|
messages.error(request, _('Only admitted patients can be marked ready for discharge'))
|
||||||
# return redirect('inpatients:admission_detail', pk=admission.pk)
|
return redirect('inpatients:admission_detail', pk=admission.pk)
|
||||||
#
|
|
||||||
# admission.mark_ready_for_discharge()
|
admission.mark_ready_for_discharge()
|
||||||
# messages.success(request, _('Patient marked ready for discharge'))
|
messages.success(request, _('Patient marked ready for discharge'))
|
||||||
# return redirect('inpatients:admission_detail', pk=admission.pk)
|
return redirect('inpatients:admission_detail', pk=admission.pk)
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# class TransferListView(LoginRequiredMixin, ListView):
|
# class TransferListView(LoginRequiredMixin, ListView):
|
||||||
@ -2977,36 +2985,36 @@ def discharge_patient(request, pk):
|
|||||||
# return redirect('inpatients:bed_detail', pk=bed.pk)
|
# return redirect('inpatients:bed_detail', pk=bed.pk)
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
@login_required
|
# @login_required
|
||||||
# @permission_required('inpatients.change_bed')
|
# @permission_required('inpatients.change_bed')
|
||||||
def maintenance_bed(request, pk):
|
# def maintenance_bed(request, pk):
|
||||||
"""
|
# """
|
||||||
Mark a bed for maintenance.
|
# Mark a bed for maintenance.
|
||||||
"""
|
# """
|
||||||
bed = get_object_or_404(
|
# bed = get_object_or_404(
|
||||||
Bed,
|
# Bed,
|
||||||
pk=pk,
|
# pk=pk,
|
||||||
ward__tenant=request.user.tenant
|
# ward__tenant=request.user.tenant
|
||||||
)
|
# )
|
||||||
|
#
|
||||||
# Only available beds can be marked for maintenance
|
# # Only available beds can be marked for maintenance
|
||||||
if bed.status != 'AVAILABLE':
|
# if bed.status != 'AVAILABLE':
|
||||||
messages.error(request, _('Only available beds can be marked for maintenance'))
|
# messages.error(request, _('Only available beds can be marked for maintenance'))
|
||||||
return redirect('inpatients:bed_detail', pk=bed.pk)
|
# return redirect('inpatients:bed_detail', pk=bed.pk)
|
||||||
|
#
|
||||||
if request.method == 'POST':
|
# if request.method == 'POST':
|
||||||
notes = request.POST.get('notes')
|
# notes = request.POST.get('notes')
|
||||||
|
#
|
||||||
# bed.mark_maintenance(notes)
|
# # bed.mark_maintenance(notes)
|
||||||
bed.status = 'MAINTENANCE'
|
# bed.status = 'MAINTENANCE'
|
||||||
bed.notes = notes
|
# bed.notes = notes
|
||||||
bed.save()
|
# bed.save()
|
||||||
messages.success(request, _('Bed marked for maintenance successfully'))
|
# messages.success(request, _('Bed marked for maintenance successfully'))
|
||||||
return redirect('inpatients:bed_detail', pk=bed.pk)
|
# return redirect('inpatients:bed_detail', pk=bed.pk)
|
||||||
|
#
|
||||||
return render(request, 'inpatients/maintenance_bed.html', {
|
# return render(request, 'inpatients/maintenance_bed.html', {
|
||||||
'bed': bed
|
# 'bed': bed
|
||||||
})
|
# })
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# @login_required
|
# @login_required
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -284,7 +284,7 @@
|
|||||||
{% elif admission.admission_type == 'DIRECT' %}red
|
{% elif admission.admission_type == 'DIRECT' %}red
|
||||||
{% else %}secondary
|
{% else %}secondary
|
||||||
{% endif %}">
|
{% endif %}">
|
||||||
{{ admission.admission_type }}
|
{{ admission.get_admission_type_display }}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@ -50,7 +50,7 @@
|
|||||||
color: #856404;
|
color: #856404;
|
||||||
}
|
}
|
||||||
.bed-out_of_order {
|
.bed-out_of_order {
|
||||||
background-color: #b6b4b4;
|
background-color: #c5c5c5;
|
||||||
color: #434242;
|
color: #434242;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,27 +437,24 @@ color: #434242;
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<div class="btn-group btn-group-sm">
|
<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>
|
<i class="fa fa-eye"></i>
|
||||||
</a>
|
</a>
|
||||||
{# <button class="btn btn-outline-primary" onclick="viewBedDetails('{{ bed.id }}')" title="View Details">#}
|
{# <button class="btn btn-outline-primary" onclick="viewBedDetails('{{ bed.id }}')" title="View Details">#}
|
||||||
{# <i class="fa fa-eye"></i>#}
|
{# <i class="fa fa-eye"></i>#}
|
||||||
{# </button>#}
|
{# </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>
|
<i class="fa fa-edit"></i>
|
||||||
</a>
|
</a>
|
||||||
{% if bed.status == 'AVAILABLE' %}
|
{% 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>
|
<i class="fa fa-user-plus"></i>
|
||||||
</a>
|
</a>
|
||||||
{% elif bed.status == 'OCCUPIED' %}
|
{% elif bed.status == 'OCCUPIED' %}
|
||||||
{% if bed.current_admission %}
|
{% 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>
|
<i class="fa fa-sign-out-alt"></i>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -615,8 +612,8 @@ color: #434242;
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Bed Details Modal -->
|
<!-- Bed Details Modal -->
|
||||||
<div class="modal fade" id="bedDetailsModal" tabindex="-1">
|
<div class="modal fade" id="bedDetailsModal" tabindex="-1">
|
||||||
@ -685,7 +682,8 @@ color: #434242;
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
|
|||||||
@ -176,17 +176,20 @@
|
|||||||
<div class="planning-header">
|
<div class="planning-header">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<h5><i class="fas fa-user"></i> Patient: Robert Davis</h5>
|
<h5><i class="fas fa-user"></i> Patient: {{ admission.patient.get_full_name }}</h5>
|
||||||
<p><strong>MRN:</strong> MRN456789 | <strong>Age:</strong> 68 years | <strong>Gender:</strong> Male</p>
|
<p><strong>MRN:</strong> {{ admission.patient.mrn }} | <strong>Age:</strong> {{ admission.patient.age }} | <strong>Gender:</strong>
|
||||||
<p><strong>Admission Date:</strong> January 15, 2024 | <strong>Length of Stay:</strong> 5 days</p>
|
{{ admission.patient.get_gender_display }}</p>
|
||||||
<p><strong>Primary Diagnosis:</strong> Acute Myocardial Infarction | <strong>Attending:</strong> Dr. Johnson</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>
|
||||||
<div class="col-md-4 text-end">
|
<div class="col-md-4 text-end">
|
||||||
<div class="progress-bar-custom">
|
<div class="progress-bar-custom">
|
||||||
<div class="progress-fill" style="width: 75%"></div>
|
<div class="progress-fill" style="width: 75%"></div>
|
||||||
<div class="progress-text">75% Complete</div>
|
<div class="progress-text">75% Complete</div>
|
||||||
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
{% block title %}Bed Maintenance Management{% endblock %}
|
{% block title %}Bed Maintenance Management{% endblock %}
|
||||||
|
|
||||||
{% block extra_css %}
|
{% block extra_css %}
|
||||||
<link href="{% static 'assets/plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
|
<link href="{% static '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-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
|
||||||
<style>
|
<style>
|
||||||
.maintenance-status-scheduled { color: #ffc107; }
|
.maintenance-status-scheduled { color: #ffc107; }
|
||||||
.maintenance-status-in-progress { color: #17a2b8; }
|
.maintenance-status-in-progress { color: #17a2b8; }
|
||||||
@ -491,10 +491,10 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block extra_js %}
|
{% block extra_js %}
|
||||||
<script src="{% static 'assets/plugins/datatables.net/js/jquery.dataTables.min.js' %}"></script>
|
<script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
|
||||||
<script src="{% static 'assets/plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
|
<script src="{% static '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 '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-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|||||||
@ -86,7 +86,7 @@
|
|||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<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 %}
|
{% csrf_token %}
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
|
|||||||
@ -79,7 +79,7 @@
|
|||||||
<!-- Patient Information Card -->
|
<!-- Patient Information Card -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card">
|
<div class="card mb-4">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h5><i class="fas fa-user"></i> Patient Information</h5>
|
<h5><i class="fas fa-user"></i> Patient Information</h5>
|
||||||
<span class="discharge-status status-pending">Discharge in Progress</span>
|
<span class="discharge-status status-pending">Discharge in Progress</span>
|
||||||
@ -87,16 +87,16 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<p><strong>Patient:</strong> {{ patient.full_name|default:"John Doe" }}</p>
|
<p><strong>Patient:</strong> {{ admission.patient.get_full_name }}</p>
|
||||||
<p><strong>MRN:</strong> {{ patient.medical_record_number|default:"MRN123456" }}</p>
|
<p><strong>MRN:</strong> {{ admission.patient.mrn }}</p>
|
||||||
<p><strong>DOB:</strong> {{ patient.date_of_birth|default:"1980-01-01" }}</p>
|
<p><strong>DOB:</strong> {{ admission.patient.date_of_birth }}</p>
|
||||||
<p><strong>Gender:</strong> {{ patient.gender|default:"Male" }}</p>
|
<p><strong>Gender:</strong> {{ admission.patient.gender }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<p><strong>Admission Date:</strong> {{ admission.admission_date|default:"2024-01-15" }}</p>
|
<p><strong>Admission Date:</strong> {{ admission.admission_datetime|date:'Y:m:d' }}</p>
|
||||||
<p><strong>Length of Stay:</strong> {{ admission.length_of_stay|default:"5 days" }}</p>
|
<p><strong>Length of Stay:</strong> {{ admission.length_of_stay }}</p>
|
||||||
<p><strong>Attending Physician:</strong> {{ admission.attending_physician|default:"Dr. Smith" }}</p>
|
<p><strong>Attending Physician:</strong> {{ admission.attending_physician }}</p>
|
||||||
<p><strong>Ward/Room:</strong> {{ admission.bed.ward.name|default:"Ward A" }} - {{ admission.bed.room_number|default:"101" }}</p>
|
<p><strong>Ward/Room:</strong> {{ admission.current_bed.ward.name }} - {{ admission.current_bed.room_number }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -107,7 +107,7 @@
|
|||||||
<!-- Discharge Checklist -->
|
<!-- Discharge Checklist -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<div class="card">
|
<div class="card mb-4">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h5><i class="fas fa-tasks"></i> Discharge Checklist</h5>
|
<h5><i class="fas fa-tasks"></i> Discharge Checklist</h5>
|
||||||
</div>
|
</div>
|
||||||
@ -182,7 +182,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<div class="card">
|
<div class="card mb-4">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h5><i class="fas fa-clock"></i> Discharge Timeline</h5>
|
<h5><i class="fas fa-clock"></i> Discharge Timeline</h5>
|
||||||
</div>
|
</div>
|
||||||
@ -192,14 +192,14 @@
|
|||||||
<div class="timeline-marker"></div>
|
<div class="timeline-marker"></div>
|
||||||
<div class="timeline-content">
|
<div class="timeline-content">
|
||||||
<h6>Discharge Order</h6>
|
<h6>Discharge Order</h6>
|
||||||
<p>09:00 AM - Dr. Smith</p>
|
<p>{{ admission.anticipated_discharge_date }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="timeline-item completed">
|
<div class="timeline-item completed">
|
||||||
<div class="timeline-marker"></div>
|
<div class="timeline-marker"></div>
|
||||||
<div class="timeline-content">
|
<div class="timeline-content">
|
||||||
<h6>Medication Review</h6>
|
<h6>Medication Review</h6>
|
||||||
<p>10:30 AM - Pharmacist</p>
|
<p>{{ admission.patient }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="timeline-item active">
|
<div class="timeline-item active">
|
||||||
|
|||||||
@ -121,28 +121,26 @@
|
|||||||
<td>
|
<td>
|
||||||
<div class="btn-group btn-group-sm">
|
<div class="btn-group btn-group-sm">
|
||||||
{% if transfer.status == 'REQUESTED' %}
|
{% if transfer.status == 'REQUESTED' %}
|
||||||
<button class="btn btn-outline-success"
|
<a class="btn btn-outline-success"
|
||||||
title="Approve"
|
title="Approve"
|
||||||
hx-post="{% url 'inpatients:approve_transfer' transfer.id %}"
|
href="{% url 'inpatients:approve_transfer' transfer.id %}">
|
||||||
hx-confirm="Approve this transfer?"
|
|
||||||
hx-swap="none">
|
|
||||||
<i class="fas fa-check"></i>
|
<i class="fas fa-check"></i>
|
||||||
</button>
|
</a>
|
||||||
<button class="btn btn-outline-danger"
|
{# <button class="btn btn-outline-danger" #}
|
||||||
title="Reject"
|
{# title="Reject"#}
|
||||||
hx-post="{% url 'inpatients:reject_transfer' transfer.id %}"
|
{# hx-post="{% url 'inpatients:reject_transfer' transfer.id %}"#}
|
||||||
hx-confirm="Reject this transfer?"
|
{# hx-confirm="Reject this transfer?"#}
|
||||||
hx-swap="none">
|
{# hx-swap="none">#}
|
||||||
<i class="fas fa-times"></i>
|
{# <i class="fas fa-times"></i>#}
|
||||||
</button>
|
{# </button>#}
|
||||||
{% elif transfer.status == 'APPROVED' or transfer.status == 'SCHEDULED' %}
|
{% elif transfer.status == 'APPROVED' or transfer.status == 'SCHEDULED' %}
|
||||||
<button class="btn btn-outline-primary"
|
{# <button class="btn btn-outline-primary" #}
|
||||||
title="Execute Transfer"
|
{# title="Execute Transfer"#}
|
||||||
hx-post="{% url 'inpatients:execute_transfer' transfer.id %}"
|
{# hx-post="{% url 'inpatients:execute_transfer' transfer.id %}"#}
|
||||||
hx-confirm="Execute this transfer?"
|
{# hx-confirm="Execute this transfer?"#}
|
||||||
hx-swap="none">
|
{# hx-swap="none">#}
|
||||||
<i class="fas fa-play"></i>
|
{# <i class="fas fa-play"></i>#}
|
||||||
</button>
|
{# </button>#}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<button class="btn btn-outline-info" title="View Details">
|
<button class="btn btn-outline-info" title="View Details">
|
||||||
@ -176,33 +174,7 @@
|
|||||||
|
|
||||||
<!-- Pagination -->
|
<!-- Pagination -->
|
||||||
{% if is_paginated %}
|
{% if is_paginated %}
|
||||||
<nav aria-label="Transfer pagination">
|
{% include 'partial/pagination.html'%}
|
||||||
<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>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user