import calendar
import logging
import pytz
import collections
from collections import defaultdict
from pytz import UTC
from datetime import datetime, timedelta
from bson.objectid import ObjectId
from django.shortcuts import render, redirect
from django.views import generic
from therapist_mgr_app.utils import *
from therapist_mgr_app.views.view_commons import get_eligible_records
from therapist_mgr_app.forms import CLINIC_CHOICES
import csv


logger = logging.getLogger(__name__)

THERAPY_BOOKING_SESSION_ID_IDX = 'therapy_bookings_sessions_id_idx'
ORDER_RECEIPT_IDX = 'order_receipt_idx'
DATE_IDX = 'date_idx'
THERAPY_BOOKING_ID_IDX = 'therapy_booking_id_idx'
ORDINAL = lambda n: "%d%s" % (n, "tsnrhtdd"[(n//10 % 10 != 1)*(n % 10 < 4) * n % 10::4])
IST = pytz.timezone('Asia/Kolkata')
THERAPY_START_DELAY_IN_MINS = 30
DEFAULT_CLINC_ID = '64e33132e4ab680775b6eb98'


def get_therapy_status(session_details_dict, total_sessions, session_status_set, ist_time):
first_session = min(session_details_dict.items(), key=lambda x: x[0])
last_session = max(session_details_dict.items(), key=lambda x: x[0])
ordered_therapy_sessions = collections.OrderedDict(sorted(session_details_dict.items()))

therapy_messages = list()
last_completed_session = 0
for k, v in ordered_therapy_sessions.items():
if v[1] == 'COMPLETED':
last_completed_session = k
if last_completed_session:
therapy_messages.append(f"{last_completed_session} of {total_sessions} Sessions")
if last_completed_session != total_sessions:
therapy_messages.append(f"{ORDINAL(last_completed_session + 1)} Session")

is_all_session_upcoming = len(session_status_set) == 1 and \
'UPCOMING' in session_status_set or 'DELAYED' in session_status_set

first_session_time = first_session[1][0]
first_session_time_ist = IST.localize(first_session_time)
if last_session and last_session[0] == total_sessions and last_session[1][1] == 'COMPLETED':
status = 'COMPLETED'
elif last_session and (last_session[0] == total_sessions or last_session[0] == 1) and last_session[1][1] == 'CANCELLED':
status = 'CANCELLED'
elif is_all_session_upcoming and first_session_time_ist > ist_time:
status = 'UPCOMING'
elif is_all_session_upcoming and \
(first_session_time_ist + timedelta(minutes=THERAPY_START_DELAY_IN_MINS)) < ist_time:
status = 'DELAYED'
elif first_session and (
(first_session[0] != total_sessions and first_session[1][1] == 'COMPLETED') or
(first_session[1][1] in ['PENDING_START', 'ONGOING', 'PENDING_END'])
):
status = 'ONGOING'
else:
status = 'UNKNOWN'

return status, therapy_messages, last_session, last_completed_session


def get_therapy_bookings_by_session_id(therapy_booking_session_id, user):
therapy_bookings_list = list()
therapy_booking_ids_list = list()
therapy_booking_sessions_dict = dict()

if user and user.clinic_id:
clinic_id = user.clinic_id
find_query = {
'therapy_bookings.sessions.clinic_id': clinic_id,
'therapy_bookings.sessions.id': therapy_booking_session_id
}
else:
clinic_id = None
if user.is_staff:
find_query = {
'therapy_bookings.sessions.id': therapy_booking_session_id
}
else:
return 'Invalid User'

user_id = None
for user_therapy_booking in user_therapy_bookings_collection.find(
find_query,
hint=THERAPY_BOOKING_SESSION_ID_IDX
):
therapy_bookings_list.append(
{
'id': user_therapy_booking['_id'],
'user_id': user_therapy_booking['user_id'],
'therapy_bookings': user_therapy_booking['therapy_bookings']
}
)

user_id = ObjectId(user_therapy_booking['user_id'])
for therapy_booking in user_therapy_booking['therapy_bookings']:
for session in therapy_booking['sessions']:
if not user.is_staff:
if clinic_id and session.get('clinic_id') != clinic_id:
continue
therapy_booking_ids_list.append(session['therapist_booking_id'])

user_phone_numbers_dict = dict()
for user_profile in user_profile_collection.find(
{
'_id': user_id
},
{
'_id': 1,
'phone_number': 1,
'is_web_registration': 1,
'patient_phone_number': 1
}
):
user_phone_numbers_dict[str(user_profile['_id'])] = (
user_profile['phone_number'], user_profile.get('is_web_registration'),
user_profile.get('patient_phone_number')
)

therapist_ids = list()
if therapy_booking_ids_list:
for booking in therapy_bookings_collection.find(
{
'therapies.booking_id': {
"$in": therapy_booking_ids_list
}
},
hint=THERAPY_BOOKING_ID_IDX
):
therapist_ids.append(ObjectId(booking['therapist_id']))
for therapy in booking.get('therapies', []):
therapy_booking_sessions_dict[therapy['therapy_booking_session_id']] = (
booking['therapist_id'], therapy.get('therapist_commission', 0),
therapy.get('treatment_accepted', False), therapy.get('treatment_accepted_at'),
therapy.get('is_essential_uploaded', False), therapy.get('essential_uploaded_at')
)

therapist_phone_numbers_dict = dict()
if therapist_ids:
for therapist_profile in therapy_therapist_profile_collection.find(
{
'_id': {"$in": therapist_ids}
},
{
'_id': 1,
'phone_number': 1,
'display_name': 1,
'razorpayx_fund_account_id': 1
}
):
therapist_phone_numbers_dict[str(therapist_profile['_id'])] = {
'phone_number': therapist_profile['phone_number'],
'display_name': therapist_profile['display_name'],
'razorpayx_fund_account_id': therapist_profile.get('razorpayx_fund_account_id')
}

for therapy_booking in therapy_bookings_list:
therapy_booking.update({
'user_phone_number': user_phone_numbers_dict[therapy_booking['user_id']][0],
'web_registration': user_phone_numbers_dict[therapy_booking['user_id']][1],
# 'therapist_name': therapist_phone_numbers_dict[therapist_id]['display_name'],
'user_alternate_contact': user_phone_numbers_dict[therapy_booking['user_id']][2]
})
for therapy in therapy_booking['therapy_bookings']:
for session in therapy['sessions']:
# if session['status'] not in ['INACTIVE'] and session['id'] in therapy_booking_sessions_dict:
if session['id'] in therapy_booking_sessions_dict:
therapist_id, therapist_commission, treatment_accepted, treatment_accepted_at, \
is_essential_uploaded, essential_uploaded_at = \
therapy_booking_sessions_dict[session['id']]
session.update({
'therapist_id': therapist_id,
'therapist_name': therapist_phone_numbers_dict[therapist_id]['display_name'],
'therapist_phone_number': therapist_phone_numbers_dict[therapist_id]['phone_number'],
'razorpayx_fund_account_id': therapist_phone_numbers_dict[therapist_id]['razorpayx_fund_account_id'],
'therapist_commission': therapist_commission,
'session_no': session['session_no']
})

return therapy_bookings_list, therapist_ids


def fix_session_timezone(session):
if session.get('start_qr_token_session_generated_at'):
x = UTC.localize(session['start_qr_token_session_generated_at']).astimezone(IST)
session['start_qr_token_session_generated_at'] = x
if session.get('end_qr_token_session_generated_at'):
x = UTC.localize(session['end_qr_token_session_generated_at']).astimezone(IST)
session['end_qr_token_session_generated_at'] = x
# if session.get('start_qr_token_session_validated_at'):
# x = UTC.localize(session['start_qr_token_session_validated_at']).astimezone(IST)
# session['start_qr_token_session_validated_at'] = x
# if session.get('end_qr_token_session_validated_at'):
# x = UTC.localize(session['end_qr_token_session_validated_at']).astimezone(IST)
# session['end_qr_token_session_validated_at'] = x

if session.get('start_otp_token_session_generated_at'):
x = UTC.localize(session['start_otp_token_session_generated_at']).astimezone(IST)
session['start_otp_token_session_generated_at'] = x
if session.get('end_otp_token_session_generated_at'):
x = UTC.localize(session['end_otp_token_session_generated_at']).astimezone(IST)
session['end_otp_token_session_generated_at'] = x

if session.get('start_otp_token_session_validated_at'):
x = UTC.localize(session['start_otp_token_session_validated_at']).astimezone(IST)
session['start_otp_token_session_validated_at'] = x
if session.get('end_otp_token_session_validated_at'):
x = UTC.localize(session['end_otp_token_session_validated_at']).astimezone(IST)
session['end_otp_token_session_validated_at'] = x


def reprocess_therapy_bookings(therapy_bookings_list, user_phone_numbers_dict,
therapy_booking_sessions_dict, therapist_phone_numbers_dict,
payment_dict, payout_dict, therapist_location_dict,
all_sessions_active_sessions_dict, all_sessions_payment_sessions_dict,
calendar_date=None , start_date=None , end_date=None):
ist_time = get_ist_time()
total_therapies_value_today = 0
for therapy_booking in therapy_bookings_list:
therapy_booking.update({
'user_id': therapy_booking['user_id'],
# 'consultation_booking_id': therapy_booking['consultation_booking_id'],
'user_phone_number': user_phone_numbers_dict[therapy_booking['user_id']][0],
'web_registration': user_phone_numbers_dict[therapy_booking['user_id']][1]
})

for therapy in therapy_booking['therapy_bookings']:
therapy['medicines_uploaded'] = False
try:
therapy_title_preprocessed = THERAPIES_SEO_HEADLINE_MAP[therapy['therapy_title']]
except KeyError:
therapy_title_preprocessed = THERAPIES_SEO_HEADLINE_MAP[
THERAPIES_SEO_FRIENDLY[therapy['therapy_title']]
]
therapy_title = therapy_title_preprocessed + '(' + str(therapy['session_duration_in_min']) + ')'
therapy_category = THERAPY_CATEGORY_DICT[therapy['therapy_title']]
therapy_duration = therapy['session_duration_in_min']
for add_on_therapy in therapy.get('add_on_therapies', []):
try:
add_on_therapy_title_preprocessed = THERAPIES_SEO_HEADLINE_MAP[add_on_therapy['therapy_title']]
except KeyError:
add_on_therapy_title_preprocessed = THERAPIES_SEO_HEADLINE_MAP[
THERAPIES_SEO_FRIENDLY[add_on_therapy['therapy_title']]
]
therapy_title += ' + ' + add_on_therapy_title_preprocessed + \
'(' + str(add_on_therapy['session_duration_in_min']) + ')' # print(type(therapy_duration), type(add_on_therapy['session_duration_in_min']))
therapy_duration += int(add_on_therapy['session_duration_in_min'])
therapy['therapy_title_with_duration'] = therapy_title
therapy['session_duration_in_min'] = therapy_duration
therapy['therapy_category'] = therapy_category
session_details_dict = dict()
session_status_set = set()
total_sessions = therapy['total_sessions']
therapy['is_bed_needed'] = therapy.get('is_bed_needed', 'NO')
therapy['is_steam_needed'] = therapy.get('is_steam_needed', 'NO')
therapy['is_cooker_needed'] = therapy.get('is_cooker_needed', 'NO')
therapy['is_cylinder_needed'] = therapy.get('is_cylinder_needed', 'NO')

booked_at_ts = UTC.localize(
therapy.get('invoice_regenerated_at', therapy.get('booked_at'))
).astimezone(IST)
therapy['booked_at_ts'] = int(booked_at_ts.timestamp())

therapy['invoice_therapist_booking_id'] = None
total_payout_amount = 0

session_medicine_upload_dict = dict()
for session in therapy['sessions']:
session_no = session['session_no']
if session.get('medicine_sent_uploaded'):
session_medicine_upload_dict[session_no] = session.get('medicine_sent_uploaded')

if (session.get('medicine_sent_uploaded') or
(session_no in session_medicine_upload_dict and session_medicine_upload_dict[session_no])):
therapy['medicines_uploaded'] = True
session['medicine_sent_uploaded'] = True

session['clinic_id'] = session.get('clinic_id', DEFAULT_CLINC_ID)
if session['session_no'] == 1 and not therapy['invoice_therapist_booking_id']:
therapy['invoice_therapist_booking_id'] = session['therapist_booking_id']
therapy['therapy_booking_first_session_id'] = session['id']
therapy['invoice_url'] = f'{host}onboarding/api/v1/therapy/booking/' \
f'{therapy["invoice_therapist_booking_id"]}/' \
f'booked-on/{therapy["booked_at_ts"]}/invoice'
session['same_date'] = False
if not session['status'] == 'INACTIVE':
# This logic to get the overall therapy booking status. (Not Session level session status)
session_status_set.add(session['status'])
session_details_dict[session['session_no']] = (
session['scheduled_appointment_start_time'],
session['status']
)

if session['id'] in therapy_booking_sessions_dict:
therapist_id, therapist_commission, treatment_accepted, treatment_accepted_at,\
is_essential_uploaded, essential_uploaded_at = therapy_booking_sessions_dict[session['id']]
if 'start_time' not in therapy_booking:
therapy_booking['start_time'] = session['scheduled_appointment_start_time']
time_delta = (
session['scheduled_appointment_end_time'] - session['scheduled_appointment_start_time'])
total_seconds = time_delta.total_seconds()
duration = round(total_seconds / 60)
payout = payout_dict.get(
session['id'],
[{'payout_amount': 0, 'payout_status': None}]
)
total_payout_amount += sum([p['payout_amount'] for p in payout])
if start_date and end_date:
start_date_obj = datetime.strptime(start_date, '%Y-%m-%d').date()
end_date_obj = datetime.strptime(end_date, '%Y-%m-%d').date()

if start_date_obj <= session['scheduled_appointment_start_time'].date() <= end_date_obj and session['status'] != 'INACTIVE':
therapy['today_therapist_name'] = therapist_phone_numbers_dict[therapist_id]['display_name']
therapy['location'] = therapist_location_dict.get(therapist_id)
session['same_date'] = True
therapy['cur_session_by_total_sessions'] = str(session['session_no']) + ' / ' + str(
therapy['total_sessions'])
else:
therapy['today_therapist_name'] = therapist_phone_numbers_dict[therapist_id]['display_name']
therapy['cur_session_by_total_sessions'] = str(session['session_no']) + ' / ' + str(
therapy['total_sessions'])

else:
if calendar_date \
and str(session['scheduled_appointment_start_time'].date()) == calendar_date \
and not session['status'] == 'INACTIVE':
therapy['today_therapist_name'] = therapist_phone_numbers_dict[therapist_id]['display_name']
therapy['location'] = therapist_location_dict.get(therapist_id)
session['same_date'] = True
therapy['cur_session_by_total_sessions'] = str(session['session_no']) + ' / ' + str(therapy['total_sessions'])
else:
therapy['today_therapist_name'] = therapist_phone_numbers_dict[therapist_id]['display_name']
therapy['cur_session_by_total_sessions'] = str(session['session_no']) + ' / ' + str(therapy['total_sessions'])

therapy['treatment_accepted'] = treatment_accepted
if treatment_accepted_at:
therapy['treatment_accepted_at'] = treatment_accepted_at.astimezone(IST).replace(tzinfo=None)

therapy['is_essential_uploaded'] = is_essential_uploaded
if essential_uploaded_at:
therapy['essential_uploaded_at'] = essential_uploaded_at.astimezone(IST).replace(tzinfo=None)

payment_list = payment_dict.get(all_sessions_payment_sessions_dict[session['id']])
actual_payment_amount = 0
if payment_list:
for payment in payment_list:
actual_payment_amount += payment['payment_amount']

booking_payment_amount = int(float(therapy['total_amount']))
medicine_sent_for_days = therapy.get('medicine_sent_for_days')
if (not medicine_sent_for_days or
(medicine_sent_for_days and session['session_no'] + 1 > medicine_sent_for_days
and session['session_no'] != therapy['total_sessions'])
) and not session['status'] in ['CANCELLED']:
therapy['medicine_sent_days_color'] = 'bg-danger'

if actual_payment_amount >= booking_payment_amount:
payment_status = 'PAID'
therapy['payment_status'] = payment_status
therapy['payment_status_color'] = 'bg-success'
elif 0 < actual_payment_amount < booking_payment_amount:
payment_status = 'PARTIALLY_PAID'
therapy['payment_status'] = payment_status
therapy['payment_status_color'] = 'bg-warning'
else:
payment_status = 'UNPAID'
therapy['payment_status'] = payment_status
if session['status'] not in ['CANCELLED']:
therapy['payment_status_color'] = 'bg-danger'
# therapy_booking['payment_status'] = 'bg-danger border border-danger'

if session['status'] in ['COMPLETED', 'CANCELLED']:
therapy_booking['payment_status'] = 'bg-success h-5 border border-success'

if session['status'] not in ['CANCELLED'] and not therapy['medicines_uploaded']:
therapy_booking['payment_status'] = 'bg-secondary p-3 h-5 border border-danger'

session.update({
'duration': duration,
'therapist_name': therapist_phone_numbers_dict[therapist_id]['display_name'],
'therapist_phone_number': therapist_phone_numbers_dict[therapist_id]['phone_number'],
'therapist_commission': therapist_commission,
'razorpayx_fund_account_id': therapist_phone_numbers_dict[therapist_id][
'razorpayx_fund_account_id'],
'payout_amount': ' + '.join([str(p['payout_amount']) for p in payout]),
'payout_status': ' + '.join([str(p['payout_status']) for p in payout]),
'payment_amount': actual_payment_amount,
'payment_status': payment_status,
'commission_eligible': False,
'treatment_accepted': treatment_accepted,
'treatment_accepted_at': treatment_accepted_at
})

fix_session_timezone(session)
if therapist_commission and therapist_commission >= sum(
p['payout_amount'] for p in payout
if p['payout_status'] and p['payout_status'] not in ['failed', 'rejected',]
):
# To display 'Pay Commission' button
session['commission_eligible'] = True

therapy['total_payout_amount'] = total_payout_amount
if session_details_dict:
''' This IF condition is added because if operation team by mistake changes therapy title to
different one, the update operation in db will fail as db update operation works on therapy title
match also. In that case, the therapy would have been set INACTIVE and there wouldnt be any
new ACTIVE session for it. Due to which all sessions will be inactive and session_Details_dict
will be empty.'''
therapy['therapy_status'], therapy['therapy_messages'], recent_session, last_completed_session = \
get_therapy_status(session_details_dict, total_sessions, session_status_set, ist_time)


def reprocess_therapy_bookings_for_therapist(therapy_bookings_list, payout_dict):
total_therapis_cnt = 0
total_commission = 0
monthly_therapies_cnt = defaultdict(int)
monthly_therapies_cnt_patient_wise = defaultdict(int)
monthly_commission = defaultdict(int)
monthly_commission_patient_wise = defaultdict(int)
for therapy_booking in therapy_bookings_list:
for therapy in therapy_booking['therapy_bookings']:
new_sessions = list()
for session in therapy['sessions']:
if session['status'] in ['COMPLETED']:
if session.get('therapist_phone_number') and session.get('therapist_name'):
month = session['scheduled_appointment_start_time'].month
monthly_therapies_cnt[month] += 1
monthly_therapies_cnt_patient_wise[(therapy['patient_name'], month)] += 1
payout_data = payout_dict.get(session['id'], [])
for payout in payout_data:
monthly_commission[month] += int(payout['payout_amount'])
monthly_commission_patient_wise[(therapy['patient_name'], month)] += int(payout['payout_amount'])
total_commission += int(payout['payout_amount'])
total_therapis_cnt += 1
new_sessions.append(session)
therapy['sessions'] = new_sessions
return monthly_therapies_cnt, monthly_commission, total_therapis_cnt, total_commission


def compute_stats(therapy_bookings_list, therapy_booking_sessions_dict_set=None,
all_sessions_payment_sessions_dict=None, stats_month=None,
stats=False, payout_dict=None, payment_dict=None, patient_name=None):

def compute_payment_amount(session):
payment_list = payment_dict.get(session['id'], [])
payment_session_id = all_sessions_payment_sessions_dict[session['id']]
if stats_month:
payment_amount = sum(
[payment['payment_amount'] if payment['session_id'] == payment_session_id and
payment['payment_date'].month == stats_month else 0
for payment in payment_list
]
) if payment_list else 0
else:
payment_amount = sum(
[payment['payment_amount'] if payment['session_id'] == payment_session_id else 0
for payment in payment_list
]
) if payment_list else 0
return payment_amount

if not therapy_booking_sessions_dict_set:
therapy_booking_sessions_dict_set = set()
if not payout_dict:
payout_dict = dict()
if not payment_dict:
payment_dict = dict()
if not all_sessions_payment_sessions_dict:
all_sessions_payment_sessions_dict = dict()

total_eligible_commission = 0
total_incomplete_commission_due = 0
total_completed_commission_due = 0
total_paid_commission = 0

total_payment_received = 0
clinic_payment_received = 0

therapist_eligible_commission = defaultdict(int)
therapist_paid_commission = defaultdict(int)
therapist_unpaid_commission = defaultdict(int)
patient_incomplete_commission_due_dict = dict()
patient_completed_commission_due_dict = dict()
patient_incomplete_sessions_dict = dict()
patient_paid_amount = defaultdict(int)
therapist_clinic_therapies_cnt = defaultdict(int)
therapist_home_therapies_cnt = defaultdict(int)

total_therapies_cnt = 0
for therapy_booking in therapy_bookings_list:
for therapy in therapy_booking['therapy_bookings']:
if patient_name:
if therapy['patient_name'] != patient_name:
continue
therapy_completed_session_latest = 0
therapy_session_commission_completed_latest = 0
therapy_pending_commission = 0
therapy_pending_sessions = 0
therapy_eligible_commission = 0
therapy_paid_commission = 0
for session in therapy['sessions']:
if payment_dict:
payment_amount = compute_payment_amount(session)
therapy_paid_amount = payment_amount
if payment_amount > 0:
patient_paid_amount[therapy['patient_name']] = payment_amount
total_payment_received += therapy_paid_amount
if session['id'] in therapy_booking_sessions_dict_set:
if session['same_date']:
if not stats and session['status'] not in ['CANCELLED']:
total_therapies_cnt += 1
elif stats:
if session['status'] in ['COMPLETED']:
total_therapies_cnt += 1

if session['status'] in ['COMPLETED']:
therapy_completed_session_latest += 1
payout_list = payout_dict.get(session['id'], [])
payout_amount = sum([payout['payout_amount'] for payout in payout_list]) \
if payout_list else 0
if session.get('therapist_name'):
therapy_session_commission_completed_latest = session['therapist_commission'] or 0
therapy_eligible_commission += session['therapist_commission'] or 0
therapist_home_therapies_cnt[session['therapist_name']] += 1
therapist_eligible_commission[session['therapist_name']] += session['therapist_commission'] or 0
therapist_paid_commission[session['therapist_name']] += payout_amount

total_eligible_commission += round(session.get('therapist_commission', 0) or 0)
total_paid_commission += payout_amount
therapy_paid_commission += payout_amount
therapy_session_commission_latest = ((session.get('therapist_commission') or 0) or
therapy_session_commission_completed_latest)

therapy_pending_sessions = session['total_sessions'] - therapy_completed_session_latest
therapy_pending_commission = therapy_pending_sessions * therapy_session_commission_latest
total_incomplete_commission_due += therapy_pending_commission
patient_incomplete_commission_due_dict[therapy['patient_name']] = therapy_pending_commission
if therapy_eligible_commission - therapy_paid_commission >= 0:
'''Greater than 0 Check. Because, the expired packages will show negative values. Those negative
values are skipped from counting for pending completed commission due to be held in bank account.'''
total_completed_commission_due += therapy_eligible_commission - therapy_paid_commission
patient_completed_commission_due_dict[therapy['patient_name']] = (
therapy_eligible_commission - therapy_paid_commission) \
if therapy_eligible_commission > 0 else 0
patient_incomplete_sessions_dict[therapy['patient_name']] = therapy_pending_sessions

patient_paid_amount = dict(sorted(patient_paid_amount.items(), key=lambda item: item[1], reverse=True))

return (total_therapies_cnt, total_eligible_commission, total_payment_received, patient_paid_amount,
therapist_eligible_commission, therapist_paid_commission, patient_incomplete_commission_due_dict,
patient_completed_commission_due_dict,
patient_incomplete_sessions_dict, total_incomplete_commission_due, total_completed_commission_due,
therapist_clinic_therapies_cnt,
therapist_home_therapies_cnt, clinic_payment_received)


def set_dept_fields(dept):
if dept == 'PHYSIO':
return


def get_active_therapy_booking_session_ids(all_therapy_booking_sessions_ids_dict):
'''
This function is duplicated in Onboarding module also.
Any changes here should be copied there too and vice versa
'''
all_sessions_active_sessions_dict = dict()
all_sessions_payment_sessions_dict = dict()
for therapy_booking_session_id in all_therapy_booking_sessions_ids_dict.keys():
all_sessions_list = all_therapy_booking_sessions_ids_dict[therapy_booking_session_id]
session_no = None
active_therapy_booking_session_id = None
payment_therapy_booking_session_id = None

for session in all_sessions_list:
total_sessions = session['total_sessions']

default_payment_freq = 'ONE_TIME' if total_sessions == 1 else 'PACKAGE'
s_id, s_no, s_status, s_pay_freq = (
session['id'],
session['session_no'],
session['status'],
session.get('payment_frequency', default_payment_freq) or default_payment_freq
)
if s_id == therapy_booking_session_id:
session_no = s_no
break

payment_map_fetched = False
for session in all_sessions_list:
total_sessions = session['total_sessions']
default_payment_freq = 'ONE_TIME' if total_sessions == 1 else 'PACKAGE'
s_id, s_no, s_status, s_pay_freq = (
session['id'],
session['session_no'],
session['status'],
session.get('payment_frequency', default_payment_freq) or default_payment_freq
)
if s_pay_freq == 'PACKAGE' and s_no == 1 and not payment_map_fetched:
# 1st session's therapy_booking_session_id is assumed to be the id of payment.receipt for
# PACKAGE payments. Also, if the first sessions is INACTIVATED due to some reasons and created
# another ACTIVE first session, the oldest session id is picked as the order receipt would have
# been created with oldest session id. payment_map_fetched flag is used to ensure to fetch always
# only the first result
payment_therapy_booking_session_id = s_id
payment_map_fetched = True
elif s_pay_freq == 'ONE_TIME' and s_no == 1 and not payment_map_fetched:
payment_therapy_booking_session_id = s_id
payment_map_fetched = True

if s_no == session_no and s_status not in ['INACTIVE']:
active_therapy_booking_session_id = s_id

all_sessions_active_sessions_dict[therapy_booking_session_id] = active_therapy_booking_session_id
all_sessions_payment_sessions_dict[therapy_booking_session_id] = payment_therapy_booking_session_id

return all_sessions_active_sessions_dict, all_sessions_payment_sessions_dict


def fetch_other_data(all_therapy_booking_sessions_ids_dict, therapist_ids):
all_sessions_active_sessions_dict, all_sessions_payment_sessions_dict = \
get_active_therapy_booking_session_ids(all_therapy_booking_sessions_ids_dict)

payout_dict = defaultdict(list)
payment_dict = defaultdict(list)
payout_amount_int = 0
if all_therapy_booking_sessions_ids_dict:
for order_cursor in payment_orders_collection.find(
{
'orders.receipt': {"$in": list(all_therapy_booking_sessions_ids_dict.keys())}
},
hint=ORDER_RECEIPT_IDX
):
therapy_booking_session_id = None
for order in order_cursor['orders']:
therapy_booking_session_id = order['receipt']
payout_amount = 0
payout_status = None

for payout in order_cursor.get('payouts', []):
if payout.get('amount'):
# no error
payout_amount_int += payout['amount']
payout_amount = int(payout['amount'] / 100)
payout_status = payout['status']
payout_data = {
'payout_amount': payout_amount,
'payout_status': payout_status,
'session_id': payout['notes']['therapy_booking_session_id'],
'payout_date': datetime.fromtimestamp(
payout['created_at']).astimezone(IST),
'payouts_reference_id': payout['reference_id']
}
if payout.get('processed_at'):
payout_data.update({
'payout_processed_date': UTC.localize(payout['processed_at']).astimezone(IST)
})
elif payout.get('rejected_at'):
payout_data.update({
'payout_processed_date': UTC.localize(payout['rejected_at']).astimezone(IST)
})
if payout['notes'].get('therapist_name'):
payout_data.update({
'therapist_name': payout['notes']['therapist_name'],
'agent_name': payout['notes'].get('agent_name')
})
payout_dict[payout['notes']['therapy_booking_session_id']].append(
payout_data
)

for payment in order_cursor.get('payments', []):
for payment_item in payment.get('items', []):
payment_amount = int(payment_item['amount'] / 100)
payment_status = payment_item.get('status')
payment_dict[all_sessions_payment_sessions_dict[therapy_booking_session_id]].append(
{
'payment_amount': payment_amount,
'payment_status': payment_status,
'payment_currency': payment_item['currency'],
'payment_mode': payment_item.get('notes').get('payment_mode'),
'session_id': payment_item['notes']['therapy_booking_id'],
'payment_date': datetime.fromtimestamp(
payment_item['created_at'])
}
)

therapist_location_dict = dict()
if therapist_ids:
for therapist in one_therapist_one_location_collection.find(
{
'_id': {"$in": therapist_ids}
}
):
location = therapist['location']
therapist_location_dict[str(therapist['_id'])] = \
f'<a href="https://www.google.com/maps/search/?api=1&query=' \
f'{str(location["latitude"])},{str(location["longitude"])}" target="_blank">{location["street"]},' \
f'{location["sub_locality"]},{location["locality"]}\n' \
f'{UTC.localize(therapist["inserted_at"]).astimezone(IST).strftime("%d %b, %H:%S")}</a>'

return all_sessions_active_sessions_dict, all_sessions_payment_sessions_dict, \
payment_dict, payout_dict, therapist_location_dict


def get_therapy_bookings_by_date(calendar_date, eligible_records=None, user=None):
therapy_booking_sessions_dict = dict()
all_therapy_booking_sessions_ids_dict = dict()

date = calendar_date
if not date:
date = datetime.today().strftime('%Y-%m-%d')

therapist_ids = list()
therapy_booking_ids_list = list()

if user and user.clinic_id:
clinic_id = user.clinic_id
find_query = {'date': date, 'therapies.clinic_id': clinic_id}
else:
clinic_id = None
if user.is_staff:
find_query = {'date': date}
else:
return 'Invalid User'

for booking in therapy_bookings_collection.find(
find_query,
hint=DATE_IDX
):
therapist_ids.append(ObjectId(booking['therapist_id']))
for therapy in booking.get('therapies', []):
if not user.is_staff:
if clinic_id and therapy.get('clinic_id') != clinic_id:
continue
if therapy.get('status', 'ACTIVE') in ['ACTIVE', 'CANCELLED']:
therapy_booking_ids_list.append(therapy['booking_id'])
therapy_booking_sessions_dict[therapy['therapy_booking_session_id']] = \
(booking['therapist_id'], therapy.get('therapist_commission', 0),
therapy.get('treatment_accepted', False), therapy.get('treatment_accepted_at'),
therapy.get('is_essential_uploaded', False), therapy.get('essential_uploaded_at')
)

user_ids = list()
therapy_bookings_list = list()
if therapy_booking_sessions_dict:
for user_therapy_booking in user_therapy_bookings_collection.find(
{
'therapy_bookings.sessions.id': {
"$in": list(therapy_booking_sessions_dict.keys())
}
},
hint=THERAPY_BOOKING_SESSION_ID_IDX
):
user_ids.append(ObjectId(user_therapy_booking['user_id']))
for booking in user_therapy_booking['therapy_bookings']:
therapy_category = THERAPY_CATEGORY_DICT[booking['therapy_title']]
record = {
'id': user_therapy_booking['_id'],
'user_id': user_therapy_booking['user_id'],
'consultation_booking_id': user_therapy_booking['consultation_booking_id'],
'therapy_bookings': user_therapy_booking['therapy_bookings']
}

if eligible_records in ['Ayurveda', 'Physio']:
if therapy_category == eligible_records:
therapy_bookings_list.append(record)
else:
therapy_bookings_list.append(record)

total_booking_sessions_count = len(booking['sessions'])
session_no_completed_idx_dict = dict()
for idx, session in enumerate(booking['sessions']):
session['total_sessions'] = booking['total_sessions']
all_therapy_booking_sessions_ids_dict[session['id']] = booking['sessions']
session['can_be_cloned'] = True
session['can_be_duplicated'] = True
session_no_completed_idx_dict[session['session_no']] = idx

if (idx + 1 < total_booking_sessions_count
and booking['sessions'][idx + 1]['status'] in ['COMPLETED', 'UPCOMING', 'INACTIVE']) \
or session['session_no'] == booking['total_sessions']\
or session['status'] == 'UPCOMING':
session['can_be_cloned'] = False

if booking['sessions'][idx]['status'] == 'CANCELLED':
'''To enable clone button on previous session if current session is CANCELLED'''
if session['session_no'] - 1 > 0: # this is added expecting to skip single session bookings. To be tested/
booking['sessions'][
session_no_completed_idx_dict[session['session_no'] - 1]
]['can_be_cloned'] = True

''' This condition is to not show duplicate in ongoing package sessions.
This also ensures to show duplicate when session is 1/N and if in CANCELLED state.'''
if (
idx+1 < total_booking_sessions_count and
booking['sessions'][idx+1]['status'] in ['COMPLETED', 'UPCOMING', 'INACTIVE']
) or (
session['session_no'] != booking['total_sessions']
and not (session['session_no'] == 1 and session['status'] in ['CANCELLED'])
):
session['can_be_duplicated'] = False

user_phone_numbers_dict = dict()
if user_ids:
for user_profile in user_profile_collection.find(
{
'_id': {"$in": user_ids}
},
{
'_id': 1,
'phone_number': 1,
'is_web_registration': 1
}
):
user_phone_numbers_dict[str(user_profile['_id'])] = (
user_profile['phone_number'], user_profile.get('is_web_registration')
)

therapist_phone_numbers_dict = dict()
if therapist_ids:
for therapist_profile in therapy_therapist_profile_collection.find(
{
'_id': {"$in": therapist_ids}
},
{
'_id': 1,
'phone_number': 1,
'display_name': 1,
'razorpayx_fund_account_id': 1
}
):
therapist_phone_numbers_dict[str(therapist_profile['_id'])] = {
'phone_number': therapist_profile['phone_number'],
'display_name': therapist_profile['display_name'],
'razorpayx_fund_account_id': therapist_profile.get('razorpayx_fund_account_id')
}

all_sessions_active_sessions_dict, all_sessions_payment_sessions_dict, \
payment_dict, payout_dict, therapist_location_dict = fetch_other_data(
all_therapy_booking_sessions_ids_dict, therapist_ids
)

therapy_bookings_sessions_dict_list = list(therapy_booking_sessions_dict.keys())
reprocess_therapy_bookings(therapy_bookings_list, user_phone_numbers_dict,
therapy_booking_sessions_dict, therapist_phone_numbers_dict,
payment_dict, payout_dict, therapist_location_dict,
all_sessions_active_sessions_dict, all_sessions_payment_sessions_dict,
calendar_date)

total_therapies, total_eligible_commission, total_payment_received, patient_paid_amount, \
therapist_commission, _, _, _, _, _, _, therapist_clinic_therapies_cnt, therapist_home_therapies_cnt, \
clinic_payment_received = \
compute_stats(therapy_bookings_list, set(therapy_bookings_sessions_dict_list))

return sorted(therapy_bookings_list, key=lambda x: x['start_time']), \
total_therapies, total_eligible_commission, total_payment_received, \
therapist_commission, therapist_clinic_therapies_cnt, therapist_home_therapies_cnt, \
clinic_payment_received


def get_therapy_bookings_by_daterange(start_date=None, end_date=None, eligible_records=None, user=None):
therapy_booking_sessions_dict = dict()
all_therapy_booking_sessions_ids_dict = dict()

# Handle date / range
if start_date and end_date:
loop_dates = []
delta = timedelta(days=1)

curr_date = datetime.strptime(start_date, '%Y-%m-%d').date()
end_date_obj = datetime.strptime(end_date, '%Y-%m-%d').date()

while curr_date <= end_date_obj:
loop_dates.append(curr_date.isoformat())
curr_date += delta

date_filter = {"date": {"$in": loop_dates}}
else:
date = start_date or datetime.today().strftime('%Y-%m-%d')
date_filter = {"date": date}

therapist_ids = list()
therapy_booking_ids_list = list()

# Build query
if user and user.clinic_id:
clinic_id = user.clinic_id
find_query = {**date_filter, 'therapies.clinic_id': clinic_id}
else:
clinic_id = None
if user.is_staff:
find_query = date_filter
else:
return 'Invalid User'

for booking in therapy_bookings_collection.find(find_query, hint=DATE_IDX):
therapist_ids.append(ObjectId(booking['therapist_id']))

for therapy in booking.get('therapies', []):
if not user.is_staff:
if clinic_id and therapy.get('clinic_id') != clinic_id:
continue

if therapy.get('status', 'ACTIVE') in ['ACTIVE', 'CANCELLED']:
therapy_booking_ids_list.append(therapy['booking_id'])

therapy_booking_sessions_dict[therapy['therapy_booking_session_id']] = (
booking['therapist_id'],
therapy.get('therapist_commission', 0),
therapy.get('treatment_accepted', False),
therapy.get('treatment_accepted_at'),
therapy.get('is_essential_uploaded', False),
therapy.get('essential_uploaded_at')
)

user_ids = list()
therapy_bookings_list = list()

# Fetch user bookings
if therapy_booking_sessions_dict:
for user_therapy_booking in user_therapy_bookings_collection.find(
{
'therapy_bookings.sessions.id': {
"$in": list(therapy_booking_sessions_dict.keys())
}
},
hint=THERAPY_BOOKING_SESSION_ID_IDX
):
user_ids.append(ObjectId(user_therapy_booking['user_id']))

record = {
'id': user_therapy_booking['_id'],
'user_id': user_therapy_booking['user_id'],
'consultation_booking_id': user_therapy_booking['consultation_booking_id'],
'therapy_bookings': user_therapy_booking['therapy_bookings']
}

therapy_bookings_list.append(record)

for booking in user_therapy_booking['therapy_bookings']:
total_booking_sessions_count = len(booking['sessions'])
session_no_completed_idx_dict = dict()

for idx, session in enumerate(booking['sessions']):
session['total_sessions'] = booking['total_sessions']
all_therapy_booking_sessions_ids_dict[session['id']] = [session]

session['can_be_cloned'] = True
session['can_be_duplicated'] = True

session_no_completed_idx_dict[session['session_no']] = idx

if (
(idx + 1 < total_booking_sessions_count and
booking['sessions'][idx + 1]['status'] in ['COMPLETED', 'UPCOMING', 'INACTIVE'])
or session['session_no'] == booking['total_sessions']
or session['status'] == 'UPCOMING'
):
session['can_be_cloned'] = False

if booking['sessions'][idx]['status'] == 'CANCELLED':
if session['session_no'] - 1 > 0:
booking['sessions'][
session_no_completed_idx_dict[session['session_no'] - 1]
]['can_be_cloned'] = True

if (
idx + 1 < total_booking_sessions_count and
booking['sessions'][idx + 1]['status'] in ['COMPLETED', 'UPCOMING', 'INACTIVE']
) or (
session['session_no'] != booking['total_sessions']
and not (session['session_no'] == 1 and session['status'] in ['CANCELLED'])
):
session['can_be_duplicated'] = False

# User phone numbers
user_phone_numbers_dict = dict()
if user_ids:
for user_profile in user_profile_collection.find(
{'_id': {"$in": user_ids}},
{'_id': 1, 'phone_number': 1, 'is_web_registration': 1}
):
user_phone_numbers_dict[str(user_profile['_id'])] = (
user_profile['phone_number'],
user_profile.get('is_web_registration')
)

# Therapist details
therapist_phone_numbers_dict = dict()
if therapist_ids:
for therapist_profile in therapy_therapist_profile_collection.find(
{'_id': {"$in": therapist_ids}},
{'_id': 1, 'phone_number': 1, 'display_name': 1, 'razorpayx_fund_account_id': 1}
):
therapist_phone_numbers_dict[str(therapist_profile['_id'])] = {
'phone_number': therapist_profile['phone_number'],
'display_name': therapist_profile['display_name'],
'razorpayx_fund_account_id': therapist_profile.get('razorpayx_fund_account_id')
}

# Other data
all_sessions_active_sessions_dict, all_sessions_payment_sessions_dict, \
payment_dict, payout_dict, therapist_location_dict = fetch_other_data(
all_therapy_booking_sessions_ids_dict, therapist_ids
)

therapy_bookings_sessions_dict_list = list(therapy_booking_sessions_dict.keys())


reprocess_therapy_bookings(
therapy_bookings_list,
user_phone_numbers_dict,
therapy_booking_sessions_dict,
therapist_phone_numbers_dict,
payment_dict,
payout_dict,
therapist_location_dict,
all_sessions_active_sessions_dict,
all_sessions_payment_sessions_dict,
calendar_date=None,
start_date=start_date,
end_date=end_date
)

total_therapies, total_eligible_commission, total_payment_received, patient_paid_amount, \
therapist_commission, _, _, _, _, _, _, therapist_clinic_therapies_cnt, therapist_home_therapies_cnt, \
clinic_payment_received = compute_stats(
therapy_bookings_list,
set(therapy_bookings_sessions_dict_list)
)

return sorted(therapy_bookings_list, key=lambda x: x['start_time']), \
total_therapies, total_eligible_commission, total_payment_received, \
therapist_commission, therapist_clinic_therapies_cnt, therapist_home_therapies_cnt, \
clinic_payment_received


def get_therapy_bookings_by_phone_number(filter, user):
all_therapy_booking_sessions_ids_dict = dict()
if user and user.clinic_id:
clinic_id = user.clinic_id
else:
clinic_id = None
if not user.is_staff:
return 'Invalid User'

if filter.isnumeric():
find_query = {
'phone_number': "+91" + filter
}
elif filter[1:].isnumeric():
find_query = {
'phone_number': filter
}
else:
find_query = {
"booking_profiles.booking_for_name": {
"$regex": filter,
"$options": 'i'
}
}

therapy_booking_sessions_dict = dict()

user_phone_numbers_dict = dict()
for user_profile in user_profile_collection.find(
find_query,
{
'_id': 1,
'phone_number': 1,
'is_web_registration': 1,
'login_method': 1
}
):
if not user.is_staff:
if clinic_id and user_profile.get('clinics_availed'):
for clinic in user_profile['clinics_availed']:
if clinic != clinic_id:
continue
user_phone_numbers_dict[str(user_profile['_id'])] = (
user_profile['phone_number'], user_profile.get('is_web_registration'), user_profile.get('login_method')
)

therapy_bookings_list = list()
therapy_booking_ids_list = list()

if user and user.clinic_id:
clinic_id = user.clinic_id
find_query = {
'user_id': {"$in": list(user_phone_numbers_dict.keys())},
'therapy_bookings.sessions.clinic_id': clinic_id
}
else:
find_query = {'user_id': {"$in": list(user_phone_numbers_dict.keys())}}

for user_therapy_booking in user_therapy_bookings_collection.find(
find_query
):
therapy_bookings_list.append(
{
'id': user_therapy_booking['_id'],
'user_id': user_therapy_booking['user_id'],
'consultation_booking_id': user_therapy_booking['consultation_booking_id'],
'therapy_bookings': user_therapy_booking['therapy_bookings']
}
)
for therapy_booking in user_therapy_booking['therapy_bookings']:
for session in therapy_booking['sessions']:
if not user.is_staff:
if clinic_id and session.get('clinic_id') and session['clinic_id'] != clinic_id:
continue
session['total_sessions'] = therapy_booking['total_sessions']
therapy_booking_ids_list.append(session['therapist_booking_id'])
all_therapy_booking_sessions_ids_dict[session['id']] = therapy_booking['sessions']

therapist_ids = list()
for booking in therapy_bookings_collection.find(
{
'therapies.booking_id': {
"$in": therapy_booking_ids_list
}
},
hint=THERAPY_BOOKING_ID_IDX
):
therapist_ids.append(ObjectId(booking['therapist_id']))
for therapy in booking.get('therapies', []):
if not user.is_staff:
if clinic_id and therapy.get('clinic_id') != clinic_id:
continue
therapy_booking_sessions_dict[therapy['therapy_booking_session_id']] = \
(booking['therapist_id'], therapy.get('therapist_commission', 0),
therapy.get('treatment_accepted', False), therapy.get('treatment_accepted_at'),
therapy.get('is_essential_uploaded', False), therapy.get('essential_uploaded_at'))

therapist_phone_numbers_dict = dict()
for therapist_profile in therapy_therapist_profile_collection.find(
{
'_id': {"$in": therapist_ids}
},
{
'_id': 1,
'phone_number': 1,
'display_name': 1,
'razorpayx_fund_account_id': 1
}
):
therapist_phone_numbers_dict[str(therapist_profile['_id'])] = {
'phone_number': therapist_profile['phone_number'],
'display_name': therapist_profile['display_name'],
'razorpayx_fund_account_id': therapist_profile.get('razorpayx_fund_account_id')
}

if not therapist_ids and not therapy_booking_sessions_dict:
therapy_bookings_list = list()

all_sessions_active_sessions_dict, all_sessions_payment_sessions_dict, \
payment_dict, payout_dict, therapist_location_dict = fetch_other_data(
all_therapy_booking_sessions_ids_dict, therapist_ids
)

reprocess_therapy_bookings(therapy_bookings_list, user_phone_numbers_dict,
therapy_booking_sessions_dict, therapist_phone_numbers_dict,
payment_dict, payout_dict, therapist_location_dict,
all_sessions_active_sessions_dict, all_sessions_payment_sessions_dict,
)
total_therapies, total_eligible_commission, total_payment_received, patient_paid_amount, \
therapist_commission, _, _, _, _, _, _, therapist_clinic_therapies_cnt, therapist_home_therapies_cnt, \
clinic_payment_received = \
compute_stats(therapy_bookings_list)
return therapy_bookings_list, \
total_therapies, total_eligible_commission, total_payment_received, therapist_commission, \
therapist_clinic_therapies_cnt, therapist_home_therapies_cnt, clinic_payment_received


def get_therapy_bookings_by_therapist_phone_number(filter, user):
all_therapy_booking_sessions_ids_dict = dict()

if filter.isnumeric():
find_query = {
'phone_number': "+91" + filter
}
else:
find_query = {
"display_name": {
"$regex": filter,
"$options": 'i'
}
}

if user and user.clinic_id:
clinic_id = user.clinic_id
find_query.update({
'clinics_associated.clinic_id': clinic_id
})
else:
clinic_id = None
if not user.is_staff:
return 'Invalid User'

therapy_booking_sessions_dict = dict()
therapist_ids = list()
therapist_phone_numbers_dict = dict()
for therapist_profile in therapy_therapist_profile_collection.find(
find_query,
{
'_id': 1,
'phone_number': 1,
'display_name': 1,
'razorpayx_fund_account_id': 1
}
):
therapist_ids.append(str(therapist_profile['_id']))
therapist_phone_numbers_dict[str(therapist_profile['_id'])] = {
'phone_number': therapist_profile['phone_number'],
'display_name': therapist_profile['display_name'],
'razorpayx_fund_account_id': therapist_profile.get('razorpayx_fund_account_id')
}

today_date = datetime.today()
# HISTORY_PAST= 31
HISTORY_PAST = 1000
last_30_days = today_date + timedelta(days=-HISTORY_PAST)
fifth_date = None
loop_date = last_30_days
while not fifth_date:
if loop_date.date().strftime('%d') == '01':
fifth_date = loop_date.date()
break
else:
loop_date = loop_date + timedelta(days=1)

loop_dates = [(fifth_date + timedelta(days=x)).strftime('%Y-%m-%d') for x in range(HISTORY_PAST+1) if
fifth_date + timedelta(days=x) <= today_date.date()]

for booking in therapy_bookings_collection.find(
{
'therapist_id': {
"$in": list(therapist_phone_numbers_dict.keys())
},
"date": {
"$in": loop_dates
}
},
hint=DATE_IDX
):
for therapy in booking.get('therapies', []):
if not user.is_staff:
if clinic_id and therapy.get('clinic_id') != clinic_id:
continue
if therapy.get('status') and therapy['status'] in ['ACTIVE']:
therapy_booking_sessions_dict[therapy['therapy_booking_session_id']] = \
(booking['therapist_id'], therapy.get('therapist_commission', 0),
therapy.get('treatment_accepted', False), therapy.get('treatment_accepted_at'),
therapy.get('is_essential_uploaded', False), therapy.get('essential_uploaded_at'))

therapy_bookings_list = list()
therapy_booking_ids_list = list()
user_ids = list()
therapy_bookings_sessions_dict_list = list(therapy_booking_sessions_dict.keys())
for user_therapy_booking in user_therapy_bookings_collection.find(
{
'therapy_bookings.sessions.id': {
"$in": therapy_bookings_sessions_dict_list
}
},
hint=THERAPY_BOOKING_SESSION_ID_IDX
):
user_ids.append(ObjectId(user_therapy_booking['user_id']))
therapy_bookings_list.append(
{
'id': user_therapy_booking['_id'],
'user_id': user_therapy_booking['user_id'],
'consultation_booking_id': user_therapy_booking['consultation_booking_id'],
'therapy_bookings': user_therapy_booking['therapy_bookings']
}
)
for therapy_booking in user_therapy_booking['therapy_bookings']:
for session in therapy_booking['sessions']:
#if session['status'] not in ['INACTIVE', 'CANCELLED']:
session['total_sessions'] = therapy_booking['total_sessions']
therapy_booking_ids_list.append(session['therapist_booking_id'])
all_therapy_booking_sessions_ids_dict[session['id']] = therapy_booking['sessions']

user_phone_numbers_dict = dict()
for user_profile in user_profile_collection.find(
{
"_id": {
"$in": user_ids
}
},
{
'_id': 1,
'phone_number': 1,
'is_web_registration': 1,
'login_method': 1
}
):
user_phone_numbers_dict[str(user_profile['_id'])] = (
user_profile['phone_number'], user_profile.get('is_web_registration'), user_profile.get('login_method')
)

all_sessions_active_sessions_dict, all_sessions_payment_sessions_dict, \
payment_dict, payout_dict, therapist_location_dict = fetch_other_data(
all_therapy_booking_sessions_ids_dict, therapist_ids
)

reprocess_therapy_bookings(therapy_bookings_list, user_phone_numbers_dict,
therapy_booking_sessions_dict, therapist_phone_numbers_dict,
payment_dict, payout_dict, therapist_location_dict,
all_sessions_active_sessions_dict, all_sessions_payment_sessions_dict,
)
monthly_therapies_cnt, monthly_commission, total_therapies_cnt, total_commission = (
reprocess_therapy_bookings_for_therapist(therapy_bookings_list, payout_dict))
return (sorted(therapy_bookings_list, key=lambda x: x['start_time']),
monthly_therapies_cnt, monthly_commission, total_therapies_cnt, total_commission)


def get_therapy_booking_stats(stats_date, user, compute_three_months=False, query_filter=None):
all_therapy_booking_sessions_ids_dict = dict()

therapy_booking_sessions_dict = dict()
therapist_ids = list()
therapist_phone_numbers_dict = dict()

if user and user.clinic_id:
clinic_id = user.clinic_id
else:
clinic_id = None
if not user.is_staff:
return 'Invalid User'

# today_date = datetime.today()
# last_30_days = today_date + timedelta(days=-31)
# first_date = None
# loop_date = last_30_days
# while not first_date:
# if loop_date.date().strftime('%d') == '01':
# first_date = loop_date.date()
# break
# else:
# loop_date = loop_date + timedelta(days=1)
#
# loop_dates = [(first_date + timedelta(days=x)).strftime('%Y-%m-%d') for x in range(32) if
# first_date + timedelta(days=x) <= today_date.date()]

loop_dates = []
if not compute_three_months:
stats_date_upd = datetime.strptime(stats_date, '%Y-%m-%d')
_, num_of_days = calendar.monthrange(stats_date_upd.year, stats_date_upd.month)
first_day_of_month = stats_date_upd.replace(day=1).date()
last_day_of_month = datetime(stats_date_upd.year, stats_date_upd.month, num_of_days).date()
stats_month = first_day_of_month.month
else:
stats_month = None
first_day_of_month = datetime.today().date() + timedelta(days=-90)
last_day_of_month = datetime.today().date()

delta = timedelta(days=1)
while first_day_of_month <= last_day_of_month:
loop_dates.append(first_day_of_month.isoformat())
first_day_of_month += delta

for booking in therapy_bookings_collection.find(
{
"date": {
"$in": loop_dates
}
}
):
for therapy in booking.get('therapies', []):
if not user.is_staff:
if clinic_id and therapy.get('clinic_id') != clinic_id:
continue
therapist_ids.append(ObjectId(booking['therapist_id']))
if therapy.get('status') and therapy['status'] in ['ACTIVE']:
therapy_booking_sessions_dict[therapy['therapy_booking_session_id']] = \
(booking['therapist_id'], therapy.get('therapist_commission', 0),
therapy.get('treatment_accepted', False), therapy.get('treatment_accepted_at'),
therapy.get('is_essential_uploaded', False), therapy.get('essential_uploaded_at')
)

for therapist_profile in therapy_therapist_profile_collection.find(
{
'_id': {
"$in": therapist_ids
}
},
{
'_id': 1,
'phone_number': 1,
'display_name': 1,
'razorpayx_fund_account_id': 1
}
):
therapist_ids.append(str(therapist_profile['_id']))
therapist_phone_numbers_dict[str(therapist_profile['_id'])] = {
'phone_number': therapist_profile['phone_number'],
'display_name': therapist_profile['display_name'],
'razorpayx_fund_account_id': therapist_profile.get('razorpayx_fund_account_id')
}

therapy_bookings_list = list()
therapy_booking_ids_list = list()
user_ids = list()
therapy_bookings_sessions_dict_list = list(therapy_booking_sessions_dict.keys())
for user_therapy_booking in user_therapy_bookings_collection.find(
{
'therapy_bookings.sessions.id': {
"$in": therapy_bookings_sessions_dict_list
}
},
hint=THERAPY_BOOKING_SESSION_ID_IDX
):
user_ids.append(ObjectId(user_therapy_booking['user_id']))
therapy_bookings_list.append(
{
'id': user_therapy_booking['_id'],
'user_id': user_therapy_booking['user_id'],
'consultation_booking_id': user_therapy_booking['consultation_booking_id'],
'therapy_bookings': user_therapy_booking['therapy_bookings']
}
)
for therapy_booking in user_therapy_booking['therapy_bookings']:
for session in therapy_booking['sessions']:
# if session['status'] not in ['INACTIVE', 'CANCELLED']:
session['total_sessions'] = therapy_booking['total_sessions']
therapy_booking_ids_list.append(session['therapist_booking_id'])
all_therapy_booking_sessions_ids_dict[session['id']] = therapy_booking['sessions']

user_phone_numbers_dict = dict()
for user_profile in user_profile_collection.find(
{
"_id": {
"$in": user_ids
}
},
{
'_id': 1,
'phone_number': 1,
'is_web_registration': 1,
'login_method': 1
}
):
user_phone_numbers_dict[str(user_profile['_id'])] = (
user_profile['phone_number'], user_profile.get('is_web_registration'), user_profile.get('login_method')
)

all_sessions_active_sessions_dict, all_sessions_payment_sessions_dict, \
payment_dict, payout_dict, therapist_location_dict = fetch_other_data(
all_therapy_booking_sessions_ids_dict, therapist_ids
)

reprocess_therapy_bookings(therapy_bookings_list, user_phone_numbers_dict,
therapy_booking_sessions_dict, therapist_phone_numbers_dict,
payment_dict, payout_dict, therapist_location_dict,
all_sessions_active_sessions_dict, all_sessions_payment_sessions_dict,
)
(total_therapies, total_eligible_commission, total_payment_received, patient_paid_amount,
therapist_commission, therapist_paid_commission, patient_incomplete_commission_due_dict,
patient_completed_commission_due_dict,
patient_incomplete_sessions_dict, total_incomplete_commission_due, total_completed_commission_due, therapist_clinic_therapies_cnt,
therapist_home_therapies_cnt, clinic_payment_received) = \
compute_stats(therapy_bookings_list, set(therapy_bookings_sessions_dict_list),
all_sessions_payment_sessions_dict, stats_month=stats_month,
stats=True, payout_dict=payout_dict, payment_dict=payment_dict,
patient_name=query_filter)
return (sorted(therapy_bookings_list, key=lambda x: x['start_time']),
total_therapies, total_eligible_commission, total_payment_received, patient_paid_amount,
therapist_commission, therapist_paid_commission, patient_incomplete_sessions_dict,
patient_incomplete_commission_due_dict, patient_completed_commission_due_dict,
total_incomplete_commission_due, total_completed_commission_due,
therapist_clinic_therapies_cnt, therapist_home_therapies_cnt,
clinic_payment_received)


class TherapyBookings(AyurshUserMixin, generic.View):
login_url = "accounts:signin"

def get(self, request, *args, **kwargs):
result_dict = dict()
query_date = request.GET.get('dateFilter')
query_filter = request.GET.get('phoneNumberFilter')
therapist_query_filter = request.GET.get('therapistphoneNumberFilter')
query_therapy_booking_session_id = request.GET.get('therapyBookingSessionId')
stats = request.GET.get('stats') == 'true'
stats_date = request.GET.get('date_filter')

eligible_records, dept_record = get_eligible_records(request.user.get_username())
unpack_error = None
therapy_bookings_list = list()
if query_filter and not stats:
therapy_bookings_by_phone_number = get_therapy_bookings_by_phone_number(query_filter, user=request.user)
try:
therapy_bookings_list, total_therapies, total_commission, total_payment_received, therapist_commission, \
therapist_clinic_therapies_cnt, therapist_home_therapies_cnt, \
clinic_payment_received = therapy_bookings_by_phone_number
result_dict.update({'phone_number': query_filter,
'total_therapies': total_therapies,
'total_commission': total_commission,
'total_payment_received': total_payment_received,
'therapist_clinic_therapies_cnt': dict(therapist_clinic_therapies_cnt),
'therapist_home_therapies_cnt': dict(therapist_home_therapies_cnt),
'clinic_payment_received': f"{clinic_payment_received:,}",
'home_payment_received': f"{total_payment_received - clinic_payment_received:,}"
})
except ValueError:
unpack_error = therapy_bookings_by_phone_number

elif therapist_query_filter and not stats:
(therapy_bookings_list, monthly_therapies_cnt, monthly_commission,
total_therapies_cnt, total_commission) = (
get_therapy_bookings_by_therapist_phone_number(therapist_query_filter, user=request.user)
)
updated_therapies_cnt = dict()
updated_monthly_commission = dict()
updated_monthly_commission_eligible = dict()
for key, value in sorted(monthly_therapies_cnt.items()):
updated_therapies_cnt[calendar.month_name[key]] = value
for key, value in sorted(monthly_commission.items()):
updated_monthly_commission[calendar.month_name[key]] = value

result_dict.update(
{
'therapist_phone_number': therapist_query_filter,
'monthly_therapies_cnt': updated_therapies_cnt,
'monthly_commission': updated_monthly_commission,
'total_therapies_cnt': total_therapies_cnt,
'total_commission': total_commission
}
)
elif query_therapy_booking_session_id:
therapy_bookings_list, _ = get_therapy_bookings_by_session_id(query_therapy_booking_session_id, user=request.user)
result_dict.update({'therapy_booking_session_id': query_therapy_booking_session_id})
elif stats:
patient_name = query_filter
(therapy_bookings_list, total_therapies, total_eligible_commission,
total_payment_received, patient_paid_amount, therapist_commission, therapist_paid_commission,
_, _,
_, total_incomplete_commission_due, _,
therapist_clinic_therapies_cnt, therapist_home_therapies_cnt, clinic_payment_received) = \
get_therapy_booking_stats(stats_date, request.user, query_filter=patient_name)

(_, _, _, _, _, _, _, patient_incomplete_sessions_dict, patient_incomplete_commission_due_dict,
patient_completed_commission_due_dict, _, total_completed_commission_due, _, _, _) = \
get_therapy_booking_stats(stats_date, request.user,
compute_three_months=True, query_filter=patient_name)

therapist_commission = dict(sorted(therapist_commission.items(),
key=lambda item: item[1], reverse=True))
result_dict.update({'total_therapies': total_therapies,
'total_eligible_commission': f"{total_eligible_commission:,}",
'total_payment_received': f"{total_payment_received:,}",
'dept_record': dept_record,
'therapist_commission': dict(therapist_commission),
'therapist_paid_commission': dict(therapist_paid_commission),
'patient_incomplete_commission_due_dict': dict(sorted(patient_incomplete_commission_due_dict.items(),
key=lambda item: item[1], reverse=True)),
'patient_completed_commission_due_dict': patient_completed_commission_due_dict,
'patient_incomplete_sessions_dict': patient_incomplete_sessions_dict,
'patient_paid_amount': patient_paid_amount,
'total_incomplete_commission_due': total_incomplete_commission_due,
'total_completed_commission_due': total_completed_commission_due,
'therapist_clinic_therapies_cnt': dict(therapist_clinic_therapies_cnt),
'therapist_home_therapies_cnt': dict(therapist_home_therapies_cnt),
'clinic_payment_received': f"{clinic_payment_received:,}",
'home_payment_received': f"{total_payment_received - clinic_payment_received:,}",
'stats': True
})

else:
if query_date:
# date_filter = datetime.strptime(query_date, '%m/%d/%Y').strftime('%Y-%m-%d')
date_filter = query_date
else:
date_filter = datetime.today().strftime('%Y-%m-%d')

therapy_bookings_by_date = get_therapy_bookings_by_date(date_filter, eligible_records, user=request.user)
try:
therapy_bookings_list, total_therapies, total_commission, \
total_payment_received, therapist_commission, therapist_clinic_therapies_cnt, \
therapist_home_therapies_cnt, clinic_payment_received = therapy_bookings_by_date
result_dict.update({'date': date_filter,
'total_therapies': total_therapies,
'total_commission': f"{total_commission:,}",
'total_payment_received': f"{total_payment_received:,}",
'dept_record': dept_record,
'therapist_commission': dict(therapist_commission),
'therapist_clinic_therapies_cnt': dict(therapist_clinic_therapies_cnt),
'therapist_home_therapies_cnt': dict(therapist_home_therapies_cnt),
'clinic_payment_received': f"{clinic_payment_received:,}",
'home_payment_received': f"{total_payment_received - clinic_payment_received:,}"
})
except ValueError:
unpack_error = therapy_bookings_by_date

result_dict.update(
{'therapy_bookings_list': therapy_bookings_list,
'dept_record': dept_record,
'superuser': self.request.user.is_superuser,
'clinic_choices': CLINIC_CHOICES}
)
if unpack_error:
result_dict.update({'errors': unpack_error})

# csv_headers = ['therapy_title', 'therapy_selection_choices', 'total_sessions', 'session_duration_in_min',
# 'booked_at', 'amount_payable', 'membership_discount', 'total_amount',
# 'address_flat_no_building', 'address_area_locality', 'address_landmark', 'address_city',
# 'patient_name', 'patient_age', 'patient_gender', 'add_on_therapies', 'sessions',
# 'payment_frequency', 'therapy_title_with_duration', 'therapy_category', 'is_bed_needed',
# 'is_steam_needed', 'is_cooker_needed', 'is_cylinder_needed', 'today_therapist_name',
# 'cur_session_by_total_sessions', 'treatment_accepted', 'payment_status', 'payment_status_color',
# 'therapy_status', 'therapy_messages']
#
# with open('TreatmentList.csv', 'w') as csvfile:
# writer = csv.DictWriter(csvfile,
# delimiter='\t',
# fieldnames=csv_headers,
# extrasaction='ignore'
# )
# writer.writeheader()
# for therapy_booking in therapy_bookings_list:
# for booking in therapy_booking['therapy_bookings']:
# if booking['payment_status'] in ['PAID', 'PARTIALLY_PAID'] and \
# booking['therapy_status'] in ['COMPLETED', 'ONGOING']:
# writer.writerow(booking)

return render(request, 'show.html', result_dict)

def post(self, request, *args, **kwargs):
pass


# from io import BytesIO
# from django.http import FileResponse
# from reportlab.platypus import SimpleDocTemplate, Table, TableStyle
# from reportlab.lib import colors
#
#
# def export_list_to_pdf(request):
# # Your data list
# my_list = [['Name', 'Age', 'City'], ['Alice', 30, 'New York'], ['Bob', 25, 'London']]
#
# # Create a file-like buffer to receive PDF data
# buffer = BytesIO()
# doc = SimpleDocTemplate(buffer)
# elements = []
#
# # Convert list to a Table object
# table = Table(my_list)
# table.setStyle(TableStyle([
# ('BACKGROUND', (0, 0), (-1, 0), colors.grey),
# ('GRID', (0, 0), (-1, -1), 1, colors.black),
# ]))
# elements.append(table)
#
# # Build the PDF
# doc.build(elements)
# buffer.seek(0)
#
# return FileResponse(buffer, as_attachment=True, filename='my_report.pdf')




from django.http import HttpResponse
from django.views import generic
from datetime import datetime, timedelta
from collections import defaultdict, OrderedDict

from django.http import HttpResponse
from django.views import generic
from datetime import datetime, timedelta
from collections import defaultdict, OrderedDict


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)

date_list = []

if single_date:
date_list = [single_date]
else:
try:
datetime.strptime(start_date, "%Y-%m-%d")
datetime.strptime(end_date, "%Y-%m-%d")
except ValueError:
return HttpResponse("Invalid date format. Use YYYY-MM-DD", status=400)

if single_date:
all_bookings, *_ = get_therapy_bookings_by_date(
start_date=single_date,
user=request.user
)
else:
all_bookings, *_ = get_therapy_bookings_by_daterange(
start_date=start_date,
end_date=end_date,
user=request.user
)


def clean(val):
if val is None:
return ''
val = str(val).strip().replace('\n', ' ')

return val

def format_datetime(val):
if not val:
return ''

try:
val_str = str(val)

# Remove timezone if present
if '+' in val_str:
val_str = val_str.split('+')[0]

# Remove microseconds
if '.' in val_str:
val_str = val_str.split('.')[0]

dt = datetime.strptime(val_str, "%Y-%m-%d %H:%M:%S")
return dt.strftime("%d-%m-%Y %H:%M") # 02-04-2026 09:49

except:
return val

def get_date_time(dt_val):
if not dt_val: return '', ''
dt_str = str(dt_val).strip()
if 'T' in dt_str:
parts = dt_str.split('T')
return parts[0], parts[1][:8]
elif ' ' in dt_str:
parts = dt_str.split(' ', 1)
return parts[0], parts[1][:8]
return dt_str, ''


person_map = OrderedDict()
person_order = []

for booking in all_bookings:
b_date, b_time = get_date_time(booking.get('start_time'))

for tb in booking.get('therapy_bookings', []):
patient_name = clean(tb.get('patient_name'))
therapist_name = clean(tb.get('today_therapist_name'))
therapy_title = clean(tb.get('therapy_title_with_duration'))

group_key = f"{patient_name}__{therapist_name}__{therapy_title}"

for s in tb.get('sessions', []):
if s.get('status') == 'INACTIVE':
continue

therapist_phone = clean(s.get('therapist_phone_number'))
if not therapist_phone:
continue

if group_key not in person_map:
person_map[group_key] = {
'sessions': [],
'tb_data': tb
}
person_order.append(group_key)

person_map[group_key]['sessions'].append({
'booking': booking,
'tb': tb,
'session': s,
'b_date': b_date,
'b_time': b_time,
'therapist_phone': therapist_phone
})

for key in person_map:
person_map[key]['sessions'].sort(
key=lambda x: x['session'].get('scheduled_appointment_start_time', '')
)

html = """
<html>
<head>
<meta charset="utf-8">
<style>
body { font-family: 'Calibri', 'Arial', sans-serif; }
table { border-collapse: collapse; width: 100%; font-size: 11pt; }
th, td {
border: 1px solid #BFBFBF;
padding: 6px 8px;
vertical-align: middle;
text-align: left;
}
.parent-header { background-color: #244061; color: #FFFFFF; font-weight: bold; }
.child-header { background-color: #DCE6F1; color: #17365D; font-weight: bold; }
.text-format { mso-number-format: "\\@"; white-space: nowrap; }
.data-row td { color: #000000; }
</style>
</head>
<body>
<table>
"""

if format_type == 'horizontal':

parent_headers = [
"Date", "Time", "Name", "Therapist", "Title",
"Sessions", "Med. Sent Days", "Age", "Address",
"Accepted Time", "T|C|C|S", "Invoice", "Amount",
"Commission", "Payout", "Status", "Location"
]

child_headers = [
"Sess No", "Appointment Time", "Duration", "Medicines", "Med Sent",
"Pre Notes", "Post Notes", "Status", "Reason", "Phone No.",
"Therapist Name", "Med Img", "Med Picked", "Therapy Start", "Therapy End",
"Payment Amt", "Payment Status", "Commission", "Payout", "Payout Status"
]

html += "<tr>"
for h in parent_headers:
html += f"<th class='parent-header'>{h}</th>"
for ch in child_headers:
html += f"<th class='child-header'>{ch}</th>"
html += "</tr>"

for key in person_order:
person_data = person_map[key]
sessions = person_data['sessions']
tb = person_data['tb_data']

for s_item in sessions:
s = s_item['session']
b_date = s.get('scheduled_appointment_start_time').date()
b_time = s_item['b_time']
t_start = clean(
s.get('start_qr_token_session_validated_at') or s.get('start_otp_token_session_validated_at'))
t_end = clean(
s.get('end_qr_token_session_validated_at') or s.get('end_otp_token_session_validated_at'))

html += "<tr class='data-row'>"

p_seg = [
clean(b_date), clean(b_time),
clean(tb.get('patient_name')),
clean(tb.get('today_therapist_name')),
clean(tb.get('therapy_title_with_duration')),
clean(tb.get('cur_session_by_total_sessions')).replace(" ", ""),
clean(tb.get('medicine_sent_for_days')),
clean(tb.get('patient_age')),
clean(f"{tb.get('address_flat_no_building', '')}, {tb.get('address_city', '')}"),
clean(tb.get('treatment_accepted_at')),
clean(f"{tb.get('is_bed_needed')} | {tb.get('is_steam_needed')}"),
clean(tb.get('invoice_url')),
clean(tb.get('total_amount')),
clean(tb.get('therapist_total_commission')),
clean(tb.get('total_payout_amount')),
clean(tb.get('payment_status')),
clean(tb.get('location'))
]
for i, val in enumerate(p_seg):

# Sessions column (index 5)
if i == 5:
html += f"<td style='mso-number-format:\"\\@\"'>{val}</td>"

else:
html += f"<td>{val}</td>"

s_seg = [
clean(s.get('session_no')),
clean(s.get('scheduled_appointment_start_time')),
clean(s.get('duration')),
clean(s.get('session_description')),
clean(s.get('medicine_sent_uploaded')),
clean(s.get('pre_therapy_notes')),
clean(s.get('post_therapy_notes')),
clean(s.get('status')),
clean(s.get('cancel_reason') or 'N/A'),
clean(s.get('therapist_phone_number')),
clean(s.get('therapist_name')),
"Available",
clean(s.get('med_picked_at')),
format_datetime(t_start),
format_datetime(t_end),
clean(s.get('payment_amount')),
clean(s.get('payment_status')),
clean(s.get('therapist_commission')),
clean(s.get('payout_amount')),
clean(s.get('payout_status'))
]
for i, val in enumerate(s_seg):

if i == 9:
html += f"<td style='mso-number-format:\"\\@\"'>{val}</td>"

else:
html += f"<td>{val}</td>"

html += "</tr>"

else:
for key in person_order:
person_data = person_map[key]
sessions = person_data['sessions']
tb = person_data['tb_data']

html += '''<tr class="parent-header">
<th>Date</th><th>Time</th><th>Name</th><th>Therapist</th><th>Title</th>
<th>Sessions</th><th>Med Sent</th><th>Age</th><th>Address</th><th>Accepted</th>
<th>T|C|C|S</th><th>Invoice</th><th>Amt</th><th>Comm</th><th>Payout</th><th>Status</th><th>Location</th>
</tr>'''

first_session = sessions[0] if sessions else None
if first_session:
b_date = first_session['b_date']
b_time = first_session['b_time']
else:
b_date = b_time = ''

sess_str = clean(tb.get('cur_session_by_total_sessions')).replace(" ", "")
html += f"""
<tr class="data-row">
<td>{clean(b_date)}</td>
<td>{clean(b_time)}</td>
<td>{clean(tb.get('patient_name'))}</td>
<td>{clean(tb.get('today_therapist_name'))}</td>
<td>{clean(tb.get('therapy_title_with_duration'))}</td>
<td class="text-format">{sess_str}</td>
<td>{clean(tb.get('medicine_sent_for_days'))}</td>
<td>{clean(tb.get('patient_age'))}</td>
<td>{clean(tb.get('address_city', ''))}</td>
<td>{clean(tb.get('treatment_accepted_at'))}</td>
<td>{clean(tb.get('is_bed_needed'))}</td>
<td>{clean(tb.get('invoice_url'))}</td>
<td>{clean(tb.get('total_amount'))}</td>
<td>{clean(tb.get('therapist_total_commission'))}</td>
<td>{clean(tb.get('total_payout_amount'))}</td>
<td>{clean(tb.get('payment_status'))}</td>
<td>{clean(tb.get('location'))}</td>
</tr>
"""

html += '''<tr class="child-header">
<th>Sess 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>Phone No.</th>
<th>Therapist Name</th><th>Med Img</th><th>Med Picked</th><th>Therapy Start</th><th>Therapy End</th>
<th>Payment Amt</th><th>Payment Status</th><th>Commission</th><th>Payout</th><th>Payout Status</th>
</tr>'''

for item in sessions:
s = item['session']
ph_no = clean(s.get('therapist_phone_number'))
t_start = clean(
s.get('start_qr_token_session_validated_at') or s.get('start_otp_token_session_validated_at'))
t_end = clean(
s.get('end_qr_token_session_validated_at') or s.get('end_otp_token_session_validated_at'))

html += f"""
<tr class="data-row">
<td>{clean(s.get('session_no'))}</td>
<td>{clean(s.get('scheduled_appointment_start_time'))}</td>
<td>{clean(s.get('duration'))}</td>
<td>{clean(s.get('session_description'))}</td>
<td>{clean(s.get('medicine_sent_uploaded'))}</td>
<td>{clean(s.get('pre_therapy_notes'))}</td>
<td>{clean(s.get('post_therapy_notes'))}</td>
<td>{clean(s.get('status'))}</td>
<td>{clean(s.get('cancel_reason') or 'N/A')}</td>
<td class="text-format">{ph_no}</td>
<td>{clean(s.get('therapist_name'))}</td>
<td>Available</td>
<td>{clean(s.get('med_picked_at'))}</td>
<td class="text-format">{format_datetime(t_start)}</td>
<td class="text-format">{format_datetime(t_end)}</td>
<td>{clean(s.get('payment_amount'))}</td>
<td>{clean(s.get('payment_status'))}</td>
<td>{clean(s.get('therapist_commission'))}</td>
<td>{clean(s.get('payout_amount'))}</td>
<td>{clean(s.get('payout_status'))}</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.encode('utf-8'))
return response

Comments

Popular Posts