465 lines
20 KiB
HTML
465 lines
20 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}Cancel Blood Request - {{ blood_request.request_number }}{% endblock %}
|
|
|
|
{% block css %}
|
|
<style>
|
|
.delete-warning {
|
|
background: #f8d7da;
|
|
border: 2px solid #dc3545;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
margin-bottom: 20px;
|
|
animation: pulse 2s infinite;
|
|
}
|
|
|
|
@keyframes pulse {
|
|
0% { opacity: 1; }
|
|
50% { opacity: 0.8; }
|
|
100% { opacity: 1; }
|
|
}
|
|
|
|
.request-info {
|
|
background: #d1ecf1;
|
|
border-left: 4px solid #17a2b8;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.impact-assessment {
|
|
background: #fff3cd;
|
|
border-left: 4px solid #ffc107;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.cancellation-options {
|
|
background: #d4edda;
|
|
border-left: 4px solid #28a745;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.required-field {
|
|
color: #dc3545;
|
|
}
|
|
|
|
.emergency-warning {
|
|
background: #dc3545;
|
|
color: white;
|
|
padding: 15px;
|
|
border-radius: 8px;
|
|
margin-bottom: 20px;
|
|
text-align: center;
|
|
font-weight: bold;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<!-- BEGIN breadcrumb -->
|
|
<ol class="breadcrumb float-xl-end">
|
|
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Home</a></li>
|
|
<li class="breadcrumb-item"><a href="{% url 'blood_bank:dashboard' %}">Blood Bank</a></li>
|
|
<li class="breadcrumb-item"><a href="{% url 'blood_bank:blood_request_list' %}">Blood Requests</a></li>
|
|
<li class="breadcrumb-item"><a href="{% url 'blood_bank:blood_request_detail' blood_request.id %}">{{ blood_request.request_number }}</a></li>
|
|
<li class="breadcrumb-item active">Cancel Request</li>
|
|
</ol>
|
|
<!-- END breadcrumb -->
|
|
|
|
<!-- BEGIN page-header -->
|
|
<h1 class="page-header">
|
|
Cancel Blood Request
|
|
<small>{{ blood_request.request_number }}</small>
|
|
{% if blood_request.urgency == 'emergency' %}
|
|
<span class="badge bg-danger ms-2">EMERGENCY</span>
|
|
{% endif %}
|
|
</h1>
|
|
<!-- END page-header -->
|
|
|
|
{% if blood_request.urgency == 'emergency' %}
|
|
<!-- BEGIN emergency warning -->
|
|
<div class="emergency-warning">
|
|
<i class="fa fa-exclamation-triangle fa-2x"></i><br>
|
|
WARNING: This is an EMERGENCY blood request. Cancellation requires immediate supervisor approval.
|
|
</div>
|
|
<!-- END emergency warning -->
|
|
{% endif %}
|
|
|
|
<!-- BEGIN panel -->
|
|
<div class="panel panel-inverse">
|
|
<div class="panel-heading">
|
|
<h4 class="panel-title">
|
|
<i class="fa fa-times-circle"></i> Cancel Blood Request
|
|
</h4>
|
|
<div class="panel-heading-btn">
|
|
<span class="badge bg-warning">Cancellation Required</span>
|
|
</div>
|
|
</div>
|
|
<div class="panel-body">
|
|
<!-- BEGIN delete warning -->
|
|
<div class="delete-warning">
|
|
<h5><i class="fa fa-exclamation-triangle"></i> CRITICAL ACTION REQUIRED</h5>
|
|
<p class="mb-2"><strong>You are about to cancel a blood request.</strong></p>
|
|
<p class="mb-0">This action will:</p>
|
|
<ul class="mb-0">
|
|
<li>Cancel the blood request permanently</li>
|
|
<li>Release any reserved blood units</li>
|
|
<li>Notify the requesting physician</li>
|
|
<li>Create an audit trail entry</li>
|
|
{% if blood_request.urgency == 'emergency' %}
|
|
<li><strong>Require supervisor approval for emergency request</strong></li>
|
|
{% endif %}
|
|
</ul>
|
|
</div>
|
|
<!-- END delete warning -->
|
|
|
|
<!-- BEGIN request information -->
|
|
<div class="request-info">
|
|
<h5><i class="fa fa-file-medical"></i> Request Information</h5>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<table class="table table-borderless mb-0">
|
|
<tr>
|
|
<td class="fw-bold">Request Number:</td>
|
|
<td>{{ blood_request.request_number }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold">Patient:</td>
|
|
<td>{{ blood_request.patient.full_name }} ({{ blood_request.patient.patient_id }})</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold">Blood Group:</td>
|
|
<td><span class="badge bg-primary">{{ blood_request.patient.blood_group.display_name }}</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold">Component:</td>
|
|
<td>{{ blood_request.component.get_name_display }}</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<table class="table table-borderless mb-0">
|
|
<tr>
|
|
<td class="fw-bold">Quantity:</td>
|
|
<td>{{ blood_request.quantity_requested }} units</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold">Urgency:</td>
|
|
<td>
|
|
<span class="badge bg-{% if blood_request.urgency == 'emergency' %}danger{% elif blood_request.urgency == 'urgent' %}warning{% else %}info{% endif %}">
|
|
{{ blood_request.get_urgency_display }}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold">Requested By:</td>
|
|
<td>{{ blood_request.requested_by.get_full_name }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold">Department:</td>
|
|
<td>{{ blood_request.department.name }}</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
{% if blood_request.clinical_indication %}
|
|
<div class="mt-3">
|
|
<h6>Clinical Indication:</h6>
|
|
<div class="alert alert-info">{{ blood_request.clinical_indication }}</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<!-- END request information -->
|
|
|
|
<!-- BEGIN impact assessment -->
|
|
<div class="impact-assessment">
|
|
<h5><i class="fa fa-exclamation-circle"></i> Impact Assessment</h5>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h6>Current Status</h6>
|
|
<ul>
|
|
<li><strong>Request Status:</strong> {{ blood_request.get_status_display }}</li>
|
|
<li><strong>Units Reserved:</strong> {{ blood_request.reserved_units.count }} units</li>
|
|
<li><strong>Units Issued:</strong> {{ blood_request.issued_units.count }} units</li>
|
|
<li><strong>Crossmatches Done:</strong> {{ blood_request.crossmatches.count }}</li>
|
|
</ul>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h6>Affected Records</h6>
|
|
<ul>
|
|
{% if blood_request.reserved_units.exists %}
|
|
<li class="text-warning">Reserved blood units will be released</li>
|
|
{% endif %}
|
|
{% if blood_request.issued_units.exists %}
|
|
<li class="text-danger">Issued units require immediate return</li>
|
|
{% endif %}
|
|
{% if blood_request.crossmatches.exists %}
|
|
<li class="text-info">Crossmatch results will be archived</li>
|
|
{% endif %}
|
|
<li class="text-info">Audit trail will be created</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
{% if blood_request.issued_units.exists %}
|
|
<div class="alert alert-danger mt-3">
|
|
<strong><i class="fa fa-exclamation-triangle"></i> WARNING:</strong>
|
|
This request has issued blood units that must be returned immediately before cancellation.
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<!-- END impact assessment -->
|
|
|
|
<!-- BEGIN cancellation form -->
|
|
<form method="post" id="cancellationForm">
|
|
{% csrf_token %}
|
|
|
|
<div class="cancellation-options">
|
|
<h5><i class="fa fa-clipboard-list"></i> Cancellation Details</h5>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="cancellationReason" class="form-label">
|
|
Cancellation Reason <span class="required-field">*</span>
|
|
</label>
|
|
<select class="form-select" id="cancellationReason" name="cancellation_reason" required>
|
|
<option value="">Select reason...</option>
|
|
<option value="patient_condition_improved">Patient condition improved</option>
|
|
<option value="surgery_cancelled">Surgery cancelled</option>
|
|
<option value="patient_discharged">Patient discharged</option>
|
|
<option value="alternative_treatment">Alternative treatment chosen</option>
|
|
<option value="physician_decision">Physician decision</option>
|
|
<option value="patient_refusal">Patient refusal</option>
|
|
<option value="duplicate_request">Duplicate request</option>
|
|
<option value="incorrect_request">Incorrect request details</option>
|
|
<option value="other">Other (specify below)</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="cancelledBy" class="form-label">
|
|
Cancelled By <span class="required-field">*</span>
|
|
</label>
|
|
<select class="form-select" id="cancelledBy" name="cancelled_by" required>
|
|
<option value="">Select staff member...</option>
|
|
{% for staff in authorized_staff %}
|
|
<option value="{{ staff.id }}">{{ staff.get_full_name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% if blood_request.urgency == 'emergency' %}
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="supervisorApproval" class="form-label">
|
|
Supervisor Approval <span class="required-field">*</span>
|
|
</label>
|
|
<select class="form-select" id="supervisorApproval" name="supervisor_approval" required>
|
|
<option value="">Select supervisor...</option>
|
|
{% for supervisor in supervisors %}
|
|
<option value="{{ supervisor.id }}">{{ supervisor.get_full_name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="approvalCode" class="form-label">
|
|
Approval Code <span class="required-field">*</span>
|
|
</label>
|
|
<input type="text" class="form-control" id="approvalCode" name="approval_code"
|
|
placeholder="Enter supervisor approval code" required>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="row">
|
|
<div class="col-md-12">
|
|
<div class="form-group">
|
|
<label for="cancellationNotes" class="form-label">
|
|
Detailed Notes <span class="required-field">*</span>
|
|
</label>
|
|
<textarea class="form-control" id="cancellationNotes" name="cancellation_notes"
|
|
rows="4" required placeholder="Provide detailed explanation for the cancellation..."></textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="notifyPhysician" class="form-label">Notify Requesting Physician</label>
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" id="notifyPhysician"
|
|
name="notify_physician" checked>
|
|
<label class="form-check-label" for="notifyPhysician">
|
|
Send notification to {{ blood_request.requested_by.get_full_name }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="notifyDepartment" class="form-label">Notify Department</label>
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" id="notifyDepartment"
|
|
name="notify_department" checked>
|
|
<label class="form-check-label" for="notifyDepartment">
|
|
Send notification to {{ blood_request.department.name }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- BEGIN confirmation checklist -->
|
|
<div class="alert alert-warning">
|
|
<h6><i class="fa fa-check-square"></i> Confirmation Checklist</h6>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="confirmUnderstand" required>
|
|
<label class="form-check-label" for="confirmUnderstand">
|
|
I understand that this action will permanently cancel the blood request
|
|
</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="confirmNotifications" required>
|
|
<label class="form-check-label" for="confirmNotifications">
|
|
I confirm that appropriate notifications will be sent
|
|
</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="confirmDocumentation" required>
|
|
<label class="form-check-label" for="confirmDocumentation">
|
|
I confirm that proper documentation has been provided
|
|
</label>
|
|
</div>
|
|
{% if blood_request.issued_units.exists %}
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="confirmUnitsReturned" required>
|
|
<label class="form-check-label" for="confirmUnitsReturned">
|
|
I confirm that all issued blood units have been returned
|
|
</label>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<!-- END confirmation checklist -->
|
|
|
|
<!-- BEGIN form actions -->
|
|
<div class="d-flex justify-content-between mt-4">
|
|
<a href="{% url 'blood_bank:blood_request_detail' blood_request.id %}" class="btn btn-secondary">
|
|
<i class="fa fa-arrow-left"></i> Keep Request Active
|
|
</a>
|
|
<div>
|
|
<button type="button" class="btn btn-info" onclick="validateCancellation()">
|
|
<i class="fa fa-check"></i> Validate Cancellation
|
|
</button>
|
|
<button type="submit" class="btn btn-danger" id="submitBtn" disabled>
|
|
<i class="fa fa-times-circle"></i> Cancel Blood Request
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<!-- END form actions -->
|
|
</form>
|
|
<!-- END cancellation form -->
|
|
</div>
|
|
</div>
|
|
<!-- END panel -->
|
|
{% endblock %}
|
|
|
|
{% block js %}
|
|
<script>
|
|
$(document).ready(function() {
|
|
// Form validation
|
|
$('.form-check-input').on('change', function() {
|
|
validateCancellation();
|
|
});
|
|
|
|
$('#cancellationReason, #cancelledBy, #cancellationNotes').on('change input', function() {
|
|
validateCancellation();
|
|
});
|
|
|
|
{% if blood_request.urgency == 'emergency' %}
|
|
$('#supervisorApproval, #approvalCode').on('change input', function() {
|
|
validateCancellation();
|
|
});
|
|
{% endif %}
|
|
|
|
$('#cancellationForm').on('submit', function(e) {
|
|
if (!validateCancellation()) {
|
|
e.preventDefault();
|
|
} else {
|
|
// Final confirmation
|
|
if (!confirm('Are you absolutely sure you want to cancel this blood request? This action cannot be undone.')) {
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
function validateCancellation() {
|
|
var errors = [];
|
|
|
|
// Check required fields
|
|
if (!$('#cancellationReason').val()) {
|
|
errors.push('Please select a cancellation reason');
|
|
}
|
|
|
|
if (!$('#cancelledBy').val()) {
|
|
errors.push('Please select who is cancelling the request');
|
|
}
|
|
|
|
if (!$('#cancellationNotes').val().trim()) {
|
|
errors.push('Please provide detailed notes for the cancellation');
|
|
}
|
|
|
|
{% if blood_request.urgency == 'emergency' %}
|
|
if (!$('#supervisorApproval').val()) {
|
|
errors.push('Supervisor approval is required for emergency requests');
|
|
}
|
|
|
|
if (!$('#approvalCode').val().trim()) {
|
|
errors.push('Approval code is required for emergency requests');
|
|
}
|
|
{% endif %}
|
|
|
|
// Check confirmation checkboxes
|
|
var requiredCheckboxes = ['confirmUnderstand', 'confirmNotifications', 'confirmDocumentation'];
|
|
{% if blood_request.issued_units.exists %}
|
|
requiredCheckboxes.push('confirmUnitsReturned');
|
|
{% endif %}
|
|
|
|
var uncheckedBoxes = requiredCheckboxes.filter(function(id) {
|
|
return !document.getElementById(id).checked;
|
|
});
|
|
|
|
if (uncheckedBoxes.length > 0) {
|
|
errors.push('Please confirm all checklist items');
|
|
}
|
|
|
|
// Enable/disable submit button
|
|
$('#submitBtn').prop('disabled', errors.length > 0);
|
|
|
|
if (errors.length > 0 && errors.length < 6) {
|
|
// Only show errors if there are just a few (user is actively trying to submit)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
</script>
|
|
{% endblock %}
|
|
|