This commit is contained in:
Marwan Alwali 2025-09-22 01:37:55 +03:00
parent 94e180f776
commit 4ca3f7159a
41 changed files with 61390 additions and 2853 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -51,7 +51,7 @@ class AppointmentRequestForm(forms.ModelForm):
self.fields['provider'].queryset = User.objects.filter(
tenant=user.tenant,
is_active=True,
role__in=['PHYSICIAN', 'NURSE', 'NURSE_PRACTITIONER', 'PHYSICIAN_ASSISTANT']
employee_profile__role__in=['PHYSICIAN', 'NURSE', 'NURSE_PRACTITIONER', 'PHYSICIAN_ASSISTANT']
).order_by('last_name', 'first_name')
def clean_preferred_date(self):

173
current_prompt.md Normal file
View File

@ -0,0 +1,173 @@
Agent Instructions:
You are a senior Django architect and full-stack developer. This is a very large, mission-critical project—do **not** dump all code at once. Follow this strict phased plan-and-approve workflow to minimize hallucination and ensure accuracy:
**Phase 1 Planning**
1. Produce a high-level outline of every app/module, its responsibilities, and the key models, views/endpoints, HTMX interactions, Celery tasks, HL7 and DICOM/PACS interfaces, AI analytics hooks, and compliance/multitenancy considerations.
2. Pause and wait for my confirmation before proceeding.
**Phase 2 Scoping & Approval (per app)**
For each confirmed app (one at a time):
1. List all models, fields, relationships, and choice enums in full detail.
2. List required UI views (with HTMX attributes) and REST API endpoints/URLs.
3. List any Celery tasks, HL7/DICOM integration points, IoT hooks, and AI rule triggers.
4. Pause and wait for my “👍 go ahead with [app_name]” before generating any code.
**Phase 3 Implementation (per app)**
When I approve an app:
1. Generate **models.py** for that app only.
2. Pause for my review and approval.
3. Generate **serializers.py** and/or **forms.py**, then pause for review.
4. Generate **views.py**, **templates/**, and any necessary HTMX snippets, then pause for review.
5. Generate **static asset scaffolding** (SASS partials, HTMX/JS modules) and pause for review.
**Phase 4 Shared Tooling & Final Integration**
After all apps are complete:
1. Generate Webpack (or Django-Webpack-Loader) setup, SCSS/JS bundling, and `django-compressor` config.
2. Generate Celery configuration with Redis broker and example tasks (including HL7/DICOM polling, IoT data ingestion, AI analytics jobs).
3. Generate the **hl7_interface** and **pacs_interface** apps: models, utilities, management commands, and Celery tasks for HL7 v2.x and DICOM messaging.
4. Generate DRF API docs (Swagger) config, pytest setup, and GitHub Actions CI workflow.
5. Generate example Gunicorn + Nginx deployment snippets with multitenancy and SSL/TLS, and notes on GDPR/HIPAA compliance (encryption at rest, audit logs, consent management).
6. Provide a comprehensive README covering:
- Python virtualenv setup
- `npm install && npm run build`
- `manage.py migrate`, superuser setup
- ColorAdmin license integration
- HTMX usage guidelines
- HL7/DICOM endpoint configuration
- IoT device onboarding
- AI risk-scoring configuration
- Multitenancy setup
- Compliance controls (2FA, encryption, consent capture)
---
**Project Specification**
Project name: `hospital_management`
UI theme: ColorAdmin template (all CSS/JS centralized—no inline or per-template scripts/styles)
Dynamic behavior: HTMX for all interactive features
Messaging: Optional inbound/outbound HL7 and DICOM/PACS interfaces
Analytics: AI-driven predictive risk scoring hooks in `decision_support`
Security & Compliance:
- Two-factor authentication, encryption at rest, GDPR/HIPAA audit trails
- Consent management, digital signatures, detailed audit logs
- Tenant-scoped data isolation for multi-hospital support
**Apps, Models & Fields**
1. **accounts**
- `User` (extends AbstractUser): username, email, first_name, last_name, password, role (choices: Admin, Doctor, Nurse, LabTech, Pharmacist, Receptionist, Patient, EMS), is_active, date_joined, tenant
- `TwoFactorDevice`: user FK, device_type, secret_key, confirmed
- `SocialAccount` (django-allauth)
2. **core**
- `AuditLogEntry`: user FK, action, timestamp, object_type, object_id, change_detail
- HL7Utility & DICOMUtility modules (no models; parsing/building functions)
3. **patients**
- `PatientProfile`: user FK (Patient), medical_record_number, date_of_birth, gender, blood_type, allergies (text), address, phone, emergency_contact FK, insurance_info FK
- `EmergencyContact`: patient FK, name, relationship, phone, email
- `InsuranceInfo`: patient FK, provider, policy_number, group_number, coverage_start_date, coverage_end_date
- `ConsentForm`: patient FK, form_type, document (FileField), signed_at, signed_by FK
4. **appointments**
- `AppointmentRequest`: patient FK, doctor FK, department, requested_datetime, status (Pending/Confirmed/Cancelled), created_at, updated_at
- `SlotAvailability`: doctor FK, date, start_time, end_time, is_available
- `WaitingQueue`: appointment FK, position, created_at
- VirtualCare scheduled via `TelemedicineSession`: patient FK, provider FK, session_url, start_time, end_time, status
5. **inpatients**
- `Ward`: name, floor, capacity, department
- `Bed`: ward FK, bed_number, bed_type (choices: General/ICU/Private), status
- `Admission`: patient FK, ward FK, bed FK, admitted_at, admitted_by FK, reason, status
- `DischargeSummary`: admission FK, summary_text, discharged_at, discharged_by FK
- `Transfer`: admission FK, from_ward FK, to_ward FK, transferred_at, reason
- `SurgerySchedule`: patient FK, surgeon FK, or_block FK, scheduled_at, duration, status
6. **emr**
- `Encounter`: patient FK, encounter_date, provider FK, encounter_type, notes
- `VitalSigns`: encounter FK, recorded_at, temperature, heart_rate, bp_systolic, bp_diastolic, respiratory_rate, oxygen_saturation
- `ProblemList`: patient FK, description, onset_date, status, notes
- `CarePlan`: encounter FK, goal, interventions, status
- `ClinicalNote`: encounter FK, note_type, content, created_at, created_by FK
7. **billing**
- `Invoice`: patient FK, date_issued, due_date, total_amount, status
- `ChargeItem`: invoice FK, description, code, quantity, unit_price, total_price
- `Payment`: invoice FK, amount, method, paid_at, transaction_id
- `InsuranceClaim`: invoice FK, claim_number, status, submitted_at, adjudicated_at
8. **pharmacy**
- `Medication`: name, code, description, unit, dosage_form
- `Prescription`: patient FK, prescriber FK, prescribed_at, status
- `DispenseRecord`: prescription FK, medication FK, quantity, dispensed_at, dispenser FK
- `StockItem`: medication FK, batch_number, expiration_date, quantity_on_hand, minimum_threshold
9. **laboratory**
- `LabTest`: name, code, description, specimen_type, department
- `Specimen`: lab_test FK, patient FK, collected_at, collected_by FK, status
- `Result`: specimen FK, result_value, units, reference_range, result_date, verified_by FK
- `LISIntegrationLog`: message_id, direction, payload, status, processed_at
10. **radiology**
- `RadiologyOrder`: patient FK, imaging_type, ordered_by FK, order_date, priority, status
- `ImagingStudy`: order FK, modality, study_date, images_count, report_status
- `RadiologyReport`: study FK, report_text, dictated_by FK, dictated_at, approved_by FK, approved_at
- `DICOMStudy`: study_instance_uid, patient_fk, modality, study_date, series_data (JSON)
11. **inventory**
- `SupplyItem`: name, sku, description, category, unit, reorder_level, location
- `PurchaseOrder`: supplier FK, order_date, expected_date, status, total_amount
- `StockTransaction`: item FK, transaction_type, quantity, transaction_date, reference
12. **decision_support**
- `CDSSRule`: name, trigger_event, condition_expression, action, active
- `AlertLog`: rule FK, patient FK, triggered_at, message, status
- AI hooks: risk_scoring_config (JSON), last_run, score_thresholds
13. **reporting**
- `CustomReport`: name, description, owner FK, query_definition (JSON), created_at, updated_at
- `DashboardWidget`: name, report FK, widget_type, settings (JSON), position
14. **hl7_interface**
- `HL7Endpoint`: name, host, port, protocol, is_active, last_checked
- `HL7MessageLog`: endpoint FK, direction, message_type, raw_message, parsed_message, sent_at, received_at, status
15. **pacs_interface**
- `PACSConnection`: name, ae_title, host, port, is_active
- `PACSLog`: connection FK, direction, dicom_uid, raw_payload, processed_at, status
16. **operating_theatre**
- `ORBlock`: name, theater_number, department, available_slots (JSON)
- `EquipmentReservation`: device FK, or_block FK, reserved_from, reserved_to, status
17. **assets**
- `MedicalDevice`: name, serial_number, category, location, status, last_maintenance
- `MaintenanceLog`: device FK, performed_at, performed_by FK, notes
- `IoTSensorReading`: device FK, timestamp, data (JSON)
18. **ems**
- `DispatchRequest`: caller_info, location, priority, status, created_at
- `Ambulance`: identifier, capacity, status, location
- `CrewMember`: user FK, ambulance FK, role
- `TripLog`: dispatch FK, ambulance FK, start_time, end_time, patient_fk
19. **nutrition**
- `MealPlan`: patient FK, date, meals (JSON), dietary_restrictions
- `DietaryOrder`: patient FK, meal_type, order_time, status
- `KitchenTask`: plan FK, task_description, assigned_to FK, status, completed_at
20. **security**
- `EncryptionKey`: key_name, key_type, created_at, rotation_date
- `AuditLogEntry` (enhanced for GDPR/HIPAA as above)
---
**Shared Tooling, Interactivity & Deployment**
- **Assets**: SCSS in `assets/scss/``static/dist/main.css`; JS in `assets/js/``static/dist/main.js` via Webpack + Babel; `django-compressor` for compression.
- **HTMX**: All dynamic features use `hx-*` attributes—no per-template JS.
- **API**: DRF ModelViewSets under `/api/v1/`, secured with JWT/OAuth2, Swagger UI at `/api/docs/`.
- **Background**: Celery+Redis for notifications, HL7/DICOM messaging, IoT ingestion, AI scoring.
- **Testing/CI**: `pytest` + GitHub Actions for lint/test/build.
- **Deployment**: Gunicorn+Nginx configs, multitenancy notes, SSL/TLS, GDPR/HIPAA compliance checklist, 2FA setup, consent management, and monitoring guidance.
Ensure phased execution and strictly pause for approvals at each step. Good luck!

Binary file not shown.

View File

@ -511,6 +511,26 @@ class Bed(models.Model):
return timezone.now() - self.occupied_since
return None
def mark_maintenance(self, notes=None):
"""
Mark bed for maintenance.
"""
self.status = 'MAINTENANCE'
self.last_maintenance = timezone.now()
if notes:
self.maintenance_notes = notes
self.save()
def mark_cleaned(self, user, cleaning_level='STANDARD'):
"""
Mark bed as cleaned.
"""
self.status = 'AVAILABLE'
self.last_cleaned = timezone.now()
self.cleaned_by = user
self.cleaning_level = cleaning_level
self.save()
class Admission(models.Model):
"""
@ -1719,4 +1739,3 @@ class SurgerySchedule(models.Model):
if self.actual_duration_minutes:
return self.actual_duration_minutes - self.estimated_duration_minutes
return None

View File

@ -3,6 +3,10 @@
{% block title %}Bed {{ object.bed_number }} Details{% endblock %}
{% block extra_head %}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
{% endblock %}
{% block content %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<div>
@ -190,86 +194,27 @@
{% endif %}
<!-- Bed History -->
<div class="panel panel-inverse" data-sortable-id="index-3">
<div class="panel-heading">
<h4 class="panel-title">
<i class="fas fa-history me-2"></i>Bed History
</h4>
<div class="panel-heading-btn">
<button type="button" class="btn btn-xs btn-outline-primary me-2" onclick="refreshHistory()">
<i class="fas fa-sync me-2"></i>Refresh
</button>
<a href="javascript:" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
<a href="javascript:" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
<a href="javascript:" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>
</div>
</div>
<div class="panel-body">
{% if admission_history %}
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Date</th>
<th>Action</th>
<th>Patient</th>
<th>Duration</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
{% for history in admission_history %}
<tr>
<td>
<div>{{ history.admission_datetime|date:"M d, Y" }}</div>
<div class="small text-muted">{{ history.admission_datetime|time:"g:i A" }}</div>
</td>
<td>
<span class="badge bg-{% if history.action == 'ADMISSION' %}success{% elif history.action == 'DISCHARGE' %}info{% elif history.action == 'TRANSFER' %}warning{% else %}secondary{% endif %}">
{{ history.get_action_display }}
</span>
</td>
<td>
{% if history.patient %}
<a href="{% url 'patients:patient_detail' history.patient.pk %}">
{{ history.patient.get_full_name }}
</a>
<div class="small text-muted">{{ history.patient.mrn }}</div>
{% else %}
<span class="text-muted">System action</span>
{% endif %}
</td>
<td>
{% if history.duration %}
{{ history.duration }}
{% else %}
<span class="text-muted">-</span>
{% endif %}
</td>
<td>
{% if history.notes %}
<span class="text-truncate" style="max-width: 200px;" title="{{ history.notes }}">
{{ history.notes }}
</span>
{% else %}
<span class="text-muted">-</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center text-muted py-4">
<i class="fas fa-history fa-3x mb-3"></i>
<h5>No History Available</h5>
<p>No bed history records found for this bed.</p>
</div>
{% endif %}
</div>
</div>
<div class="panel panel-inverse" data-sortable-id="index-3">
<div class="panel-heading">
<h4 class="panel-title">
<i class="fas fa-history me-2"></i>Bed History
</h4>
<div class="panel-heading-btn">
<button type="button" class="btn btn-xs btn-outline-primary me-2" hx-get="{% url 'inpatients:refresh_bed_history' object.pk %}" hx-target="#bed-history-body" hx-swap="innerHTML">
<i class="fas fa-sync me-2"></i>Refresh
</button>
<a href="javascript:" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
<a href="javascript:" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
<a href="javascript:" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>
</div>
</div>
<div class="panel-body">
<div id="bed-history-body">
{% include 'inpatients/partials/bed_history.html' %}
</div>
</div>
</div>
</div>
<div class="col-xl-3">
@ -439,7 +384,7 @@
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="statusUpdateForm">
<form id="statusUpdateForm" method="post" action="{% url 'inpatients:update_bed_status' object.pk %}">
{% csrf_token %}
<input type="hidden" id="newStatus" name="status">
<div class="mb-3">
@ -456,6 +401,310 @@
</div>
</div>
<!-- Assign Patient Modal -->
<div class="modal fade" id="assignPatientModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Assign Patient to Bed</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="assignPatientForm" method="post" action="{% url 'inpatients:assign_patient_to_bed' object.pk %}">
{% csrf_token %}
<div class="mb-3">
<label for="patientSearch" class="form-label">Search Patient</label>
<input type="text" class="form-control" id="patientSearch" placeholder="Search by name or MRN..." onkeyup="searchPatients()">
<div id="patientResults" class="mt-2" style="max-height: 200px; overflow-y: auto;"></div>
</div>
<input type="hidden" id="selectedPatientId" name="patient_id">
<div id="selectedPatientInfo" class="d-none">
<div class="card">
<div class="card-body">
<h6 class="card-title">Selected Patient</h6>
<div id="patientDetails"></div>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="assignBtn" disabled onclick="assignPatientToBed()">Assign Patient</button>
</div>
</div>
</div>
</div>
<!-- Discharge Patient Modal -->
<div class="modal fade" id="dischargePatientModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Discharge Patient</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
{% if object.current_admission %}
<div class="alert alert-warning">
<i class="fas fa-exclamation-triangle me-2"></i>
You are about to discharge <strong>{{ object.current_admission.patient.get_full_name }}</strong> from this bed.
</div>
<form id="dischargeForm" method="post" action="{% url 'inpatients:discharge_patient' object.current_admission.pk %}">
{% csrf_token %}
<div class="mb-3">
<label for="dischargeReason" class="form-label">Discharge Reason</label>
<select class="form-control" id="dischargeReason" name="discharge_reason" required>
<option value="">Select reason...</option>
<option value="RECOVERED">Recovered</option>
<option value="TRANSFERRED">Transferred to another facility</option>
<option value="AGAINST_MEDICAL_ADVICE">Against medical advice</option>
<option value="DECEASED">Deceased</option>
<option value="OTHER">Other</option>
</select>
</div>
<div class="mb-3">
<label for="dischargeNotes" class="form-label">Discharge Notes</label>
<textarea class="form-control" id="dischargeNotes" name="notes" rows="3" placeholder="Additional notes..."></textarea>
</div>
</form>
{% else %}
<div class="alert alert-info">
No patient is currently assigned to this bed.
</div>
{% endif %}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
{% if object.current_admission %}
<button type="button" class="btn btn-danger" onclick="dischargePatientConfirm()">Discharge Patient</button>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Transfer Patient Modal -->
<div class="modal fade" id="transferPatientModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Transfer Patient</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
{% if object.current_admission %}
<form id="transferForm" method="post" action="{% url 'inpatients:transfer_patient' object.current_admission.pk %}">
{% csrf_token %}
<div class="mb-3">
<label class="form-label">Current Location</label>
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-6">
<strong>Ward:</strong> {{ object.ward.name }}<br>
<strong>Bed:</strong> {{ object.bed_number }}
</div>
<div class="col-md-6">
<strong>Patient:</strong> {{ object.current_admission.patient.get_full_name }}<br>
<strong>Admission Date:</strong> {{ object.current_admission.admission_datetime|date:"M d, Y" }}
</div>
</div>
</div>
</div>
</div>
<div class="mb-3">
<label for="toWard" class="form-label">Transfer to Ward</label>
<select class="form-control" id="toWard" name="to_ward" required onchange="loadAvailableBeds()">
<option value="">Select ward...</option>
{% for ward in wards %}
{% if ward != object.ward %}
<option value="{{ ward.pk }}">{{ ward.name }} ({{ ward.available_beds }} available)</option>
{% endif %}
{% endfor %}
</select>
</div>
<div class="mb-3">
<label for="toBed" class="form-label">Transfer to Bed</label>
<select class="form-control" id="toBed" name="to_bed">
<option value="">Select bed...</option>
</select>
</div>
<div class="mb-3">
<label for="transferReason" class="form-label">Transfer Reason</label>
<select class="form-control" id="transferReason" name="reason" required>
<option value="">Select reason...</option>
<option value="CLINICAL_NEED">Clinical need</option>
<option value="BED_AVAILABILITY">Bed availability</option>
<option value="PATIENT_REQUEST">Patient request</option>
<option value="WARD_MAINTENANCE">Ward maintenance</option>
<option value="OTHER">Other</option>
</select>
</div>
<div class="mb-3">
<label for="transferPriority" class="form-label">Priority</label>
<select class="form-control" id="transferPriority" name="priority">
<option value="ROUTINE">Routine</option>
<option value="URGENT">Urgent</option>
<option value="EMERGENCY">Emergency</option>
</select>
</div>
<div class="mb-3">
<label for="transferNotes" class="form-label">Notes</label>
<textarea class="form-control" id="transferNotes" name="notes" rows="2" placeholder="Additional notes..."></textarea>
</div>
</form>
{% else %}
<div class="alert alert-info">
No patient is currently assigned to this bed.
</div>
{% endif %}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
{% if object.current_admission %}
<button type="button" class="btn btn-primary" onclick="transferPatientConfirm()">Initiate Transfer</button>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Schedule Cleaning Modal -->
<div class="modal fade" id="scheduleCleaningModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Schedule Cleaning</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="cleaningForm" method="post" action="{% url 'inpatients:clean_bed' object.pk %}">
{% csrf_token %}
<div class="mb-3">
<label for="cleaningLevel" class="form-label">Cleaning Level</label>
<select class="form-control" id="cleaningLevel" name="cleaning_level" required>
<option value="ROUTINE">Routine</option>
<option value="DEEP">Deep cleaning</option>
<option value="TERMINAL">Terminal cleaning</option>
</select>
</div>
<div class="mb-3">
<label for="cleaningNotes" class="form-label">Notes</label>
<textarea class="form-control" id="cleaningNotes" name="notes" rows="2" placeholder="Special instructions..."></textarea>
</div>
<div class="mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="markCleaned" name="mark_cleaned">
<label class="form-check-label" for="markCleaned">
Mark as cleaned immediately
</label>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" onclick="scheduleCleaningConfirm()">Schedule Cleaning</button>
</div>
</div>
</div>
</div>
<!-- Schedule Maintenance Modal -->
<div class="modal fade" id="scheduleMaintenanceModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Schedule Maintenance</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="maintenanceForm" method="post" action="{% url 'inpatients:maintenance_bed' object.pk %}">
{% csrf_token %}
<div class="mb-3">
<label for="maintenanceType" class="form-label">Maintenance Type</label>
<select class="form-control" id="maintenanceType" name="maintenance_type" required>
<option value="REPAIR">Repair</option>
<option value="INSPECTION">Inspection</option>
<option value="REPLACEMENT">Equipment replacement</option>
<option value="UPGRADE">Upgrade</option>
</select>
</div>
<div class="mb-3">
<label for="maintenanceNotes" class="form-label">Description</label>
<textarea class="form-control" id="maintenanceNotes" name="notes" rows="3" placeholder="Describe the maintenance needed..." required></textarea>
</div>
<div class="mb-3">
<label for="priority" class="form-label">Priority</label>
<select class="form-control" id="priority" name="priority">
<option value="LOW">Low</option>
<option value="MEDIUM">Medium</option>
<option value="HIGH">High</option>
<option value="URGENT">Urgent</option>
</select>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" onclick="scheduleMaintenanceConfirm()">Schedule Maintenance</button>
</div>
</div>
</div>
</div>
<!-- Bed Utilization Chart Modal -->
<div class="modal fade" id="bedChartModal" tabindex="-1">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Bed Utilization Chart</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-8">
<canvas id="utilizationChart" width="400" height="200"></canvas>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header">
<h6 class="card-title mb-0">Statistics</h6>
</div>
<div class="card-body">
<div class="mb-3">
<div class="d-flex justify-content-between">
<span>Current Occupancy:</span>
<span id="currentOccupancy">{{ bed_stats.occupancy_rate|default:0 }}%</span>
</div>
</div>
<div class="mb-3">
<div class="d-flex justify-content-between">
<span>Total Admissions:</span>
<span>{{ bed_stats.total_admissions|default:0 }}</span>
</div>
</div>
<div class="mb-3">
<div class="d-flex justify-content-between">
<span>Avg Stay (days):</span>
<span>{{ bed_stats.avg_stay_days|default:0 }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script src="{% static 'plugins/chart.js/dist/chart.umd.js' %}"></script>
<script>
function updateBedStatus(status) {
document.getElementById('newStatus').value = status;
@ -465,52 +714,151 @@ function updateBedStatus(status) {
function confirmStatusUpdate() {
const form = document.getElementById('statusUpdateForm');
const formData = new FormData(form);
// In a real implementation, this would submit via AJAX
console.log('Updating bed status to:', formData.get('status'));
// Close modal and refresh page
bootstrap.Modal.getInstance(document.getElementById('updateStatusModal')).hide();
location.reload();
form.submit();
}
function assignPatient() {
// In a real implementation, this would open a patient selection modal
alert('Patient assignment functionality would be implemented here.');
const modal = new bootstrap.Modal(document.getElementById('assignPatientModal'));
modal.show();
}
function searchPatients() {
const query = document.getElementById('patientSearch').value;
if (query.length < 2) {
document.getElementById('patientResults').innerHTML = '';
return;
}
fetch(`/patients/api/search/?q=${encodeURIComponent(query)}`)
.then(response => response.json())
.then(data => {
let html = '';
data.forEach(patient => {
html += `
<div class="patient-result p-2 border-bottom" onclick="selectPatient(${patient.id}, '${patient.full_name}', '${patient.mrn}', '${patient.date_of_birth}')">
<strong>${patient.full_name}</strong><br>
<small class="text-muted">MRN: ${patient.mrn} | DOB: ${patient.date_of_birth}</small>
</div>
`;
});
document.getElementById('patientResults').innerHTML = html;
})
.catch(error => console.error('Error searching patients:', error));
}
function selectPatient(id, name, mrn, dob) {
document.getElementById('selectedPatientId').value = id;
document.getElementById('patientDetails').innerHTML = `
<strong>${name}</strong><br>
<small class="text-muted">MRN: ${mrn} | DOB: ${dob}</small>
`;
document.getElementById('selectedPatientInfo').classList.remove('d-none');
document.getElementById('assignBtn').disabled = false;
document.getElementById('patientResults').innerHTML = '';
}
function assignPatientToBed() {
const form = document.getElementById('assignPatientForm');
form.submit();
}
function dischargePatient() {
if (confirm('Are you sure you want to discharge the current patient?')) {
// In a real implementation, this would handle discharge process
alert('Discharge process would be initiated here.');
}
const modal = new bootstrap.Modal(document.getElementById('dischargePatientModal'));
modal.show();
}
function dischargePatientConfirm() {
const form = document.getElementById('dischargeForm');
form.submit();
}
function transferPatient() {
// In a real implementation, this would open a transfer modal
alert('Patient transfer functionality would be implemented here.');
const modal = new bootstrap.Modal(document.getElementById('transferPatientModal'));
modal.show();
}
function loadAvailableBeds() {
const wardId = document.getElementById('toWard').value;
const bedSelect = document.getElementById('toBed');
if (!wardId) {
bedSelect.innerHTML = '<option value="">Select bed...</option>';
return;
}
fetch(`/inpatients/beds/available/?ward_id=${wardId}`)
.then(response => response.json())
.then(data => {
let html = '<option value="">Select bed...</option>';
data.beds.forEach(bed => {
html += `<option value="${bed.id}">${bed.name}</option>`;
});
bedSelect.innerHTML = html;
})
.catch(error => console.error('Error loading beds:', error));
}
function transferPatientConfirm() {
const form = document.getElementById('transferForm');
form.submit();
}
function scheduleCleaning() {
// In a real implementation, this would open a cleaning schedule modal
alert('Cleaning schedule functionality would be implemented here.');
const modal = new bootstrap.Modal(document.getElementById('scheduleCleaningModal'));
modal.show();
}
function scheduleCleaningConfirm() {
const form = document.getElementById('cleaningForm');
form.submit();
}
function scheduleMaintenance() {
// In a real implementation, this would open a maintenance schedule modal
alert('Maintenance schedule functionality would be implemented here.');
const modal = new bootstrap.Modal(document.getElementById('scheduleMaintenanceModal'));
modal.show();
}
function scheduleMaintenanceConfirm() {
const form = document.getElementById('maintenanceForm');
form.submit();
}
function viewBedChart() {
// In a real implementation, this would show utilization charts
alert('Bed utilization charts would be displayed here.');
const modal = new bootstrap.Modal(document.getElementById('bedChartModal'));
modal.show();
// Load chart data
fetch(`/inpatients/beds/{{ object.pk }}/utilization/`)
.then(response => response.json())
.then(data => {
const ctx = document.getElementById('utilizationChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: data.labels,
datasets: [{
label: 'Occupancy Rate (%)',
data: data.data,
borderColor: 'rgb(75, 192, 192)',
tension: 0.1
}]
},
options: {
responsive: true,
scales: {
y: {
beginAtZero: true,
max: 100
}
}
}
});
})
.catch(error => console.error('Error loading chart data:', error));
}
function refreshHistory() {
// In a real implementation, this would refresh the history via AJAX
location.reload();
// HTMX handles this
}
</script>
{% endblock %}

File diff suppressed because it is too large Load Diff

View File

@ -1,380 +1,123 @@
{% extends "base.html" %}
{% load static %}
{% load i18n %}
{% block title %}Delete Discharge Record{% endblock %}
{% block title %}{% trans "Delete Discharge Summary" %}{% endblock %}
{% block content %}
<div class="d-flex align-items-center mb-3">
<div>
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'inpatients:dashboard' %}">Inpatients</a></li>
<li class="breadcrumb-item"><a href="{% url 'inpatients:discharge_list' %}">Discharges</a></li>
<li class="breadcrumb-item"><a href="{% url 'inpatients:discharge_detail' object.pk %}">Discharge #{{ object.pk }}</a></li>
<li class="breadcrumb-item active">Delete</li>
</ol>
<h1 class="page-header mb-0">Delete Discharge Record</h1>
</div>
<div class="ms-auto">
<a href="{% url 'inpatients:discharge_detail' object.pk %}" class="btn btn-secondary">
<i class="fas fa-arrow-left me-2"></i>Back to Discharge
</a>
</div>
</div>
<div class="row justify-content-center">
<div class="col-xl-8">
<div class="card">
<div class="card-header bg-danger text-white">
<h4 class="card-title mb-0">
<i class="fas fa-exclamation-triangle me-2"></i>
Confirm Discharge Record Deletion
</h4>
</div>
<div class="card-body">
<div class="alert alert-warning">
<h5 class="alert-heading">
<i class="fas fa-exclamation-triangle me-2"></i>
Are you sure you want to delete this discharge record?
</h5>
<p class="mb-0">
This action cannot be undone. The discharge record and all associated data will be permanently removed from the system.
</p>
</div>
<!-- BEGIN breadcrumb -->
<ol class="breadcrumb float-xl-end">
<li class="breadcrumb-item"><a href="javascript:;">Home</a></li>
<li class="breadcrumb-item"><a href="javascript:;">Inpatients</a></li>
<li class="breadcrumb-item"><a href="javascript:;">Discharges</a></li>
<li class="breadcrumb-item"><a href="{% url 'inpatients:discharge_summary_list' %}">Discharge Summaries</a></li>
<li class="breadcrumb-item"><a href="{% url 'inpatients:discharge_summary_detail' discharge_summary.id %}">{{ discharge_summary.admission.patient.get_full_name }}</a></li>
<li class="breadcrumb-item active">Delete</li>
</ol>
<!-- END breadcrumb -->
<!-- BEGIN page-header -->
<h1 class="page-header">Delete Discharge Summary <small>{{ discharge_summary.admission.patient.get_full_name }}</small></h1>
<!-- END page-header -->
<!-- Discharge Details -->
<div class="row mb-4">
<div class="col-md-6">
<div class="card bg-light">
<div class="card-body">
<h6 class="card-title">
<i class="fas fa-user-injured me-2"></i>Patient Information
</h6>
<div class="mb-2">
<strong>Patient:</strong> {{ object.admission.patient.get_full_name }}
</div>
<div class="mb-2">
<strong>MRN:</strong> {{ object.admission.patient.medical_record_number }}
</div>
<div class="mb-2">
<strong>DOB:</strong> {{ object.admission.patient.date_of_birth|date:"M d, Y" }}
</div>
<div>
<strong>Age:</strong> {{ object.admission.patient.age }} years
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card bg-light">
<div class="card-body">
<h6 class="card-title">
<i class="fas fa-sign-out-alt me-2"></i>Discharge Information
</h6>
<div class="mb-2">
<strong>Discharge Date:</strong> {{ object.discharge_date|date:"M d, Y g:i A" }}
</div>
<div class="mb-2">
<strong>Discharge Type:</strong> {{ object.get_discharge_type_display }}
</div>
<div class="mb-2">
<strong>Status:</strong>
<span class="badge bg-{% if object.status == 'completed' %}success{% elif object.status == 'pending' %}warning{% else %}info{% endif %}">
{{ object.get_status_display }}
</span>
</div>
<div>
<strong>Discharge ID:</strong> {{ object.pk }}
</div>
</div>
</div>
</div>
</div>
<!-- BEGIN row -->
<div class="row">
<!-- BEGIN col-12 -->
<div class="col-xl-12">
<!-- BEGIN panel -->
<div class="panel panel-inverse" data-sortable-id="delete-discharge-summary">
<div class="panel-heading">
<h4 class="panel-title">
<i class="fa fa-trash-alt me-2"></i>{% trans "Delete Discharge Summary" %}
<span class="badge bg-danger ms-2">
<i class="fa fa-exclamation-triangle me-1"></i>{% trans "Warning" %}
</span>
</h4>
<div class="panel-heading-btn">
<a href="{% url 'inpatients:discharge_summary_detail' discharge_summary.id %}" class="btn btn-xs btn-icon btn-info me-1" title="{% trans 'View' %}">
<i class="fa fa-eye"></i>
</a>
<a href="{% url 'inpatients:discharge_summary_update' discharge_summary.id %}" class="btn btn-xs btn-icon btn-warning me-1" title="{% trans 'Edit' %}">
<i class="fa fa-edit"></i>
</a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>
</div>
</div>
<div class="panel-body">
<!-- Warning Alert -->
<div class="note alert-danger mb-4 p-4">
<h5 class="alert-heading mb-3">
<i class="fa fa-exclamation-triangle me-2"></i>{% trans "Warning: This action cannot be undone!" %}
</h5>
<p class="mb-0">{% trans "Are you sure you want to delete this discharge summary? This will permanently remove all associated data." %}</p>
</div>
<!-- Admission Details -->
<div class="row mb-4">
<div class="col-12">
<div class="card bg-light">
<div class="card-body">
<h6 class="card-title">
<i class="fas fa-hospital me-2"></i>Related Admission Information
</h6>
<div class="row">
<div class="col-md-6">
<div class="mb-2">
<strong>Admission Date:</strong> {{ object.admission.admission_date|date:"M d, Y g:i A" }}
</div>
<div class="mb-2">
<strong>Length of Stay:</strong> {{ object.length_of_stay }} days
</div>
<div>
<strong>Ward:</strong> {{ object.admission.ward.name }}
</div>
</div>
<div class="col-md-6">
<div class="mb-2">
<strong>Bed:</strong> {{ object.admission.bed.bed_number }}
</div>
<div class="mb-2">
<strong>Attending Physician:</strong> {{ object.admission.attending_physician.get_full_name }}
</div>
<div>
<strong>Admission Diagnosis:</strong> {{ object.admission.primary_diagnosis }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Summary Information -->
<div class="row mb-4">
<div class="col-md-8">
<div class="bg-light p-3 rounded">
<h6 class="text-primary mb-3"><i class="fa fa-file-medical me-2"></i>{% trans "Discharge Summary Details" %}</h6>
<div class="row">
<div class="col-md-6">
<p class="mb-2"><i class="fa fa-user me-2"></i><strong>{% trans "Patient" %}:</strong> {{ discharge_summary.admission.patient.get_full_name }}</p>
<p class="mb-2"><i class="fa fa-id-card me-2"></i><strong>{% trans "MRN" %}:</strong> {{ discharge_summary.admission.patient.mrn }}</p>
<p class="mb-0"><i class="fa fa-calendar-plus me-2"></i><strong>{% trans "Admission Date" %}:</strong> {{ discharge_summary.admission.admission_datetime|date:"M d, Y g:i A" }}</p>
</div>
<div class="col-md-6">
<p class="mb-2"><i class="fa fa-calendar-minus me-2"></i><strong>{% trans "Discharge Date" %}:</strong> {{ discharge_summary.discharge_date|date:"M d, Y" }} {{ discharge_summary.discharge_time|time:"g:i A" }}</p>
<p class="mb-2"><i class="fa fa-user-md me-2"></i><strong>{% trans "Physician" %}:</strong> {{ discharge_summary.discharging_physician.get_full_name }}</p>
<p class="mb-0"><i class="fa fa-clock me-2"></i><strong>{% trans "Length of Stay" %}:</strong> {{ discharge_summary.length_of_stay }} {% trans "days" %}</p>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="bg-light p-3 rounded h-100">
<h6 class="text-info mb-3"><i class="fa fa-info-circle me-2"></i>{% trans "Status" %}</h6>
{% if discharge_summary.summary_completed %}
<span class="badge bg-success d-block mb-2">
<i class="fa fa-check me-1"></i>{% trans "Summary Completed" %}
</span>
{% if discharge_summary.summary_signed %}
<span class="badge bg-info d-block mb-2">
<i class="fa fa-signature me-1"></i>{% trans "Summary Signed" %}
</span>
{% endif %}
{% else %}
<span class="badge bg-warning d-block mb-2">
<i class="fa fa-clock me-1"></i>{% trans "Incomplete" %}
</span>
{% endif %}
{% if discharge_summary.patient_copy_provided %}
<span class="badge bg-primary d-block">
<i class="fa fa-copy me-1"></i>{% trans "Patient Copy Provided" %}
</span>
{% endif %}
</div>
</div>
</div>
{% if object.discharge_summary %}
<div class="row mb-4">
<div class="col-12">
<div class="card bg-light">
<div class="card-body">
<h6 class="card-title">
<i class="fas fa-file-medical me-2"></i>Discharge Summary
</h6>
<div class="alert alert-info mb-0">
{{ object.discharge_summary|truncatewords:50 }}
{% if object.discharge_summary|wordcount > 50 %}
<div class="mt-2">
<small class="text-muted">Summary truncated for display...</small>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endif %}
<!-- Confirmation Form -->
<div class="text-center">
<p class="text-muted mb-4">{% trans "Please confirm that you want to permanently delete this discharge summary." %}</p>
{% if object.discharge_medications.exists %}
<div class="row mb-4">
<div class="col-12">
<div class="card bg-light">
<div class="card-body">
<h6 class="card-title">
<i class="fas fa-pills me-2"></i>Discharge Medications
</h6>
<div class="row">
{% for medication in object.discharge_medications.all|slice:":6" %}
<div class="col-md-6 mb-2">
<div class="d-flex align-items-center">
<i class="fas fa-pill text-primary me-2"></i>
<div>
<strong>{{ medication.medication.name }}</strong>
<div class="small text-muted">{{ medication.dosage }} - {{ medication.frequency }}</div>
</div>
</div>
</div>
{% endfor %}
{% if object.discharge_medications.count > 6 %}
<div class="col-12">
<small class="text-muted">And {{ object.discharge_medications.count|add:"-6" }} more medications...</small>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endif %}
<!-- Deletion Form -->
<form method="post">
{% csrf_token %}
<div class="mb-3">
<label for="deletion_reason" class="form-label">
<strong>Reason for Deletion *</strong>
</label>
<select class="form-select" id="deletion_reason" name="deletion_reason" required>
<option value="">Select a reason</option>
<option value="data_error">Data Entry Error</option>
<option value="duplicate_record">Duplicate Record</option>
<option value="patient_request">Patient Request</option>
<option value="privacy_compliance">Privacy Compliance</option>
<option value="system_error">System Error</option>
<option value="incorrect_discharge">Incorrect Discharge</option>
<option value="administrative">Administrative Correction</option>
<option value="other">Other</option>
</select>
</div>
<div class="mb-3">
<label for="deletion_notes" class="form-label">
<strong>Additional Notes</strong>
</label>
<textarea class="form-control"
id="deletion_notes"
name="deletion_notes"
rows="3"
placeholder="Provide additional details about why this discharge record is being deleted..."></textarea>
<div class="form-text">
These notes will be recorded for audit purposes and compliance.
</div>
</div>
<div class="form-check mb-3">
<input class="form-check-input"
type="checkbox"
id="confirm_deletion"
name="confirm_deletion"
required>
<label class="form-check-label" for="confirm_deletion">
I understand that this action cannot be undone and confirm the deletion of this discharge record.
</label>
</div>
<div class="form-check mb-3">
<input class="form-check-input"
type="checkbox"
id="notify_stakeholders"
name="notify_stakeholders">
<label class="form-check-label" for="notify_stakeholders">
Notify relevant stakeholders (attending physician, nursing staff, billing department) about this deletion.
</label>
</div>
<div class="alert alert-info">
<h6 class="alert-heading">
<i class="fas fa-info-circle me-2"></i>What happens when you delete this discharge record?
</h6>
<ul class="mb-0">
<li>The discharge record will be permanently removed from the system</li>
<li>The associated admission will be marked as "active" again</li>
<li>The patient's bed will be marked as occupied</li>
<li>Discharge medications and instructions will be deleted</li>
<li>Billing records may be affected and require manual adjustment</li>
<li>This action will be logged in the audit trail</li>
<li>Follow-up appointments may need to be rescheduled</li>
<li>Insurance claims may need to be updated</li>
</ul>
</div>
<div class="d-flex justify-content-between">
<a href="{% url 'inpatients:discharge_detail' object.pk %}" class="btn btn-secondary">
<i class="fas fa-times me-2"></i>Cancel
</a>
<button type="submit" class="btn btn-danger" onclick="return confirmDeletion()">
<i class="fas fa-trash me-2"></i>Delete Discharge Record
</button>
</div>
</form>
</div>
</div>
<!-- Impact Warning -->
{% if object.status == 'completed' %}
<div class="card mt-4">
<div class="card-header bg-warning text-dark">
<h5 class="card-title mb-0">
<i class="fas fa-exclamation-triangle me-2"></i>
Important Considerations
</h5>
</div>
<div class="card-body">
<div class="alert alert-warning">
<strong>Completed Discharge:</strong> This discharge has been completed. Deleting it may affect:
<ul class="mb-0 mt-2">
<li>Billing and insurance claims that have already been processed</li>
<li>Quality metrics and hospital statistics</li>
<li>Regulatory reporting requirements</li>
<li>Patient care continuity and follow-up schedules</li>
</ul>
</div>
{% if object.follow_up_appointments.exists %}
<div class="alert alert-info">
<strong>Follow-up Appointments:</strong> This discharge has {{ object.follow_up_appointments.count }} associated follow-up appointment{{ object.follow_up_appointments.count|pluralize }}.
These may need to be rescheduled or cancelled.
</div>
{% endif %}
</div>
</div>
{% endif %}
<!-- Related Information -->
<div class="card mt-4">
<div class="card-header">
<h5 class="card-title">
<i class="fas fa-link me-2"></i>
Related Information
</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<h6>Discharge Details</h6>
<ul class="list-unstyled">
<li><strong>Discharge ID:</strong> {{ object.pk }}</li>
<li><strong>Created:</strong> {{ object.created_at|date:"M d, Y g:i A" }}</li>
<li><strong>Last Updated:</strong> {{ object.updated_at|date:"M d, Y g:i A" }}</li>
<li><strong>Created By:</strong> {{ object.created_by.get_full_name|default:"System" }}</li>
</ul>
</div>
<div class="col-md-6">
<h6>System Information</h6>
<ul class="list-unstyled">
<li><strong>Admission ID:</strong> {{ object.admission.pk }}</li>
<li><strong>Patient ID:</strong> {{ object.admission.patient.pk }}</li>
{% if object.discharge_medications.exists %}
<li><strong>Medications:</strong> {{ object.discharge_medications.count }} prescribed</li>
{% endif %}
{% if object.follow_up_appointments.exists %}
<li><strong>Follow-ups:</strong> {{ object.follow_up_appointments.count }} scheduled</li>
{% endif %}
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function confirmDeletion() {
const reason = document.getElementById('deletion_reason').value;
const confirmed = document.getElementById('confirm_deletion').checked;
if (!reason) {
alert('Please select a reason for deletion.');
return false;
}
if (!confirmed) {
alert('Please confirm that you understand this action cannot be undone.');
return false;
}
const dischargeId = "{{ object.pk }}";
const patientName = "{{ object.admission.patient.get_full_name }}";
const dischargeDate = "{{ object.discharge_date|date:'M d, Y' }}";
const message = `Are you absolutely sure you want to delete this discharge record?\n\nPatient: ${patientName}\nDischarge Date: ${dischargeDate}\nDischarge ID: ${dischargeId}\n\nThis action cannot be undone and may affect billing, statistics, and patient care continuity.`;
return confirm(message);
}
document.addEventListener('DOMContentLoaded', function() {
// Auto-focus on deletion reason
document.getElementById('deletion_reason').focus();
// Show/hide additional notes based on reason
const reasonSelect = document.getElementById('deletion_reason');
const notesTextarea = document.getElementById('deletion_notes');
reasonSelect.addEventListener('change', function() {
if (this.value === 'other') {
notesTextarea.required = true;
notesTextarea.placeholder = 'Please specify the reason for deletion...';
} else {
notesTextarea.required = false;
notesTextarea.placeholder = 'Provide additional details about why this discharge record is being deleted...';
}
});
});
</script>
<form method="post" class="d-inline">
{% csrf_token %}
<button type="submit" class="btn btn-danger btn-lg me-3">
<i class="fa fa-trash-alt me-2"></i>{% trans "Yes, Delete Discharge Summary" %}
</button>
<a href="{% url 'inpatients:discharge_summary_detail' discharge_summary.id %}" class="btn btn-outline-secondary btn-lg">
<i class="fa fa-times me-2"></i>{% trans "Cancel" %}
</a>
</form>
</div>
</div>
</div>
<!-- END panel -->
</div>
<!-- END col-12 -->
</div>
<!-- END row -->
{% endblock %}

View File

@ -1,454 +1,458 @@
{% extends "base.html" %}
{% load static %}
{% load i18n %}
{% block title %}{{ object|yesno:"Edit,Create" }} Discharge - Inpatients{% endblock %}
{% block css %}
<link href="{% static 'assets/plugins/select2/dist/css/select2.min.css' %}" rel="stylesheet" />
<link href="{% static 'assets/plugins/bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css' %}" rel="stylesheet" />
<link href="{% static 'assets/plugins/bootstrap-timepicker/css/bootstrap-timepicker.min.css' %}" rel="stylesheet" />
<link href="{% static 'assets/plugins/summernote/dist/summernote-lite.css' %}" rel="stylesheet" />
{% endblock %}
{% block title %}{% if form.instance.pk %}{% trans "Edit Discharge Summary" %}{% else %}{% trans "Create Discharge Summary" %}{% endif %}{% endblock %}
{% block content %}
<!-- BEGIN breadcrumb -->
<ol class="breadcrumb float-xl-end">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{% url 'inpatients:dashboard' %}">Inpatients</a></li>
<li class="breadcrumb-item"><a href="{% url 'inpatients:discharge_list' %}">Discharges</a></li>
<li class="breadcrumb-item active">{{ object|yesno:"Edit,Create" }} Discharge</li>
</ol>
<!-- END breadcrumb -->
<!-- BEGIN page-header -->
<h1 class="page-header">{{ object|yesno:"Edit,Create" }} Patient Discharge</h1>
<!-- END page-header -->
<!-- BEGIN breadcrumb -->
<ol class="breadcrumb float-xl-end">
<li class="breadcrumb-item"><a href="javascript:;">Home</a></li>
<li class="breadcrumb-item"><a href="javascript:;">Inpatients</a></li>
<li class="breadcrumb-item"><a href="javascript:;">Discharges</a></li>
<li class="breadcrumb-item"><a href="{% url 'inpatients:discharge_summary_list' %}">Discharge Summaries</a></li>
<li class="breadcrumb-item active">{% if form.instance.pk %}Edit{% else %}Create{% endif %}</li>
</ol>
<!-- END breadcrumb -->
<!-- BEGIN page-header -->
<h1 class="page-header">{% if form.instance.pk %}Edit{% else %}Create{% endif %} Discharge Summary <small>{% if form.instance.pk %}{{ form.instance.admission.patient.get_full_name }}{% else %}New Summary{% endif %}</small></h1>
<!-- END page-header -->
<div class="row">
<div class="col-xl-8">
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Discharge Information</h4>
<div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
</div>
</div>
<div class="panel-body">
<form method="post" id="discharge-form">
{% csrf_token %}
<!-- BEGIN row -->
<div class="row">
<!-- BEGIN col-12 -->
<div class="col-xl-12">
<!-- BEGIN panel -->
<div class="panel panel-inverse" data-sortable-id="discharge-form">
<div class="panel-heading">
<h4 class="panel-title">
<i class="fa fa-file-medical me-2"></i>{% if form.instance.pk %}{% trans "Edit Discharge Summary" %}{% else %}{% trans "Create Discharge Summary" %}{% endif %}
{% if form.instance.pk %}
{% if form.instance.summary_completed %}
<span class="badge bg-success ms-2">
<i class="fa fa-check me-1"></i>{% trans "Completed" %}
</span>
{% else %}
<span class="badge bg-warning ms-2">
<i class="fa fa-clock me-1"></i>{% trans "Incomplete" %}
</span>
{% endif %}
{% else %}
<span class="badge bg-primary ms-2">
<i class="fa fa-plus me-1"></i>{% trans "New" %}
</span>
{% endif %}
</h4>
<div class="panel-heading-btn">
{% if form.instance.pk %}
<a href="{% url 'inpatients:discharge_summary_detail' form.instance.pk %}" class="btn btn-xs btn-icon btn-info me-1" title="{% trans 'View' %}">
<i class="fa fa-eye"></i>
</a>
<a href="{% url 'inpatients:discharge_summary_delete' form.instance.pk %}" class="btn btn-xs btn-icon btn-danger me-1" title="{% trans 'Delete' %}">
<i class="fa fa-trash"></i>
</a>
{% endif %}
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>
</div>
</div>
<div class="panel-body">
<form method="post">
{% csrf_token %}
<!-- Patient and Admission Information -->
<div class="row mb-3">
<div class="col-md-6">
<label class="form-label" for="{{ form.admission.id_for_label }}">Admission <span class="text-danger">*</span></label>
{{ form.admission }}
{% if form.admission.errors %}
<div class="invalid-feedback d-block">{{ form.admission.errors.0 }}</div>
{% endif %}
<div class="form-text">Select the admission to discharge</div>
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.discharge_type.id_for_label }}">Discharge Type <span class="text-danger">*</span></label>
{{ form.discharge_type }}
{% if form.discharge_type.errors %}
<div class="invalid-feedback d-block">{{ form.discharge_type.errors.0 }}</div>
{% endif %}
</div>
</div>
<!-- Basic Information Section -->
<div class="d-flex align-items-center mb-3">
<i class="fa fa-info-circle fa-2x text-primary me-3"></i>
<div>
<h5 class="mb-1">{% trans "Basic Information" %}</h5>
<small class="text-muted">Admission and discharge details</small>
</div>
</div>
<!-- Discharge Date and Time -->
<div class="row mb-3">
<div class="col-md-4">
<label class="form-label" for="{{ form.discharge_date.id_for_label }}">Discharge Date <span class="text-danger">*</span></label>
{{ form.discharge_date }}
{% if form.discharge_date.errors %}
<div class="invalid-feedback d-block">{{ form.discharge_date.errors.0 }}</div>
{% endif %}
</div>
<div class="col-md-4">
<label class="form-label" for="{{ form.discharge_time.id_for_label }}">Discharge Time <span class="text-danger">*</span></label>
{{ form.discharge_time }}
{% if form.discharge_time.errors %}
<div class="invalid-feedback d-block">{{ form.discharge_time.errors.0 }}</div>
{% endif %}
</div>
<div class="col-md-4">
<label class="form-label" for="{{ form.discharge_status.id_for_label }}">Status</label>
{{ form.discharge_status }}
{% if form.discharge_status.errors %}
<div class="invalid-feedback d-block">{{ form.discharge_status.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="row mb-4">
<div class="col-md-6">
<div class="bg-light p-3 rounded">
<h6 class="text-primary mb-3"><i class="fa fa-hospital-user me-2"></i>{% trans "Admission Details" %}</h6>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Admission" %}</label>
{{ form.admission }}
{% if form.admission.errors %}
<div class="invalid-feedback d-block">{{ form.admission.errors }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Discharging Physician" %}</label>
{{ form.discharging_physician }}
{% if form.discharging_physician.errors %}
<div class="invalid-feedback d-block">{{ form.discharging_physician.errors }}</div>
{% endif %}
</div>
</div>
</div>
<div class="col-md-6">
<div class="bg-light p-3 rounded">
<h6 class="text-success mb-3"><i class="fa fa-calendar-check me-2"></i>{% trans "Discharge Details" %}</h6>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Discharge Date" %}</label>
{{ form.discharge_date }}
{% if form.discharge_date.errors %}
<div class="invalid-feedback d-block">{{ form.discharge_date.errors }}</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Discharge Time" %}</label>
{{ form.discharge_time }}
{% if form.discharge_time.errors %}
<div class="invalid-feedback d-block">{{ form.discharge_time.errors }}</div>
{% endif %}
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Length of Stay (days)" %}</label>
{{ form.length_of_stay }}
{% if form.length_of_stay.errors %}
<div class="invalid-feedback d-block">{{ form.length_of_stay.errors }}</div>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Discharge Destination -->
<div class="row mb-3">
<div class="col-md-6">
<label class="form-label" for="{{ form.discharge_destination.id_for_label }}">Discharge Destination</label>
{{ form.discharge_destination }}
{% if form.discharge_destination.errors %}
<div class="invalid-feedback d-block">{{ form.discharge_destination.errors.0 }}</div>
{% endif %}
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.attending_physician.id_for_label }}">Attending Physician</label>
{{ form.attending_physician }}
{% if form.attending_physician.errors %}
<div class="invalid-feedback d-block">{{ form.attending_physician.errors.0 }}</div>
{% endif %}
</div>
</div>
<!-- Status Section -->
<div class="d-flex align-items-center mb-3">
<i class="fa fa-tasks fa-2x text-warning me-3"></i>
<div>
<h5 class="mb-1">{% trans "Status & Documentation" %}</h5>
<small class="text-muted">Completion status and documentation</small>
</div>
</div>
<!-- Clinical Information -->
<h5 class="mb-3 mt-4">Clinical Information</h5>
<div class="row mb-3">
<div class="col-md-6">
<label class="form-label" for="{{ form.primary_diagnosis.id_for_label }}">Primary Diagnosis</label>
{{ form.primary_diagnosis }}
{% if form.primary_diagnosis.errors %}
<div class="invalid-feedback d-block">{{ form.primary_diagnosis.errors.0 }}</div>
{% endif %}
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.secondary_diagnoses.id_for_label }}">Secondary Diagnoses</label>
{{ form.secondary_diagnoses }}
{% if form.secondary_diagnoses.errors %}
<div class="invalid-feedback d-block">{{ form.secondary_diagnoses.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="row mb-4">
<div class="col-md-4">
<div class="form-check mb-3">
{{ form.summary_completed }}
<label class="form-check-label fw-bold">
<i class="fa fa-check-circle text-success me-2"></i>{% trans "Summary Completed" %}
</label>
</div>
</div>
<div class="col-md-4">
<div class="form-check mb-3">
{{ form.summary_signed }}
<label class="form-check-label fw-bold">
<i class="fa fa-signature text-info me-2"></i>{% trans "Summary Signed" %}
</label>
</div>
</div>
<div class="col-md-4">
<div class="form-check mb-3">
{{ form.patient_copy_provided }}
<label class="form-check-label fw-bold">
<i class="fa fa-copy text-primary me-2"></i>{% trans "Patient Copy Provided" %}
</label>
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label" for="{{ form.discharge_summary.id_for_label }}">Discharge Summary</label>
{{ form.discharge_summary }}
{% if form.discharge_summary.errors %}
<div class="invalid-feedback d-block">{{ form.discharge_summary.errors.0 }}</div>
{% endif %}
<div class="form-text">Comprehensive summary of the patient's stay and treatment</div>
</div>
<hr>
<!-- Medications and Instructions -->
<h5 class="mb-3 mt-4">Discharge Instructions</h5>
<div class="mb-3">
<label class="form-label" for="{{ form.discharge_medications.id_for_label }}">Discharge Medications</label>
{{ form.discharge_medications }}
{% if form.discharge_medications.errors %}
<div class="invalid-feedback d-block">{{ form.discharge_medications.errors.0 }}</div>
{% endif %}
<div class="form-text">List all medications the patient should continue at home</div>
</div>
<!-- Clinical Summary Section -->
<div class="d-flex align-items-center mb-3">
<i class="fa fa-clipboard-list fa-2x text-info me-3"></i>
<div>
<h5 class="mb-1">{% trans "Clinical Summary" %}</h5>
<small class="text-muted">Medical diagnosis and hospital course details</small>
</div>
</div>
<div class="mb-3">
<label class="form-label" for="{{ form.discharge_instructions.id_for_label }}">Patient Instructions</label>
{{ form.discharge_instructions }}
{% if form.discharge_instructions.errors %}
<div class="invalid-feedback d-block">{{ form.discharge_instructions.errors.0 }}</div>
{% endif %}
<div class="form-text">Detailed instructions for patient care at home</div>
</div>
<div class="row mb-4">
<div class="col-md-6">
<div class="bg-light p-3 rounded">
<h6 class="text-primary mb-3"><i class="fa fa-diagnoses me-2"></i>{% trans "Diagnoses" %}</h6>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Admission Diagnosis" %}</label>
{{ form.admission_diagnosis }}
{% if form.admission_diagnosis.errors %}
<div class="invalid-feedback d-block">{{ form.admission_diagnosis.errors }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Final Diagnosis" %}</label>
{{ form.final_diagnosis }}
{% if form.final_diagnosis.errors %}
<div class="invalid-feedback d-block">{{ form.final_diagnosis.errors }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Secondary Diagnoses (JSON list)" %}</label>
{{ form.secondary_diagnoses }}
{% if form.secondary_diagnoses.errors %}
<div class="invalid-feedback d-block">{{ form.secondary_diagnoses.errors }}</div>
{% endif %}
</div>
</div>
</div>
<div class="col-md-6">
<div class="bg-light p-3 rounded">
<h6 class="text-success mb-3"><i class="fa fa-procedures me-2"></i>{% trans "Procedures & Course" %}</h6>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Procedures Performed (JSON list)" %}</label>
{{ form.procedures_performed }}
{% if form.procedures_performed.errors %}
<div class="invalid-feedback d-block">{{ form.procedures_performed.errors }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Hospital Course" %}</label>
{{ form.hospital_course }}
{% if form.hospital_course.errors %}
<div class="invalid-feedback d-block">{{ form.hospital_course.errors }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Complications" %}</label>
{{ form.complications }}
{% if form.complications.errors %}
<div class="invalid-feedback d-block">{{ form.complications.errors }}</div>
{% endif %}
</div>
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label" for="{{ form.follow_up_instructions.id_for_label }}">Follow-up Instructions</label>
{{ form.follow_up_instructions }}
{% if form.follow_up_instructions.errors %}
<div class="invalid-feedback d-block">{{ form.follow_up_instructions.errors.0 }}</div>
{% endif %}
<div class="form-text">When and where the patient should follow up</div>
</div>
<hr>
<!-- Activity and Diet -->
<h5 class="mb-3 mt-4">Activity and Diet Restrictions</h5>
<div class="row mb-3">
<div class="col-md-6">
<label class="form-label" for="{{ form.activity_restrictions.id_for_label }}">Activity Restrictions</label>
{{ form.activity_restrictions }}
{% if form.activity_restrictions.errors %}
<div class="invalid-feedback d-block">{{ form.activity_restrictions.errors.0 }}</div>
{% endif %}
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.diet_restrictions.id_for_label }}">Diet Restrictions</label>
{{ form.diet_restrictions }}
{% if form.diet_restrictions.errors %}
<div class="invalid-feedback d-block">{{ form.diet_restrictions.errors.0 }}</div>
{% endif %}
</div>
</div>
<!-- Medications and Instructions Section -->
<div class="d-flex align-items-center mb-3">
<i class="fa fa-pills fa-2x text-warning me-3"></i>
<div>
<h5 class="mb-1">{% trans "Medications and Instructions" %}</h5>
<small class="text-muted">Discharge medications and patient care instructions</small>
</div>
</div>
<!-- Additional Information -->
<div class="row mb-3">
<div class="col-md-6">
<div class="form-check">
{{ form.patient_education_provided }}
<label class="form-check-label" for="{{ form.patient_education_provided.id_for_label }}">
Patient education provided
</label>
</div>
</div>
<div class="col-md-6">
<div class="form-check">
{{ form.discharge_planning_completed }}
<label class="form-check-label" for="{{ form.discharge_planning_completed.id_for_label }}">
Discharge planning completed
</label>
</div>
</div>
</div>
<div class="row mb-4">
<div class="col-md-6">
<div class="bg-light p-3 rounded">
<h6 class="text-warning mb-3"><i class="fa fa-prescription-bottle me-2"></i>{% trans "Medications" %}</h6>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Discharge Medications (JSON list)" %}</label>
{{ form.discharge_medications }}
{% if form.discharge_medications.errors %}
<div class="invalid-feedback d-block">{{ form.discharge_medications.errors }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Medication Changes" %}</label>
{{ form.medication_changes }}
{% if form.medication_changes.errors %}
<div class="invalid-feedback d-block">{{ form.medication_changes.errors }}</div>
{% endif %}
</div>
</div>
</div>
<div class="col-md-6">
<div class="bg-light p-3 rounded">
<h6 class="text-success mb-3"><i class="fa fa-clipboard-check me-2"></i>{% trans "Patient Instructions" %}</h6>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Activity Restrictions" %}</label>
{{ form.activity_restrictions }}
{% if form.activity_restrictions.errors %}
<div class="invalid-feedback d-block">{{ form.activity_restrictions.errors }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Diet Instructions" %}</label>
{{ form.diet_instructions }}
{% if form.diet_instructions.errors %}
<div class="invalid-feedback d-block">{{ form.diet_instructions.errors }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Wound Care" %}</label>
{{ form.wound_care }}
{% if form.wound_care.errors %}
<div class="invalid-feedback d-block">{{ form.wound_care.errors }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Special Instructions" %}</label>
{{ form.special_instructions }}
{% if form.special_instructions.errors %}
<div class="invalid-feedback d-block">{{ form.special_instructions.errors }}</div>
{% endif %}
</div>
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label" for="{{ form.notes.id_for_label }}">Additional Notes</label>
{{ form.notes }}
{% if form.notes.errors %}
<div class="invalid-feedback d-block">{{ form.notes.errors.0 }}</div>
{% endif %}
</div>
<hr>
<!-- Form Actions -->
<div class="d-flex justify-content-between">
<a href="{% url 'inpatients:discharge_list' %}" class="btn btn-default">
<i class="fa fa-arrow-left me-2"></i>Cancel
</a>
<div>
<button type="submit" name="action" value="save_draft" class="btn btn-warning me-2">
<i class="fa fa-save me-2"></i>Save as Draft
</button>
<button type="submit" name="action" value="save" class="btn btn-success">
<i class="fa fa-check me-2"></i>{{ object|yesno:"Update,Complete" }} Discharge
</button>
</div>
</div>
</form>
</div>
</div>
<!-- END panel -->
</div>
<!-- Follow-up and Disposition Section -->
<div class="d-flex align-items-center mb-3">
<i class="fa fa-calendar-check fa-2x text-primary me-3"></i>
<div>
<h5 class="mb-1">{% trans "Follow-up and Disposition" %}</h5>
<small class="text-muted">Post-discharge care and discharge destination</small>
</div>
</div>
<div class="col-xl-4">
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Discharge Guidelines</h4>
<div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
</div>
</div>
<div class="panel-body">
<div class="alert alert-info">
<h6><i class="fa fa-info-circle me-2"></i>Discharge Checklist</h6>
<ul class="mb-0">
<li>Patient is medically stable for discharge</li>
<li>All necessary medications prescribed</li>
<li>Follow-up appointments scheduled</li>
<li>Patient/family education completed</li>
<li>Transportation arranged</li>
<li>Discharge summary completed</li>
</ul>
</div>
<div class="row mb-4">
<div class="col-md-6">
<div class="bg-light p-3 rounded">
<h6 class="text-primary mb-3"><i class="fa fa-calendar-plus me-2"></i>{% trans "Follow-up Care" %}</h6>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Follow-up Instructions" %}</label>
{{ form.follow_up_instructions }}
{% if form.follow_up_instructions.errors %}
<div class="invalid-feedback d-block">{{ form.follow_up_instructions.errors }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Follow-up Appointments (JSON list)" %}</label>
{{ form.follow_up_appointments }}
{% if form.follow_up_appointments.errors %}
<div class="invalid-feedback d-block">{{ form.follow_up_appointments.errors }}</div>
{% endif %}
</div>
</div>
</div>
<div class="col-md-6">
<div class="bg-light p-3 rounded">
<h6 class="text-danger mb-3"><i class="fa fa-exclamation-triangle me-2"></i>{% trans "Warning Signs" %}</h6>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Warning Signs" %}</label>
{{ form.warning_signs }}
{% if form.warning_signs.errors %}
<div class="invalid-feedback d-block">{{ form.warning_signs.errors }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "When to Call" %}</label>
{{ form.when_to_call }}
{% if form.when_to_call.errors %}
<div class="invalid-feedback d-block">{{ form.when_to_call.errors }}</div>
{% endif %}
</div>
</div>
</div>
</div>
<div class="alert alert-warning">
<h6><i class="fa fa-exclamation-triangle me-2"></i>Required Documentation</h6>
<ul class="mb-0">
<li>Discharge summary with diagnoses</li>
<li>Medication reconciliation</li>
<li>Patient instruction sheet</li>
<li>Follow-up appointment details</li>
<li>Emergency contact information</li>
</ul>
</div>
<div class="row mb-4">
<div class="col-md-6">
<div class="bg-light p-3 rounded">
<h6 class="text-secondary mb-3"><i class="fa fa-sign-out-alt me-2"></i>{% trans "Discharge Disposition" %}</h6>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Discharge Disposition" %}</label>
{{ form.discharge_disposition }}
{% if form.discharge_disposition.errors %}
<div class="invalid-feedback d-block">{{ form.discharge_disposition.errors }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Discharge Location" %}</label>
{{ form.discharge_location }}
{% if form.discharge_location.errors %}
<div class="invalid-feedback d-block">{{ form.discharge_location.errors }}</div>
{% endif %}
</div>
</div>
</div>
<div class="col-md-6">
<div class="bg-light p-3 rounded">
<h6 class="text-info mb-3"><i class="fa fa-box-open me-2"></i>{% trans "Equipment & Supplies" %}</h6>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Durable Medical Equipment (JSON list)" %}</label>
{{ form.durable_medical_equipment }}
{% if form.durable_medical_equipment.errors %}
<div class="invalid-feedback d-block">{{ form.durable_medical_equipment.errors }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Supplies Provided (JSON list)" %}</label>
{{ form.supplies_provided }}
{% if form.supplies_provided.errors %}
<div class="invalid-feedback d-block">{{ form.supplies_provided.errors }}</div>
{% endif %}
</div>
</div>
</div>
</div>
<div class="alert alert-success">
<h6><i class="fa fa-check-circle me-2"></i>Discharge Types</h6>
<ul class="mb-0">
<li><strong>Home:</strong> Patient returns to home environment</li>
<li><strong>Transfer:</strong> Transfer to another facility</li>
<li><strong>AMA:</strong> Against medical advice</li>
<li><strong>Expired:</strong> Patient deceased during stay</li>
</ul>
</div>
<hr>
{% if object and object.admission %}
<div class="alert alert-secondary">
<h6><i class="fa fa-user me-2"></i>Patient Information</h6>
<ul class="mb-0">
<li><strong>Patient:</strong> {{ object.admission.patient.get_full_name }}</li>
<li><strong>MRN:</strong> {{ object.admission.patient.medical_record_number }}</li>
<li><strong>Admission Date:</strong> {{ object.admission.admission_date|date:"M d, Y" }}</li>
<li><strong>Length of Stay:</strong> {{ object.admission.get_length_of_stay }} days</li>
</ul>
</div>
{% endif %}
</div>
</div>
<!-- END panel -->
<!-- Additional Information Section -->
<div class="d-flex align-items-center mb-3">
<i class="fa fa-chart-bar fa-2x text-dark me-3"></i>
<div>
<h5 class="mb-1">{% trans "Additional Information" %}</h5>
<small class="text-muted">Patient education and assessment data</small>
</div>
</div>
{% if object and object.admission %}
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Admission Summary</h4>
<div class="panel-heading-btn">
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
</div>
</div>
<div class="panel-body">
<div class="small">
<div class="mb-2">
<strong>Admission Reason:</strong><br>
{{ object.admission.admission_reason|default:"Not specified" }}
</div>
<div class="row mb-4">
<div class="col-md-6">
<div class="bg-light p-3 rounded">
<h6 class="text-success mb-3"><i class="fa fa-graduation-cap me-2"></i>{% trans "Patient Education" %}</h6>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Education Provided (JSON list)" %}</label>
{{ form.education_provided }}
{% if form.education_provided.errors %}
<div class="invalid-feedback d-block">{{ form.education_provided.errors }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Patient Understanding" %}</label>
{{ form.patient_understanding }}
{% if form.patient_understanding.errors %}
<div class="invalid-feedback d-block">{{ form.patient_understanding.errors }}</div>
{% endif %}
</div>
</div>
</div>
<div class="col-md-6">
<div class="bg-light p-3 rounded">
<h6 class="text-warning mb-3"><i class="fa fa-chart-line me-2"></i>{% trans "Assessment & Satisfaction" %}</h6>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Readmission Risk" %}</label>
{{ form.readmission_risk }}
{% if form.readmission_risk.errors %}
<div class="invalid-feedback d-block">{{ form.readmission_risk.errors }}</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label fw-bold">{% trans "Patient Satisfaction (1-10)" %}</label>
{{ form.patient_satisfaction }}
{% if form.patient_satisfaction.errors %}
<div class="invalid-feedback d-block">{{ form.patient_satisfaction.errors }}</div>
{% endif %}
</div>
</div>
</div>
</div>
<div class="mb-2">
<strong>Attending Physician:</strong><br>
{{ object.admission.attending_physician.get_full_name|default:"Not assigned" }}
</div>
<hr>
<div class="mb-2">
<strong>Current Bed:</strong><br>
{{ object.admission.bed|default:"Not assigned" }}
</div>
<div class="mb-2">
<strong>Admission Type:</strong><br>
{{ object.admission.get_admission_type_display }}
</div>
<div class="mb-2">
<strong>Insurance:</strong><br>
{{ object.admission.insurance_information|default:"Not provided" }}
</div>
<!-- Form Actions -->
<div class="d-flex justify-content-end gap-2">
<button type="submit" class="btn btn-success btn-lg">
<i class="fa fa-save me-2"></i>{% trans "Save Discharge Summary" %}
</button>
<a href="{% url 'inpatients:discharge_summary_list' %}" class="btn btn-outline-secondary btn-lg">
<i class="fa fa-times me-2"></i>{% trans "Cancel" %}
</a>
</div>
</form>
</div>
</div>
</div>
<!-- END panel -->
{% endif %}
</div>
</div>
{% endblock %}
{% block js %}
<script src="{% static 'assets/plugins/select2/dist/js/select2.min.js' %}"></script>
<script src="{% static 'assets/plugins/bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js' %}"></script>
<script src="{% static 'assets/plugins/bootstrap-timepicker/js/bootstrap-timepicker.min.js' %}"></script>
<script src="{% static 'assets/plugins/summernote/dist/summernote-lite.min.js' %}"></script>
<script>
$(document).ready(function() {
// Initialize Select2
$('.select2').select2({
theme: 'bootstrap-5',
width: '100%'
});
// Initialize date picker
$('input[type="date"]').datepicker({
format: 'yyyy-mm-dd',
autoclose: true,
todayHighlight: true,
endDate: new Date()
});
// Initialize time picker
$('input[type="time"]').timepicker({
showMeridian: false,
defaultTime: 'current'
});
// Initialize Summernote
$('.summernote').summernote({
height: 150,
toolbar: [
['style', ['style']],
['font', ['bold', 'italic', 'underline', 'clear']],
['para', ['ul', 'ol', 'paragraph']],
['insert', ['link']],
['view', ['fullscreen', 'codeview']]
]
});
// Form validation
$('#discharge-form').on('submit', function(e) {
var isValid = true;
var requiredFields = ['admission', 'discharge_type', 'discharge_date', 'discharge_time'];
requiredFields.forEach(function(field) {
var input = $('[name="' + field + '"]');
if (!input.val()) {
input.addClass('is-invalid');
isValid = false;
} else {
input.removeClass('is-invalid');
}
});
if (!isValid) {
e.preventDefault();
toastr.error('Please fill in all required fields.');
}
});
// Real-time validation
$('input, select, textarea').on('change blur', function() {
if ($(this).val()) {
$(this).removeClass('is-invalid');
}
});
// Load admission details when admission is selected
$('select[name="admission"]').on('change', function() {
var admissionId = $(this).val();
if (admissionId) {
$.ajax({
url: '{% url "inpatients:admission_detail_api" 0 %}'.replace('0', admissionId),
success: function(data) {
// Pre-fill attending physician if available
if (data.attending_physician) {
$('select[name="attending_physician"]').val(data.attending_physician).trigger('change');
}
// Show admission information
toastr.info('Admission details loaded: ' + data.patient_name);
},
error: function() {
toastr.warning('Could not load admission details');
}
});
}
});
// Auto-populate current date and time
if (!$('input[name="discharge_date"]').val()) {
$('input[name="discharge_date"]').val(new Date().toISOString().split('T')[0]);
}
if (!$('input[name="discharge_time"]').val()) {
var now = new Date();
var time = now.getHours().toString().padStart(2, '0') + ':' +
now.getMinutes().toString().padStart(2, '0');
$('input[name="discharge_time"]').val(time);
}
// Discharge type change handler
$('select[name="discharge_type"]').on('change', function() {
var dischargeType = $(this).val();
// Show/hide relevant fields based on discharge type
if (dischargeType === 'transfer') {
$('input[name="discharge_destination"]').closest('.col-md-6').show();
$('input[name="discharge_destination"]').attr('required', true);
} else if (dischargeType === 'ama') {
// Show warning for AMA discharge
if (!$('.ama-warning').length) {
$('<div class="alert alert-warning ama-warning mt-2">' +
'<strong>Against Medical Advice:</strong> Ensure proper documentation and patient acknowledgment.' +
'</div>').insertAfter($(this).closest('.col-md-6'));
}
} else {
$('.ama-warning').remove();
}
});
});
</script>
{% endblock %}

View File

@ -0,0 +1,160 @@
{% extends "base.html" %}
{% load i18n %}
{% block title %}{% trans "Discharge Summaries" %}{% endblock %}
{% block content %}
<!-- BEGIN breadcrumb -->
<ol class="breadcrumb float-xl-end">
<li class="breadcrumb-item"><a href="javascript:;">Home</a></li>
<li class="breadcrumb-item"><a href="javascript:;">Inpatients</a></li>
<li class="breadcrumb-item"><a href="javascript:;">Discharges</a></li>
<li class="breadcrumb-item active">Discharge Summaries</li>
</ol>
<!-- END breadcrumb -->
<!-- BEGIN page-header -->
<h1 class="page-header">Discharge Summaries <small>List of all discharge summaries</small></h1>
<!-- END page-header -->
<!-- BEGIN row -->
<div class="row">
<!-- BEGIN col-12 -->
<div class="col-xl-12">
<!-- BEGIN panel -->
<div class="panel panel-inverse" data-sortable-id="discharge-summaries">
<div class="panel-heading">
<h4 class="panel-title">Discharge Summaries</h4>
<div class="panel-heading-btn">
<a href="{% url 'inpatients:discharge_summary_create' %}" class="btn btn-xs btn-icon btn-success me-1" title="Create New">
<i class="fa fa-plus"></i>
</a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-success" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-warning" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-danger" data-toggle="panel-remove"><i class="fa fa-times"></i></a>
</div>
</div>
<div class="panel-body">
<!-- Search and Filters -->
<div class="row mb-3">
<div class="col-md-4">
<div class="input-group">
<input type="text" name="search" class="form-control" placeholder="{% trans 'Search by patient name or diagnosis' %}" value="{{ search_query }}">
<button class="btn btn-outline-secondary" type="button">
<i class="fa fa-search"></i>
</button>
</div>
</div>
<div class="col-md-2">
<select name="completed" class="form-select">
<option value="">{% trans "All Status" %}</option>
<option value="true" {% if completed_filter == 'true' %}selected{% endif %}>{% trans "Completed" %}</option>
<option value="false" {% if completed_filter == 'false' %}selected{% endif %}>{% trans "Incomplete" %}</option>
</select>
</div>
<div class="col-md-3">
<input type="date" name="date_from" class="form-control" value="{{ date_from }}">
</div>
<div class="col-md-3">
<div class="btn-group">
<button type="submit" class="btn btn-primary">
<i class="fa fa-filter me-1"></i>{% trans "Filter" %}
</button>
<a href="{% url 'inpatients:discharge_summary_list' %}" class="btn btn-outline-secondary">
<i class="fa fa-times me-1"></i>{% trans "Clear" %}
</a>
</div>
</div>
</div>
<!-- Table -->
<div class="table-responsive">
<table class="table table-hover table-striped">
<thead class="table-dark">
<tr>
<th>{% trans "Patient" %}</th>
<th>{% trans "Discharge Date" %}</th>
<th>{% trans "Physician" %}</th>
<th>{% trans "Status" %}</th>
<th>{% trans "Actions" %}</th>
</tr>
</thead>
<tbody>
{% for summary in discharge_summaries %}
<tr>
<td>
<div class="d-flex align-items-center">
<div class="me-3">
<i class="fa fa-user fa-2x text-primary"></i>
</div>
<div>
<a href="{% url 'inpatients:discharge_summary_detail' summary.pk %}" class="fw-bold">
{{ summary.admission.patient.get_full_name }}
</a>
<br><small class="text-muted">{{ summary.admission.patient.mrn }}</small>
</div>
</div>
</td>
<td>
<i class="fa fa-calendar me-1"></i>{{ summary.discharge_date|date:"M d, Y" }}
<br><small class="text-muted">{{ summary.discharge_time|time:"g:i A" }}</small>
</td>
<td>
<i class="fa fa-user-md me-1"></i>{{ summary.discharging_physician.get_full_name }}
</td>
<td>
{% if summary.summary_completed %}
<span class="badge bg-success">
<i class="fa fa-check me-1"></i>{% trans "Completed" %}
</span>
{% if summary.summary_signed %}
<br><span class="badge bg-info">
<i class="fa fa-signature me-1"></i>{% trans "Signed" %}
</span>
{% endif %}
{% else %}
<span class="badge bg-warning">
<i class="fa fa-clock me-1"></i>{% trans "Incomplete" %}
</span>
{% endif %}
</td>
<td>
<div class="btn-group">
<a href="{% url 'inpatients:discharge_summary_detail' summary.pk %}" class="btn btn-sm btn-info" title="{% trans 'View' %}">
<i class="fa fa-eye"></i>
</a>
<a href="{% url 'inpatients:discharge_summary_update' summary.pk %}" class="btn btn-sm btn-warning" title="{% trans 'Edit' %}">
<i class="fa fa-edit"></i>
</a>
<a href="{% url 'inpatients:discharge_summary_delete' summary.pk %}" class="btn btn-sm btn-danger" title="{% trans 'Delete' %}">
<i class="fa fa-trash"></i>
</a>
</div>
</td>
</tr>
{% empty %}
<tr>
<td colspan="5" class="text-center py-4">
<i class="fa fa-inbox fa-3x text-muted mb-3"></i>
<h6 class="text-muted">{% trans "No discharge summaries found." %}</h6>
<p class="text-muted">{% trans "Try adjusting your search criteria or create a new discharge summary." %}</p>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Pagination -->
{% if is_paginated %}
{% include 'partial/pagination.html' %}
{% endif %}
</div>
</div>
<!-- END panel -->
</div>
<!-- END col-12 -->
</div>
<!-- END row -->
{% endblock %}

View File

@ -0,0 +1,62 @@
{% if admission_history %}
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Date</th>
<th>Action</th>
<th>Patient</th>
<th>Duration</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
{% for history in admission_history %}
<tr>
<td>
<div>{{ history.admission_datetime|date:"M d, Y" }}</div>
<div class="small text-muted">{{ history.admission_datetime|time:"g:i A" }}</div>
</td>
<td>
<span class="badge bg-{% if history.action == 'ADMISSION' %}success{% elif history.action == 'DISCHARGE' %}info{% elif history.action == 'TRANSFER' %}warning{% else %}secondary{% endif %}">
{{ history.get_action_display }}
</span>
</td>
<td>
{% if history.patient %}
<a href="{% url 'patients:patient_detail' history.patient.pk %}">
{{ history.patient.get_full_name }}
</a>
<div class="small text-muted">{{ history.patient.mrn }}</div>
{% else %}
<span class="text-muted">System action</span>
{% endif %}
</td>
<td>
{% if history.duration %}
{{ history.duration }}
{% else %}
<span class="text-muted">-</span>
{% endif %}
</td>
<td>
{% if history.notes %}
<span class="text-truncate" style="max-width: 200px;" title="{{ history.notes }}">
{{ history.notes }}
</span>
{% else %}
<span class="text-muted">-</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center text-muted py-4">
<i class="fas fa-history fa-3x mb-3"></i>
<h5>No History Available</h5>
<p>No bed history records found for this bed.</p>
</div>
{% endif %}

1224
inpatients/templates/temp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,13 @@ urlpatterns = [
path('discharge/<int:admission_id>/', views.discharge_patient, name='discharge_patient'),
# path('discharge/<int:admission_id>/summary/', views.discharge_summary, name='discharge_summary'),
# Discharge Summaries
path('discharges/', views.DischargeSummaryListView.as_view(), name='discharge_summary_list'),
path('discharges/<int:pk>/', views.DischargeSummaryDetailView.as_view(), name='discharge_summary_detail'),
path('discharges/create/', views.DischargeSummaryCreateView.as_view(), name='discharge_summary_create'),
path('discharges/<int:pk>/edit/', views.DischargeSummaryUpdateView.as_view(), name='discharge_summary_update'),
path('discharges/<int:pk>/delete/', views.DischargeSummaryDeleteView.as_view(), name='discharge_summary_delete'),
path('transfers/', views.TransferManagementView.as_view(), name='transfer_management'),
path('transfer/<int:admission_id>/', views.transfer_patient, name='transfer_patient'),
@ -48,8 +55,11 @@ urlpatterns = [
path('beds/<int:pk>/unblock/', views.unblock_bed, name='unblock_bed'),
path('beds/<int:pk>/maintenance/', views.maintenance_bed, name='maintenance_bed'),
path('beds/grid/', views.bed_grid, name='bed_grid'),
path('beds/status/', views.bed_status_board, name='update_bed_status'),
path('beds/<int:bed_id>/status/', views.update_bed_status, name='update_bed_status'),
path('beds/<int:bed_id>/assign-patient/', views.assign_patient_to_bed, name='assign_patient_to_bed'),
path('beds/<int:bed_id>/utilization/', views.bed_utilization, name='bed_utilization'),
path('beds/<int:bed_id>/details/', views.bed_details, name='bed_details'),
path('beds/<int:bed_id>/refresh-history/', views.refresh_bed_history, name='refresh_bed_history'),
@ -74,4 +84,3 @@ urlpatterns = [
# API endpoints
# path('api/', include('inpatients.api.urls')),
]

View File

@ -9,7 +9,7 @@ from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy, reverse
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.http import JsonResponse, HttpResponse
from django.db.models import Q, Count, Sum, F, ExpressionWrapper, fields
from django.db.models import Q, Count, Sum, F, ExpressionWrapper, fields, DurationField, Avg
from django.utils import timezone
from django.contrib import messages
from django.core.paginator import Paginator
@ -435,6 +435,7 @@ class BedDetailView(LoginRequiredMixin, DetailView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
bed = self.get_object()
tenant = self.request.user.tenant
# Get bed history - admissions that used this bed
context['admission_history'] = Admission.objects.filter(
@ -442,8 +443,28 @@ class BedDetailView(LoginRequiredMixin, DetailView):
'patient', 'admitting_physician',
).order_by('-admission_datetime')
# Get wards for transfer modal
context['wards'] = Ward.objects.filter(
tenant=tenant,
is_active=True
).exclude(pk=bed.ward.pk).order_by('name')
# context['maintenance_history'] = bed.maintenance_history.all().order_by('-scheduled_date')[:10]
# Bed stats
admissions = Admission.objects.filter(current_bed=bed)
total_admissions = admissions.count()
avg_stay_days = 0
if total_admissions > 0:
avg_duration = admissions.aggregate(avg_duration=Avg(ExpressionWrapper(F('discharge_datetime') - F('admission_datetime'), output_field=DurationField())))['avg_duration']
avg_stay_days = avg_duration.total_seconds() / 86400 if avg_duration else 0
context['bed_stats'] = {
'occupancy_rate': 0, # Placeholder - would need more complex calculation
'total_admissions': total_admissions,
'avg_stay_days': avg_stay_days,
}
# Placeholder for maintenance schedule
context['maintenance_schedule'] = []
return context
@ -1593,9 +1614,169 @@ def bed_details(request, bed_id):
tenant = request.user.tenant
bed = get_object_or_404(Bed, ward__tenant=tenant,id=bed_id)
# Bed stats
admissions = Admission.objects.filter(current_bed=bed)
total_admissions = admissions.count()
avg_stay_days = 0
if total_admissions > 0:
avg_duration = admissions.aggregate(avg_duration=Avg(ExpressionWrapper(F('discharge_datetime') - F('admission_datetime'), output_field=DurationField())))['avg_duration']
avg_stay_days = avg_duration.total_seconds() / 86400 if avg_duration else 0
context['bed_stats'] = {
'occupancy_rate': bed.occupancy_rate if hasattr(bed, 'occupancy_rate') else 0,
'total_admissions': total_admissions,
'avg_stay_days': avg_stay_days,
}
# Placeholder for maintenance schedule
context['maintenance_schedule'] = []
return render(request, 'inpatients/partials/bed_details.html', {'object':bed})
@login_required
def refresh_bed_history(request, bed_id):
"""
HTMX endpoint to refresh bed history.
"""
bed = get_object_or_404(Bed, id=bed_id, ward__tenant=request.user.tenant)
# Get bed history - admissions that used this bed
admission_history = Admission.objects.filter(
current_bed=bed
).select_related(
'patient', 'admitting_physician',
).order_by('-admission_datetime')
return render(request, 'inpatients/partials/bed_history.html', {
'admission_history': admission_history
})
@login_required
def assign_patient_to_bed(request, bed_id):
"""
View to assign a patient to a bed.
"""
bed = get_object_or_404(Bed, id=bed_id, ward__tenant=request.user.tenant)
if request.method == 'POST':
patient_id = request.POST.get('patient_id')
if patient_id:
patient = get_object_or_404(PatientProfile, id=patient_id, tenant=request.user.tenant)
bed.current_patient = patient
bed.status = 'OCCUPIED'
bed.occupied_since = timezone.now()
bed.save()
messages.success(request, 'Patient assigned to bed successfully.')
return redirect('inpatients:bed_detail', pk=bed.pk)
# GET: show form with patient search
patients = PatientProfile.objects.filter(tenant=request.user.tenant).order_by('-created_at')[:20]
return render(request, 'inpatients/assign_patient.html', {'bed': bed, 'patients': patients})
@login_required
def bed_utilization(request, bed_id):
"""
View for bed utilization chart data.
"""
bed = get_object_or_404(Bed, id=bed_id, ward__tenant=request.user.tenant)
# Generate last 30 days of data
end_date = timezone.now().date()
start_date = end_date - timedelta(days=29)
labels = []
data_points = []
current_date = start_date
while current_date <= end_date:
labels.append(current_date.strftime('%b %d'))
# Calculate occupancy for this date
# This is a simplified calculation - in a real system you'd track historical occupancy
# For now, we'll use a random-ish calculation based on bed admissions
admissions_on_date = Admission.objects.filter(
current_bed=bed,
admission_datetime__date=current_date
).count()
# Simple heuristic: if there were admissions, assume some occupancy
occupancy_rate = min(admissions_on_date * 20 + 30, 100) # Cap at 100%
data_points.append(occupancy_rate)
current_date += timedelta(days=1)
data = {
'labels': labels,
'data': data_points
}
return JsonResponse(data)
@login_required
def update_bed_status(request, bed_id):
"""
View to update bed status.
"""
bed = get_object_or_404(Bed, id=bed_id, ward__tenant=request.user.tenant)
if request.method == 'POST':
new_status = request.POST.get('status')
notes = request.POST.get('notes', '')
if new_status and new_status in dict(Bed.BedStatus.choices):
old_status = bed.status
bed.status = new_status
# Handle special cases
if new_status == 'AVAILABLE' and old_status == 'CLEANING':
bed.last_cleaned = timezone.now()
bed.cleaned_by = request.user
elif new_status == 'MAINTENANCE':
bed.last_maintenance = timezone.now()
if notes:
bed.notes = notes
bed.save()
# Log the action
AuditLogger.log_event(
actor=request.user,
action='BED_STATUS_UPDATED',
target=bed,
target_repr=str(bed),
description=f"Bed status updated from {dict(Bed.BedStatus.choices)[old_status]} to {dict(Bed.BedStatus.choices)[new_status]}"
)
messages.success(request, f"Bed status updated to {bed.get_status_display()}")
else:
messages.error(request, "Invalid bed status")
return redirect('inpatients:bed_detail', pk=bed.pk)
return redirect('inpatients:bed_detail', pk=bed.pk)
@login_required
def refresh_bed_history(request, bed_id):
"""
HTMX endpoint to refresh bed history.
"""
bed = get_object_or_404(Bed, id=bed_id, ward__tenant=request.user.tenant)
# Get bed history - admissions that used this bed
admission_history = Admission.objects.filter(
current_bed=bed
).select_related(
'patient', 'admitting_physician',
).order_by('-admission_datetime')
return render(request, 'inpatients/partials/bed_history.html', {
'admission_history': admission_history
})
@login_required
def clean_bed(request, pk):
"""
@ -2337,6 +2518,149 @@ class AdmissionDetailView(LoginRequiredMixin, DetailView):
return context
class DischargeSummaryListView(LoginRequiredMixin, ListView):
"""
List view for discharge summaries.
"""
model = DischargeSummary
template_name = 'inpatients/discharges/discharge_list.html'
context_object_name = 'discharge_summaries'
paginate_by = 20
def get_queryset(self):
"""Filter discharge summaries by tenant and search query."""
queryset = DischargeSummary.objects.filter(
admission__tenant=self.request.user.tenant
).select_related(
'admission', 'admission__patient', 'discharging_physician'
).order_by('-discharge_date')
# Handle search query
search_query = self.request.GET.get('search', '')
if search_query:
queryset = queryset.filter(
Q(admission__patient__first_name__icontains=search_query) |
Q(admission__patient__last_name__icontains=search_query) |
Q(admission__patient__mrn__icontains=search_query) |
Q(admission_diagnosis__icontains=search_query) |
Q(final_diagnosis__icontains=search_query)
)
# Handle filter by status (e.g., completed)
completed = self.request.GET.get('completed', '')
if completed == 'true':
queryset = queryset.filter(summary_completed=True)
elif completed == 'false':
queryset = queryset.filter(summary_completed=False)
# Handle filter by date range
date_from = self.request.GET.get('date_from', '')
if date_from:
queryset = queryset.filter(discharge_date__gte=date_from)
date_to = self.request.GET.get('date_to', '')
if date_to:
queryset = queryset.filter(discharge_date__lte=date_to)
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({
'search_query': self.request.GET.get('search', ''),
'completed_filter': self.request.GET.get('completed', ''),
'date_from': self.request.GET.get('date_from', ''),
'date_to': self.request.GET.get('date_to', ''),
})
return context
class DischargeSummaryDetailView(LoginRequiredMixin, DetailView):
"""
Detail view for a discharge summary.
"""
model = DischargeSummary
template_name = 'inpatients/discharges/discharge_detail.html'
context_object_name = 'discharge_summary'
def get_queryset(self):
"""Filter discharge summaries by tenant."""
return DischargeSummary.objects.filter(
admission__tenant=self.request.user.tenant
).select_related(
'admission', 'admission__patient', 'discharging_physician', 'primary_nurse'
)
class DischargeSummaryCreateView(LoginRequiredMixin, CreateView):
"""
Create view for a discharge summary.
"""
model = DischargeSummary
form_class = DischargeSummaryForm
template_name = 'inpatients/discharges/discharge_form.html'
permission_required = 'inpatients.add_dischargesummary' # Assuming permission exists
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
def form_valid(self, form):
form.instance.created_by = self.request.user
messages.success(self.request, 'Discharge summary created successfully')
return super().form_valid(form)
def get_success_url(self):
return reverse('inpatients:discharge_summary_detail', kwargs={'pk': self.object.pk})
class DischargeSummaryUpdateView(LoginRequiredMixin, UpdateView):
"""
Update view for a discharge summary.
"""
model = DischargeSummary
form_class = DischargeSummaryForm
template_name = 'inpatients/discharges/discharge_form.html'
permission_required = 'inpatients.change_dischargesummary'
def get_queryset(self):
"""Filter discharge summaries by tenant."""
return DischargeSummary.objects.filter(admission__tenant=self.request.user.tenant)
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
def form_valid(self, form):
messages.success(self.request, 'Discharge summary updated successfully')
return super().form_valid(form)
def get_success_url(self):
return reverse('inpatients:discharge_summary_detail', kwargs={'pk': self.object.pk})
class DischargeSummaryDeleteView(LoginRequiredMixin, DeleteView):
"""
Delete view for a discharge summary.
"""
model = DischargeSummary
template_name = 'inpatients/discharges/discharge_confirm_delete.html'
permission_required = 'inpatients.delete_dischargesummary'
success_url = reverse_lazy('inpatients:discharge_summary_list')
context_object_name = 'discharge_summary'
def get_queryset(self):
"""Filter discharge summaries by tenant."""
return DischargeSummary.objects.filter(admission__tenant=self.request.user.tenant)
def delete(self, request, *args, **kwargs):
summary = self.get_object()
messages.success(request, 'Discharge summary deleted successfully')
return super().delete(request, *args, **kwargs)
@login_required

File diff suppressed because it is too large Load Diff

54026
media/docs/2024-17021.pdf Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,209 @@
# Product Requirements Document (PRD): Hospital Management System v4
## 1. Introduction
### 1.1 Purpose
This PRD documents the current state of the Hospital Management System (HMS) v4, a comprehensive Django-based web application designed to manage hospital operations. The system supports multi-tenant environments, integrates healthcare standards (e.g., ICD-10 codes, SBS billing), and covers key domains such as patient care, administrative functions, financial billing, and facility operations. It facilitates efficient workflows for healthcare providers, administrators, and support staff.
### 1.2 Scope
The system is modular, with Django apps handling specific functionalities. Core features include patient registration, appointment scheduling, electronic medical records (EMR), inpatient management, laboratory and radiology services, pharmacy, billing, HR, inventory, blood bank, operating theatre, quality assurance, communications, analytics, and facility management. Data generation scripts (e.g., `hr_data.py`, `inpatients_data.py`) and compliance documents (e.g., ICD-10 XML files, SBS code lists) indicate support for testing and regulatory adherence.
### 1.3 Target Users
- **Clinical Staff**: Doctors, nurses (EMR, appointments, inpatients, lab/radiology/pharmacy).
- **Administrative Staff**: Receptionists, admins (patient profiles, billing, HR, inventory).
- **Management**: Executives (analytics, quality, facility management).
- **Support**: IT (integrations, core system config).
### 1.4 Assumptions and Dependencies
- Built on Django with PostgreSQL/SQLite (evident from `db.sqlite3` and migrations).
- Uses external libraries (e.g., via `requirements.txt`, `uv.lock`).
- Multi-tenant via `core.models.Tenant`.
- Compliance with Saudi health standards (SBS V2, ICD-10).
## 2. System Architecture
### 2.1 High-Level Overview
- **Framework**: Django (MVC pattern) with apps for modularity.
- **Database**: Relational (models use Django ORM); supports audit logging (`core.models.AuditLogEntry`).
- **Frontend**: Django templates (e.g., dashboards for HR/inpatients, lists for assets/maintenance).
- **Backend**: Views and forms for CRUD operations; API endpoints in most apps (e.g., `accounts/api/`).
- **Integrations**: External systems via `integration` app (endpoints, webhooks, logs).
- **Security**: Two-factor auth, password history (`accounts`); consents (`patients`).
- **File Structure**: Root-level data scripts, Django project (`hospital_management`), apps with models/views/templates/migrations.
### 2.2 Key Technologies
- Python/Django.
- Templates: HTML with partials (e.g., bed details, transfer forms).
- Standards: ICD-10 (`emr.models.Icd10`), SBS billing (`billing`).
## 3. Features
The system implements a wide range of hospital workflows. Below is a breakdown by module.
### 3.1 Core System (`core`)
- Tenant management for multi-hospital support.
- System configurations, notifications, audit logs.
- Middleware and context processors for global functionality.
### 3.2 User Accounts and Authentication (`accounts`)
- User sessions, social accounts, two-factor devices.
- Password history for security compliance.
### 3.3 Patient Management (`patients`)
- Patient profiles with emergency contacts.
- Insurance info, claims (with documents, status history).
- Consent templates and forms.
- Patient notes for documentation.
### 3.4 Appointments (`appointments`)
- Appointment requests and slot availability.
- Waiting queues and lists with contact logs.
- Telemedicine sessions.
- Templates for recurring schedules.
### 3.5 Electronic Medical Records (EMR) (`emr`)
- Encounters linking to patient visits.
- Vital signs tracking.
- Problem lists, care plans, clinical notes (with templates).
- ICD-10 code integration for diagnoses.
### 3.6 Inpatient Management (`inpatients`)
- Wards and bed management (status updates).
- Admissions, discharge summaries.
- Patient transfers.
- Surgery schedules.
UI: Dashboards, ward/bed lists/details, transfer forms/management (from open tabs).
### 3.7 Laboratory (`laboratory`)
- Lab tests, orders, specimens.
- Results with quality control and reference ranges.
### 3.8 Radiology (`radiology`)
- Imaging studies, series, DICOM images.
- Reports with templates.
- Orders for procedures.
### 3.9 Pharmacy (`pharmacy`)
- Medication catalog with interactions.
- Prescriptions, inventory items, dispense records.
- Administration tracking.
### 3.10 Operating Theatre (`operating_theatre`)
- Operating rooms and block scheduling.
- Surgical cases, notes (with templates), equipment usage.
### 3.11 Blood Bank (`blood_bank`)
- Blood groups, donors, components, units.
- Testing (cross-match, infectious diseases).
- Requests, issues, transfusions, adverse reactions.
- Inventory locations and quality control.
### 3.12 Billing (`billing`)
- Medical bills with line items.
- Insurance claims, payments, status updates.
- Billing configurations for SBS compliance.
### 3.13 Human Resources (HR) (`hr`)
- Employee profiles, departments.
- Schedules, assignments, time entries.
- Performance reviews.
- Training programs (modules, prerequisites, sessions, records, attendance, assessments, certificates).
UI: HR dashboard (from open tabs).
### 3.14 Inventory (`inventory`)
- Items, stock levels, locations.
- Purchase orders, suppliers.
### 3.15 Facility Management (`facility_management`)
- Buildings, floors, rooms.
- Assets (categories), maintenance (requests, schedules, types).
- Vendors, service contracts, inspections.
- Energy meters/readings, space reservations.
UI: Asset/maintenance lists (from open tabs).
### 3.16 Quality Assurance (`quality`)
- Quality indicators and measurements.
- Incident reports, risk assessments.
- Audit plans/findings.
- Improvement projects.
### 3.17 Communications (`communications`)
- Messages and recipients.
- Notification templates, alert rules/instances.
- Channels and delivery logs.
### 3.18 Analytics (`analytics`)
- Dashboards with widgets.
- Data sources, reports, executions.
- Metric definitions and values.
### 3.19 Integrations (`integration`)
- External systems, endpoints, data mappings.
- Execution logs, webhooks.
## 4. Data Model
The system uses Django models for relational data. Key entities (from 144+ models):
- **Patients/Encounters**: `PatientProfile`, `Encounter`, `VitalSigns`, `ProblemList`, `CarePlan`.
- **Clinical Data**: `ClinicalNote`, `Icd10`, `LabResult`, `ImagingStudy`, `Prescription`, `MedicationAdministration`.
- **Administrative**: `Employee`, `Department`, `AppointmentRequest`, `MedicalBill`, `InsuranceClaim`.
- **Operational**: `Ward`, `Bed`, `Admission`, `Transfer`, `SurgicalCase`, `BloodUnit`, `InventoryItem`, `Asset`, `MaintenanceRequest`.
- **Support**: `AuditLogEntry`, `SystemConfiguration`, `QualityIndicator`, `IncidentReport`.
- Relationships: Foreign keys link entities (e.g., `Admission` to `PatientProfile`, `LabOrder` to `Encounter`). Choices (e.g., `TrainingType`) and many-to-many (e.g., schedules).
Data integrity via signals (e.g., `accounts/signals.py`, `facility_management/signals.py`). Migrations ensure schema evolution.
## 5. User Interface and Experience
- **Dashboards**: Centralized views (e.g., inpatients dashboard, HR dashboard).
- **Lists and Details**: Paginated lists (wards, beds, assets, maintenance); detail views with partials (bed details, update forms).
- **Forms**: Interactive (e.g., transfer forms, bed status updates).
- **Templates**: Modular (e.g., `inpatients/templates/inpatients/partials/` for reusable components).
- Responsive design inferred from Django templates; no explicit JS frameworks noted.
Open tabs indicate focus on inpatient workflows (wards, beds, transfers) and HR/facility management.
## 6. Non-Functional Requirements
### 6.1 Security
- Authentication: Sessions, 2FA, social login.
- Auditing: Logs for all actions.
- Consents: Managed forms.
### 6.2 Performance
- Analytics for metrics; scalable via Django ORM.
- Inventory/quality control for real-time tracking.
### 6.3 Compliance
- ICD-10 for diagnoses (`emr`).
- SBS V2 for billing (`billing`).
- Quality indicators for accreditation.
### 6.4 Testing and Data
- Test files in apps (e.g., `tests.py`).
- Data generators (e.g., `patients_data.py`) for population.
## 7. Current Status and Gaps
### 7.1 Implemented
- Full CRUD for core entities.
- Web UI for key modules (inpatients, HR, facility).
- Backend APIs and integrations ready.
### 7.2 Potential Gaps
- No explicit mobile/responsive UI details.
- Advanced features (e.g., AI analytics) not evident.
- Full end-to-end testing coverage unknown.
- Deployment config (e.g., ASGI in `hospital_management/asgi.py`).
### 7.3 Next Steps Recommendations
- Implement user roles/permissions.
- Add real-time features (e.g., WebSockets for notifications).
- Integrate with external APIs (e.g., via `integration`).
- Conduct security audits and performance testing.
This PRD is based on the codebase analysis as of 9/21/2025. Total models: 144+, indicating a mature, feature-rich system.

BIN
static/.DS_Store vendored

Binary file not shown.

Binary file not shown.

BIN
static/plugins/ionicons/.DS_Store vendored Normal file

Binary file not shown.

62
system_prompt.md Normal file
View File

@ -0,0 +1,62 @@
Agent Instructions — Complete & Finish Hospital Management System v4
You are a senior Django architect + full-stack developer and your job is to finish the partially-completed `hospital_management` codebase so it fully matches the provided PRD (Hospital Management System v4). This is mission-critical: do **not** dump all code at once. Follow a strict phased plan-and-approve workflow so I can verify each step and reduce hallucination.
BEFORE YOU START: you must compare the "current prompt / implemented spec" (the system you already produced) with the PRD attached by the user and produce a short gap analysis (a list of missing features, mismatches, and priority items). Show the gap analysis first and pause for my confirmation. Do not implement anything until I confirm the gap analysis.
PHASES (high level)
1) Gap Analysis (required) — produce a structured list of missing modules, missing fields, missing integrations, missing non-functional items (ASGI/websockets, mobile/responsive, AI analytics hooks, tests, CI, deployment configs), and any commented JS functions in templates that appear unimplemented. Pause.
2) Discovery & Repo Scan — when I approve the gap analysis, scan the repo (templates, apps, static assets, migrations) and produce an inventory: list of apps, list of templates that contain commented JS functions (with file path + exact commented code snippet), list of endpoints/views that exist vs. required by the PRD, list of missing migrations, and test coverage gaps. Pause.
3) Per-App Scoping & Approval — for each app I approve (one at a time), produce a complete scope: models (full fields + choices), serializers/forms, views (UI + HTMX endpoints + API), templates/partials, static asset list (SASS partials), Celery tasks, HL7/DICOM/PACS hooks, WebSocket events (if relevant), tests (unit + integration). Pause and wait for “👍 go ahead with [app_name]”.
4) Implementation (per app, incremental) — after approval for an app, implement only that apps deliverables in this order: models.py → pause → serializers/forms & admin → pause → views + templates + HTMX snippets + JS modules (if genuinely needed) → pause → tests (pytest) → pause → migrations & fixture seeds → pause. Each pause is a hard stop for my review.
5) Shared Tooling & Final Integration (last phase) — Webpack/asset pipeline, HTMX guidelines, ASGI + Channels setup for WebSockets, Celery + Redis, HL7 + PACS interfaces, DRF docs, pytest + coverage, GitHub Actions CI, deployment (Gunicorn+Nginx + ASGI workers, multi-tenant notes), GDPR/HIPAA checklist, monitoring, backups, and runbook. Pause for final signoff.
MANDATORY RULES FOR THE AGENT
- Always pause after the Gap Analysis and after each deliverable chunk listed above and wait for explicit approval before continuing. Use the exact pause phrasing: “**Paused — awaiting approval: [description]**”.
- NEVER leave CSS or JS scattered in templates. All styles must be SCSS partials under `static/css/` and JS modules (if required) under `static/js/`. Templates must only include bundle loaders (e.g., `{% render_bundle 'main' 'css' %}`, `{% render_bundle 'main' 'js' %}`) or HTMX attributes.
- HTMX is the preferred mechanism for dynamic interactions. Use small unobtrusive JS only when HTMX cannot provide the functionality (charting libraries are acceptable).
- For any UI interaction previously implemented with commented JavaScript functions inside templates: you must:
1. List every template file that contains commented JS functions (file path + exact commented function body).
2. For each such function decide whether it should be replaced with an HTMX endpoint, a Django view (returning partial HTML), or a small JS module imported via Webpack. Prefer HTMX where possible.
3. Implement the change: uncomment the function (or replace it), create the correct server side view / DRF endpoint / HTMX fragment, wire the template (remove inline script if replaced by HTMX), and add tests that validate both the front-end interaction (via a simple integration test using Django's test client or HTMX-compatible request) and the server behavior.
4. Add a comment in the template referencing the view name and test id.
**Do not** leave any commented JS functions in templates after your work—either remove them or make them active and covered by tests.
- Provide a traceability matrix that maps every PRD item to the exact file(s) and tests that implement it (e.g., PRD §3.6 → `inpatients/models.py:Admission`, `inpatients/views.py:AdmissionUpdateView`, `tests/inpatients/test_admission_flow.py`). This matrix must be updated as you implement items.
- Add or update migrations and provide `./manage.py migrate` run notes (including any data migrations) in the README.
- Add pytest tests for each implemented feature (models, views, HTMX flows, integrations). Target at least 85% coverage for newly implemented modules; report coverage per app.
- For integrations (HL7, PACS/DICOM, external APIs listed in PRD e.g., BestCare, Cerner, Epic): provide concrete adapter stubs with config examples and tests that simulate inbound/outbound messages. Use environment variables for credentials; do not hardcode secrets.
PRIORITY ITEMS (must be in the Gap Analysis and implemented first once approved)
- WebSockets/real-time notifications (ASGI + Channels) for: waiting queue updates, bed status, telemedicine session start, OR schedule changes, ambulance dispatch updates.
- Mobile/responsive work: ensure core templates are responsive and provide a mobile view for patient portal and clinician quick-actions.
- AI analytics hooks and a sample risk-scoring job integrated into `decision_support` (a stub that runs over recent encounters and emits alerts into `AlertLog`).
- Blood Bank app completeness (blood units, cross-match, transfusions) if missing.
- Full HL7 v2.x inbound/outbound wiring and a PACS adapter for DICOMStudy ingestion (stubs with tests).
- Ensure multi-tenant isolation is consistently applied (Tenant FK or tenant middleware where appropriate).
- Tests and CI (GitHub Actions) for all implemented parts.
- Commented JS functions: list + implement (see above mandatory rule).
DELIVERABLE FORMAT (for each pause)
- Short summary (25 lines) of what you did / will do next.
- File list changed/added (paths).
- Relevant code snippets (only the smallest necessary to explain, not full files unless asked).
- Tests added (paths).
- “Paused — awaiting approval: [description]”
EXTRA REQUIREMENTS & STANDARDS
- Code style: black + isort + flake8. Include pre-commit config.
- Migrations: No destructive migrations without a data-migration plan stated in the pause note.
- Security: Add 2FA (already present but ensure it's fully wired in login flow), encryption key rotation notes, and an audit log for all PII access.
- Documentation: update README with per-app setup, developer notes for HTMX, asset build commands, how to run the async workers, and how to test HL7/DICOM adapters locally (with sample payloads).
- Accessibility: ensure forms use proper labels and aria attributes for key patient/clinician views.
- Performance: add simple caching strategy (per-tenant cache keys) for dashboards/widgets that query large analytics tables.
FINAL PHASE & SIGNOFF
When all apps and the shared tooling are complete, produce:
1. Full traceability matrix (PRD → code + tests).
2. Final test coverage report and CI badge.
3. Deployment runbook (step-by-step: build assets, apply migrations, start ASGI/WSGI workers, start Celery, configure Nginx, configure load balancer, backup/rollback procedures).
4. A “what changed” summary for operations (including required config changes, env vars, credentials to set, and any manual steps for cutover).
START NOW (but remember: FIRST produce the Gap Analysis and pause)
- Step 0: Output a clear Gap Analysis comparing the current implemented prompt/spec vs the PRD attached (identify missing apps, missing model fields, missing integrations, commented JS functions in templates, missing ASGI/websocket, missing tests/CI, mobile issues, compliance items). The Gap Analysis must be a numbered list grouped by priority (Critical, High, Medium, Low).
**Paused — awaiting approval: Gap Analysis**