class ExportTherapyBookingsExcelHTML(generic.View):
def get(self, request, *args, **kwargs):
start_date = request.GET.get('start_date')
end_date = request.GET.get('end_date')
single_date = request.GET.get('date')
format_type = request.GET.get('format', 'vertical')
if not single_date and not start_date:
return HttpResponse("Provide date OR start_date & end_date", status=400)
all_bookings = []
if single_date:
data, *_ = get_therapy_bookings_by_date(single_date, user=request.user)
all_bookings.extend(data)
else:
start = datetime.strptime(start_date, "%Y-%m-%d")
end = datetime.strptime(end_date, "%Y-%m-%d")
while start <= end:
date_str = start.strftime("%Y-%m-%d")
data, *_ = get_therapy_bookings_by_date(date_str, user=request.user)
all_bookings.extend(data)
start += timedelta(days=1)
def clean(val):
if not val:
return ''
return str(val).replace('\n', ' ').strip()
html = """
<html>
<head>
<style>
table { border-collapse: collapse; width: 100%; font-size: 12px; }
th, td {
border: 1px solid #999;
padding: 6px;
vertical-align: top;
word-wrap: break-word;
white-space: normal;
}
.parent-header { background-color: #343a40; color: white; font-weight: bold; }
.child-header { background-color: #d9ead3; font-weight: bold; }
</style>
</head>
<body>
<table>
"""
if format_type == 'horizontal':
# Horizontal headers
html += """
<tr>
<!-- Parent headers -->
<th class="parent-header">Time</th>
<th class="parent-header">Name</th>
<th class="parent-header">Therapist</th>
<th class="parent-header">Title</th>
<th class="parent-header">Sessions</th>
<th class="parent-header">Med. Sent Days</th>
<th class="parent-header">Age</th>
<th class="parent-header">Address</th>
<th class="parent-header">Accepted Time</th>
<th class="parent-header">T | C | C | S</th>
<th class="parent-header">Invoice</th>
<th class="parent-header">Amount</th>
<th class="parent-header">Commission</th>
<th class="parent-header">Payout</th>
<th class="parent-header">Booking Status</th>
<th class="parent-header">Location</th>
<!-- Child headers -->
<th class="child-header">Session No</th>
<th class="child-header">Appointment Time</th>
<th class="child-header">Duration</th>
<th class="child-header">Medicines</th>
<th class="child-header">Medicines Sent</th>
<th class="child-header">Pre Notes</th>
<th class="child-header">Post Notes</th>
<th class="child-header">Session Status</th>
<th class="child-header">Reason</th>
<th class="child-header">Ph. No.</th>
<th class="child-header">Name</th>
<th class="child-header">Med Img</th>
<th class="child-header">Med Picked At</th>
<th class="child-header">Therapy Start</th>
<th class="child-header">Therapy End</th>
<th class="child-header">Payment Amt</th>
<th class="child-header">Payment Status</th>
<th class="child-header">Commission</th>
<th class="child-header">Payout Amt</th>
<th class="child-header">Payout Status</th>
</tr>
"""
for booking in all_bookings:
for therapy_booking in booking.get('therapy_bookings', []):
parent_data = [
clean(booking.get('start_time')),
clean(therapy_booking.get('patient_name')),
clean(therapy_booking.get('today_therapist_name')),
clean(therapy_booking.get('therapy_title_with_duration')),
f'="{clean(therapy_booking.get("cur_session_by_total_sessions"))}"',
clean(therapy_booking.get('medicine_sent_for_days')),
clean(therapy_booking.get('patient_age')),
clean(
f"{therapy_booking.get('address_flat_no_building', '')}, "
f"{therapy_booking.get('address_area_locality', '')}, "
f"{therapy_booking.get('address_landmark', '')}, "
f"{therapy_booking.get('address_city', '')}"
),
clean(therapy_booking.get('treatment_accepted_at')),
clean(
f"{therapy_booking.get('is_bed_needed')} | "
f"{therapy_booking.get('is_cooker_needed')} | "
f"{therapy_booking.get('is_cylinder_needed')} | "
f"{therapy_booking.get('is_steam_needed')}"
),
clean(therapy_booking.get('invoice_url')),
clean(therapy_booking.get('total_amount')),
clean(therapy_booking.get('therapist_total_commission')),
clean(therapy_booking.get('total_payout_amount')),
clean(therapy_booking.get('payment_status')),
clean(therapy_booking.get('location')),
]
for session in therapy_booking.get('sessions', []):
if session.get('status') == 'INACTIVE':
continue
session_data = [
clean(session.get('session_no')),
clean(session.get('scheduled_appointment_start_time')),
clean(session.get('duration')),
clean(session.get('session_description')),
clean(session.get('medicine_sent_uploaded')),
clean(session.get('pre_therapy_notes')),
clean(session.get('post_therapy_notes')),
clean(session.get('status')),
clean(session.get('cancel_reason') or session.get('modify_reason') or 'N/A'),
clean(session.get('therapist_phone_number')),
clean(session.get('therapist_name')),
"Available",
clean(session.get('med_picked_at')),
clean(session.get('start_qr_token_session_validated_at') or session.get('start_otp_token_session_validated_at')),
clean(session.get('end_qr_token_session_validated_at') or session.get('end_otp_token_session_validated_at')),
clean(session.get('payment_amount')),
clean(session.get('payment_status')),
clean(session.get('therapist_commission')),
clean(session.get('payout_amount')),
clean(session.get('payout_status')),
]
row = parent_data + session_data
html += "<tr>"
for col in row:
html += f"<td>{col}</td>"
html += "</tr>"
html += '<tr><td colspan="36" style="background:#eee; height:15px;"></td></tr>'
else:
# Existing vertical/stacked format (current code)
for booking in all_bookings:
for therapy_booking in booking.get('therapy_bookings', []):
# 🔷 PARENT HEADER
html += """
<tr class="parent-header">
<th>Time</th>
<th>Name</th>
<th>Therapist</th>
<th>Title</th>
<th>Sessions</th>
<th>Med Sent Days</th>
<th>Age</th>
<th>Address</th>
<th>Accepted Time</th>
<th>T | C | C | S</th>
<th>Invoice</th>
<th>Amount</th>
<th>Commission</th>
<th>Payout</th>
<th>Status</th>
<th>Location</th>
</tr>
"""
html += f"""
<tr>
<td>{clean(booking.get('start_time'))}</td>
<td>{clean(therapy_booking.get('patient_name'))}</td>
<td>{clean(therapy_booking.get('today_therapist_name'))}</td>
<td>{clean(therapy_booking.get('therapy_title_with_duration'))}</td>
<td style="mso-number-format:\@;">{clean(therapy_booking.get('cur_session_by_total_sessions'))}</td>
<td>{clean(therapy_booking.get('medicine_sent_for_days'))}</td>
<td>{clean(therapy_booking.get('patient_age'))}</td>
<td>{clean(
f"{therapy_booking.get('address_flat_no_building', '')}, "
f"{therapy_booking.get('address_area_locality', '')}, "
f"{therapy_booking.get('address_landmark', '')}, "
f"{therapy_booking.get('address_city', '')}"
)}</td>
<td>{clean(therapy_booking.get('treatment_accepted_at'))}</td>
<td>{clean(
f"{therapy_booking.get('is_bed_needed')} | "
f"{therapy_booking.get('is_cooker_needed')} | "
f"{therapy_booking.get('is_cylinder_needed')} | "
f"{therapy_booking.get('is_steam_needed')}"
)}</td>
<td>{clean(therapy_booking.get('invoice_url'))}</td>
<td>{clean(therapy_booking.get('total_amount'))}</td>
<td>{clean(therapy_booking.get('therapist_total_commission'))}</td>
<td>{clean(therapy_booking.get('total_payout_amount'))}</td>
<td>{clean(therapy_booking.get('payment_status'))}</td>
<td>{clean(therapy_booking.get('location'))}</td>
</tr>
"""
html += """
<tr class="child-header">
<th>Session No</th>
<th>Appointment Time</th>
<th>Duration</th>
<th>Medicines</th>
<th>Medicines Sent</th>
<th>Pre Notes</th>
<th>Post Notes</th>
<th>Status</th>
<th>Reason</th>
<th>Ph. No.</th>
<th>Name</th>
<th>Med Img</th>
<th>Med Picked At</th>
<th>Therapy Start</th>
<th>Therapy End</th>
<th>Payment Amt</th>
<th>Payment Status</th>
<th>Commission</th>
<th>Payout Amt</th>
<th>Payout Status</th>
</tr>
"""
for session in therapy_booking.get('sessions', []):
if session.get('status') == 'INACTIVE':
continue
html += f"""
<tr>
<td>{clean(session.get('session_no'))}</td>
<td>{clean(session.get('scheduled_appointment_start_time'))}</td>
<td>{clean(session.get('duration'))}</td>
<td>{clean(session.get('session_description'))}</td>
<td>{clean(session.get('medicine_sent_uploaded'))}</td>
<td>{clean(session.get('pre_therapy_notes'))}</td>
<td>{clean(session.get('post_therapy_notes'))}</td>
<td>{clean(session.get('status'))}</td>
<td>{clean(session.get('cancel_reason') or session.get('modify_reason') or 'N/A')}</td>
<td>{clean(session.get('therapist_phone_number'))}</td>
<td>{clean(session.get('therapist_name'))}</td>
<td>Available</td>
<td>{clean(session.get('med_picked_at'))}</td>
<td>{clean(session.get('start_qr_token_session_validated_at') or session.get('start_otp_token_session_validated_at'))}</td>
<td>{clean(session.get('end_qr_token_session_validated_at') or session.get('end_otp_token_session_validated_at'))}</td>
<td>{clean(session.get('payment_amount'))}</td>
<td>{clean(session.get('payment_status'))}</td>
<td>{clean(session.get('therapist_commission'))}</td>
<td>{clean(session.get('payout_amount'))}</td>
<td>{clean(session.get('payout_status'))}</td>
</tr>
"""
html += "<tr><td colspan='25' style='background:#eee;'></td></tr>"
html += "</table></body></html>"
response = HttpResponse(content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename=\"therapy_bookings.xls\"'
response.write(html)
return response
Comments
Post a Comment