
    4ʜhB                    X   d dl Z d dlZd dlmZmZmZmZmZmZm	Z	m
Z
 d dlmZ d dlmZmZmZmZ d dlmZmZmZmZmZ d dlmZmZ d dlmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z& d dl'm(Z( d d	l)m*Z* d d
l+m,Z,m-Z- d dl.Z.d dl.m/Z/ d dl.m0Z0 d dl1Z1d dl2m3Z3 d dl4m5Z5 d dl6m7Z7m8Z8m9Z9 d dl:m;Z; d dl<m=Z=m>Z> d dl?m@Z@ d dlAmBZBmCZC d dlDmEZE ddlFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZPmQZQ ddlRmSZS ddlTmUZUmVZVmWZWmXZX d dlYmZZZ d dl[m\Z\m]Z] d dl6m^Z^ d dl_m`Z` d dlambZb d dlcmdZd d dleZe e       Zf e/j                  d      Zh eieh        e.j                  eh        G d  d!e      Zk G d" d#e      Zl G d$ d%e      Zm G d& d'e      Znefj                  d(ee,j                     )      d d* ee;      fd+eqd,eqd-efd.       Zrefj                  d/       e	d0d12      fd3esfd4       Ztefj                  d5       e	d d62       ee;       eeS      fd7eqd-ed8efd9       Zuefj                  d:       ee;       eeS      fd-ed8efd;       Zvefj                  d<       ee;       eeS      fd-ed8efd=       Zwefj                  d>       ee;       eeS      fd?e,j                  d-ed8ed@eesef   fdA       Zzefj                  dB       ee;       eeS      fd-ed8ed@eesef   fdC       Z{efj                  dDe,j                  )       ee;       eeS      fdEeqd-ed8efdF       Z}efj                  d(ej                  G       ed0       ee;       eeS      fdHed-ed8efdI       Zefj                  dDe,j                  )       ee;       eeS      fdEeqdJe,j                  d-ed8efdK       Zefj                  dD       ee;       eeS      fdEeqd-ed8efdL       Zefj                  dMee,j                     )       ee;       eeS      fdNeqd-ed8efdO       Zefj                  dPe,j                  )       ee;       eeS      fdEeqdQeqd-ed8efdR       Zefj                  dS       ed0dTU       ee;       eeS      fdEeqdVed-ed8ed@ef
dW       Zefj                  dX       e	d       e	d       ee;       eeS      fdYedZed-ed8ed@eesef   f
d[       Zefj                  d\       e	d       e	d       ee;       eeS      fdYedZed-ed8ed@eesef   f
d]       Zefj                  d^       e	d       e	d       ee;       eeS      fdYedZed-ed8ed@eesef   f
d_       Zefj                  d`       e	d       e	d       e	dda2       ee;       eeS      fdYedZedEeeq   d-ed8ed@eesef   fdb       Zefj                  dc       ee;       eeS      fddekd-ed8ed@eesef   fde       Zefj                  df       ed0       ee;       eeS      fddekd-ed8ed@eesef   fdg       Zefj                  dh       e	d       e	d       e	didj2       ee;       eeS      fdYee   dZee   d,eqd-ed8ed@eesef   fdk       Zdled@efdmZefj                  dn       ed0       ee;       eeS      fddeesef   d-ed8ed@eesef   fdo       Zefj                  dp       ed0       ee;       eeS      fddeesef   d-ed8ed@eesef   fdq       Zefj                  dr       ee;       eeS      fd3esd-ed8ed@eesef   fds       Zefj                  dt       ee;       eeS      fd3esd-ed8efdu       Zefj                  dveeesef      )       ee;       eeS      fd-ed8efdw       Zefj                  dxeesef   )       ee;       eeS      fdEeqd-ed8efdy       Zefj                  dz       ed0       ee;       eeS      fddend-ed8efd{       Zd| Zefj                  d}e,j2                  )       ed0       ee;       eeS      fd~emd-ed8ed@eesef   fd       Zefj                  de)       ee;       eeS       e	dd       e	didd*      fd-edeqdeqfd       Z G d de      Zefj                  deej<                         ed0       ee;       eeS      fded-ed8efd       Zefj                  de)       ee;      fdeqd-efd       Zefj                  d       ed0       ee;       eeS      fddeesef   d-ed8efd       Zefj                  d       ed0       ee;       eeS      fddeesef   d-ed8efd       Zefj                  d       ee;       eeS      fd-ed8efd       Zefj                  d       ed0       ee;       eeS      fddeesef   d-ed8efd       Zefj                  d       ed0       ee;       eeS      fddeesef   d-ed8efd       Zefj                  d       ed0       ee;       eeS      fddeesef   d-ed8efd       Zefj                  d       ed0       ee;       eeS      fddeesef   d-ed8efd       Zefj                  d       ed0       ee;       eeS      fddeesef   d-ed8efd       Zefj                  d       e	d0d2       ee;       eeS      fdesd-ed8efd       Zefj                  d       ed0       ee;       eeS      fddeesef   d-ed8efd       Zefj                  d       ee;       eeS      fdded-ed8efd       Zy)    N)	APIRouterDependsHTTPExceptionRequeststatusBodyQueryPath)Session)ListDictAnyOptional)datetime	timedeltadatetimezonetime)	BaseModelField)DatefunccasedescasccastStringand_literal_columnor_distinctselect)StreamingResponse)convert_to_local_time)schemasmodels)credentials)	messaging)get_speech_to_text)OffTime)UserCustomerTransferResult)get_db)get_call_recording_public_urlget_twillio_client)convert_to_utc)NotFoundExceptionValidationError)Response   )get_advisorsget_advisorcreate_advisorprocess_booking_intentupdate_advisordelete_advisorget_advisors_by_departmentupdate_advisor_scoreupdate_advisor_availabilityis_advisor_availableget_all_available_advisors)validate_token)get_unique_repetitive_countsget_daily_call_countsget_hourly_call_volumeget_summary_statistics)ZoneInfo)stream_recording_from_urldownload_recording_by_call_id)Settings)get_setting)
month_name)defaultdictzfirebase/serviceAccountKey.jsonc                   6    e Zd ZU dZee   ed<   dZee   ed<   y)DashboardRequestN
start_dateend_date)__name__
__module____qualname__rO   r   r   __annotations__rP        F/var/www/html/DP/alpha_backend/app/advisor_service/routers/advisors.pyrN   rN   ;   s     %)J")#'Hhx 'rV   rN   c                   "    e Zd ZU eed<   eed<   y)DateRangeRequestrO   rP   N)rQ   rR   rS   r   rT   rU   rV   rW   rY   rY   I   s    NrV   rY   c                   "    e Zd ZU eed<   eed<   y)DailyLogRequestlog_date
advisor_idN)rQ   rR   rS   r   rT   intrU   rV   rW   r[   r[   M   s    NOrV   r[   c                   6    e Zd ZU eed<   eed<   dZee   ed<   y)AdvisorTimeStatsRequestrO   rP   Nr]   )rQ   rR   rS   r   rT   r]   r   r^   rU   rV   rW   r`   r`   R   s    N $J$rV   r`   z	/advisors)response_modeld   skiplimitdbc                 .   K   t        || |dd      }|S w)a  
    Get all advisors, ordered by status (available first) and then by full name.
    
    Args:
        skip: Number of records to skip for pagination
        limit: Maximum number of records to return
        
    Returns:
        List of advisors ordered by availability and name
    T)rc   rd   order_by_statusorder_by_name)r6   )rc   rd   re   advisorss       rW   read_advisorsrj   W   s(     $ 
H Os   z#/advisors/speech/get-speech-to-text.z%The call ID to get speech-to-text for)descriptioncall_idc                    K   t        |       }|t        t        j                  d      t	        |      \  }}}}||dS w)zs
    Get speech-to-text for a given call
    
    Args:
        call_id: The call ID to get speech-to-text for
    z No recording found for this callstatus_codedetail)
transcriptbooking_intent)r/   r   r   HTTP_404_NOT_FOUNDr)   )rl   recording_public_urlrq   rr   booking_datetimetranscript_with_speaker_labelss         rW   get_speech_textrw   r   sW      9A#115
 	

 TffzS{PJ 02P$GGs   >A z/advisors/notificationszNumber of records to skipstartcurrent_userc                   K   d}|j                  t              j                  t        j                  |j	                  d      k(        j                         }|j                  dk(  st        t        j                  d      |j                  t        j                        j                  t        j                  j                  |j                  k(        j                         }|j                  }|j                  t        j                  t        j                   j                              j                  t        j                   j"                  |k(        j%                         }|j                  t        j                  t        j                   j                              j                  t        j                   j"                  |k(  t        j                   j&                  dk(        j%                         }|j                  t        j                         j                  t        j                   j"                  |k(        j)                  t        j                   j*                  j-                               j/                  |       j1                  |      j3                         }	g }
|	D ]X  }d}d}|j4                  r{|j                  t        j6                        j                  t        j6                  j4                  |j4                  k(        j                         }|r|j8                  }|j:                  }|j                  |j<                  |j>                  |j4                  |||j@                  |jB                  |jD                  r|jD                  nd|j&                  |jF                  r|jF                  jI                         nd|j*                  r|j*                  jI                         ndd	}|
jK                  |       [ |
||| |d
S w)z
    Get notifications for the authenticated advisor.
    Returns latest 5 notifications by default, with pagination for the rest.
       emailadvisorNo advisor ID found in tokenrn   FNUnknown)idnotification_typetitlerl   rq   call_summarymessagecustomer_phonecustomer_nameis_readread_at
created_at)datatotaltotal_unreadrx   rd   )&queryr+   filterr|   getfirsttyper   r   HTTP_403_FORBIDDENr&   Advisoruser_idr   r   countNotificationsr]   scalarr   order_byr   r   offsetrd   allrl   CallsLogrq   r   r   r   r   r   r   r   	isoformatappend)rx   re   ry   rd   userr}   r]   total_countr   notificationsresponse_datanotificationrq   r   call_lognotification_datas                   rW   get_notificationsr      s     E88D>  |/?/?/H!HIOOQD99	!111
 	

 hhv~~&--fnn.D.D.OPVVXGJ ((

6''**+f'':5fh	  88

6''**+f'':5$$- fh  HHf'':5h'',,.fUmEE%L  M%
xx077''<+?+??eg  %00
'44 //!-!?!?!''#++$(#++*99;G;U;U\77[d#++;G;O;O|++557UYAMAXAX,11;;=^b
 	./5 &: $ s   PPz/advisors/notifications/latestc           	        K   | j                  t              j                  t        j                  |j	                  d      k(        j                         }|j                  dk(  st        t        j                  d      | j                  t        j                        j                  t        j                  j                  |j                  k(        j                         }|j                  }t        d|       | j                  t        j                        j                  t        j                  j                   |k(  t        j                  j"                  dk(  t        j                  j$                  dk(        j'                  t        j                  j(                  j+                               j                         }|sdd	iS |j                  |j$                  |j,                  |j.                  |j0                  |j2                  r|j2                  nd
|j"                  |j(                  r|j(                  j5                         nd	d}d|iS w)zG
    Get single latest notification for the authenticated advisor.
    r|   r}   r~   rn   r]   Fmissed_callr   Nr   )r   r   r   r   r   r   r   r   )r   r+   r   r|   r   r   r   r   r   r   r&   r   r   r   printr   r]   r   r   r   r   r   r   r   r   r   r   )re   ry   r   r}   r]   r   r   s          rW   get_latest_notificationr      s     88D>  |/?/?/H!HIOOQD99	!111
 	

 hhv~~&--fnn.D.D.OPVVXGJ	,
# 88f'':5$$-..-? h'',,.eg  ~ oo);;##''&557C7Q7Q33W`''=I=T=Tl--779Z^	 	! s   I	Iz /advisors/notifications/read-allc                   K   | j                  t              j                  t        j                  |j	                  d      k(        j                         }|j                  dk(  st        t        j                  d      | j                  t        j                        j                  t        j                  j                  |j                  k(  t        j                  j                  dk(        j                  t        j                  j                  dt        j                  j                   t#        j$                  t&        j(                        i      }| j+                          dd| d	iS w)
zF
    Mark all notifications as read for the authenticated advisor
    r|   r}   r~   rn   FTr   zMarked z notifications as read)r   r+   r   r|   r   r   r   r   r   r   r&   r   r   r   r   updater   r   nowr   utccommit)re   ry   r   results       rW   read_all_notificationsr     s     88D>  |/?/?/H!HIOOQD99	!111
 	
 XXf**+22$$/$$- f$$d$$hll8<<&@   IIK 	WVH$:; s   E(E*z/advisors/update-fcmreq_datareturnc                 F  K   |j                  t        j                        j                  t        j                  j                  |j                  d      k(        j                         }|r2| j                  |_        |j                          |j                  |       ddiS w)Nr|   r   zFcm token updated successfully)r   r&   r+   r   r|   r   r   token	fcm_tokenr   refresh)r   re   ry   db_users       rW   updateFcmTokenr   /  s      hhv{{#**6;;+<+<@P@PQX@Y+YZ``bG$NN
		


7 	3 s   BB!z/advisors/send-notificationc                   K   | j                  t        j                        j                  t        j                  j                  |j                  d      k(        j                         }d}d}|rS|j                  G|j                  }t        j                  ddd|      }t        j                  |      }t        d|       d	d
iS w)Nr|   zDealerPulse UpdatezUHi john, someone is missing you. Guess what, it's your client. Please call back asap.850z2:45)scorer   )r   r   zSuccessfully sent message:r   zNotification sent successfully)r   r&   r+   r   r|   r   r   r   r(   Messagesendr   )re   ry   r   message_titlemessage_bodyregistration_tokenr   responses           rW   sendPushNotificationr   @  s     
 hhv{{#**6;;+<+<@P@PQX@Y+YZ``bG(MjL(!(!2!2  ''"" )G !~~g.H.93    CCz/advisors/{advisor_id}r]   c                 $   K   t        ||       S w)Nr]   )r7   r]   re   ry   s      rW   read_advisorr   a  s      rj11   )ro   advisor_datac           	        K   | j                  dd      }d| d<   	 t        j                  d
i | }t        |||      }|j                  |j                  |j                  |j                  |j
                  |j                  |j                  |j                  d}t!        |d	      r|j"                  |d	<   |S # t        $ r,}t	        t
        j                  dt        |             d}~ww xY ww)a:  
    Create a new advisor with a user account
    
    Expects a JSON object with advisor details. The password field is optional - 
    if not provided, a random secure password will be generated.
    
    Example request:
    {
        "full_name": "John Doe",
        "email": "john@example.com",
        "phone_number": "+1234567890",
        "status": "1",
        "department_id": 1,
        "type": "sales",
        "password": "securepassword123"  // Optional
    }
    
    If password is not provided, the response will include a generated_password field.
    passwordN0r   zInvalid advisor data: rn   )re   r}   r   )r   	full_namer|   phone_numberr   department_idr   r   generated_passwordrU   )popr%   AdvisorCreate	Exceptionr   r   HTTP_400_BAD_REQUESTstrr8   r   r   r|   r   r   r   r   hasattrr   )r   re   ry   r   r}   ecreated_advisorr   s           rW   create_new_advisorr   i  s     4 
D1H L
''7,7 %GhOO   $.. &&'44!(((66$$"**	M  45.=.P.P*+3  
33+CF84
 	

s(   C.B6 BC.6	C+?'C&&C++C.r}   c                   K   |j                  t        j                        j                  t        j                  j                  | k(        j                         }|st        dd|  d      |j                  t        j                        j                  t        j                  j                  j                  |j                        t        j                  j                  | k7        j                         }|rt        t        j                  d      |j                  r|j                  t        j                        j                  t        j                  j                  |j                  k(        j                         }|r>|j                  r2|j                  |_        |j                  |       |j                          t!        || |      S w)N  zA staff member with id 
 not foundrn   zJA staff member with this name already exists. Please use a different name.)re   r]   r}   )r   r&   r   r   r   r   r   r   iliker   r   r   r+   nameaddr   r:   )r]   r}   re   ry   
db_advisorexisting_advisorr   s          rW   update_existing_advisorr     sU     &..)001B1Bj1PQWWYJ,ZL
C
 	
 xx/66  &&w'8'89Z' eg 
 33_
 	
 xx$++FKKNNj>P>P,PQWWY  #--	t		RJHHs   GGc                 $   K   t        ||       S w)N)re   r]   )r;   r   s      rW   delete_existing_advisorr     s      RJ77r   z%/departments/{department_id}/advisorsr   c                 (   K   t        ||       }|S w)N)r   )r<   )r   re   ry   ri   s       rW   read_advisors_by_departmentr     s      *"MJHOs   z/advisors/{advisor_id}/scorer   c                 &   K   t        || |      S w)N)re   r]   r   )r=   )r]   r   re   ry   s       rW   update_advisor_score_endpointr     s       2*EJJ   z/availability/{advisor_id}T)embedis_availablec                    K   t        || |      }|st        dd|  d      |j                  |j                  |j                  d|j                   d|j                  dk(  rdnd	 d
S w)z
    Set an advisor's availability status.
    
    Args:
        advisor_id: ID of the advisor
        is_available: True to mark as available, False to mark as unavailable
        
    Returns:
        JSON response with updated advisor information
    r   Advisor with ID r   rn   zAdvisor z is now 1	availableunavailable)r   r   r   r   )r>   r   r   r   r   )r]   r   re   ry   r}   s        rW   set_advisor_availabilityr     s     " *"j,GG%j\<
 	
 jj&&..g//0Z]H]cp8qr	 s   A'A)z/dashboard/call-countsrO   rP   c                 b  K   	 | s!t        j                         t        d      z
  } |st        j                         }|j                  ddd      }t	        || ||      }d|| j                         |j                         dd	S # t        $ r}t        d
dt        |             d}~ww xY ww)zM
    Get counts of unique and repetitive calls for the given date range.
       days   ;   hourminutesecondr   TrO   rP   successr   
date_range  zError retrieving call counts: rn   N)	r   r   r   replacerB   r   r   r   r   )rO   rP   re   ry   call_countsr   s         rW   get_call_countsr    s     
!)*<<J||~H ##Br#B 32z8R^_ (224$..0
 	
  
3CF8<
 	

s)   B/B B B/	B,B''B,,B/z/dashboard/daily-callsc                   K   	 | s!t        j                         t        d      z
  } |st        j                         }|j                  ddd      }|j	                  di       j	                  d      }|j	                  di       j	                  d      }|d	k(  rt        || |      }nt        || ||
      }d|| j                         |j                         ddS # t        $ r}t        ddt        |             d}~ww xY ww)zS
    Get daily counts of unique and repetitive calls for the given date range.
    r   r   r   r   r   r   r   r]   managerr   Tr   r   r  z$Error retrieving daily call counts: rn   N)
r   r   r   r  r   rC   r   r   r   r   )rO   rP   re   ry   	user_typer]   daily_callsr   s           rW   get_daily_callsr	  .  s    #
!)*<<J||~H ##Br#B $$VR044V<	!%%fb155lC
 	!/JIK 0JU_`K (224$..0
 	
  
9#a&B
 	

s)   DCC D	D#C<<DDz/dashboard/hourly-callsc                 ^  K   	 | s!t        j                         t        d      z
  } |st        j                         }|j                  ddd      }t	        || |      }d|| j                         |j                         ddS # t        $ r}t        d	d
t        |             d}~ww xY ww)zJ
    Get average call volume by hour of day for the given date range.
    r   r   r   r   r   Tr   r   r  z%Error retrieving hourly call volume: rn   N)	r   r   r   r  rD   r   r   r   r   )rO   rP   re   ry   hourly_callsr   s         rW   get_hourly_callsr  ]  s     
!)*<<J||~H ##Br#B .b*hG  (224$..0
 	
  
:3q6(C
 	

s)   B-A>B B-	B*B%%B**B-z/dashboard/summaryzFilter by advisor IDc                   K   	 | s!t        j                         t        d      z
  } |st        j                         }|j                  ddd      }t	        || ||      }d|| j                         |j                         ddS # t        $ r5}t        d	t        |              t        d
d	t        |             d}~ww xY ww)a.  
    Get summary statistics for the given date range.
    
    Args:
        start_date: Optional start date for filtering (defaults to 30 days ago)
        end_date: Optional end date for filtering (defaults to current date)
        advisor_id: Optional advisor ID to filter statistics by advisor
    r   r   r   r   r   Tr   r   zError retrieving call summary: r  rn   N)
r   r   r   r  rE   r   r   r   r   r   )rO   rP   r]   re   ry   summaryr   s          rW   get_call_summaryr    s      
!)*<<J||~H ##Br#B )Z:N (224$..0
 	
  
/Ax894SVH=
 	

s)   CA?B C	C0B==CCz/dashboard/allrequestc                   K   	 t        j                         j                         }| j                  }| j                  }t        | dd      }|rt        |      }|rt        |      }|xs |t        d      z
  }|xs |}|j                  d      }	d}
d}|	|j                  t        j                        j                  t        j                  j                  |	k(  t        j                  j                  dk(        j                         }|r|j                   }
|j"                  }t        j$                  |t         j&                  j)                               }t        j$                  |t         j*                  j)                               }t-        |||||      }t/        |||||      }t1        |||||      }t3        |||||
      }||||d	}d
||j5                         |j5                         ddS # t6        $ rG}ddl}t;        d       t;         |j<                                t?        ddtA        |             d}~ww xY ww)ar  
    Get all dashboard data in a single API call for the given date range.
    Combines call counts, daily calls, hourly calls, and summary statistics.
    
    Request body:
    {
        "start_date": "2023-01-01T00:00:00-07:00",  // Optional, defaults to 30 days ago
        "end_date": "2023-01-31T23:59:59-07:00"     // Optional, defaults to current date
    }
    current_timezoneAmerica/Los_Angelesr   r   r   Nr}   )r   r]   )r  r  r  r  Tr   r   r   z#Error in get_customer_call_history:r  z!Error retrieving dashboard data: rn   )!r   r   r   rO   rP   getattrr1   r   r   r   r&   r   r   r   r   r   r   r   combineminr   maxrB   rC   rD   rE   r   r   	tracebackr   
format_excr   r   )r  re   ry   todayrO   rP   r   start_date_valend_date_valr   r]   advisor_phoner}   r  r  r  r  dashboard_datar   r  s                       rW   get_all_dashboard_datar    s&     7
##%''
##7$68MN'
3J%h/H#C	r0B(B(5""4(
hhv~~.55fnn6L6LPW6WY_YgYgYlYlpyYyz  A  A  CG$ZZ
 ' 4 4%%nhll6G6G6IJ
##L(,,2C2C2EF22z8R^kxy+B
H<dqr-b*h\fst(Zakl '&(	
 ",668(224
 	
  
34"i""$%6s1vh?
 	
	
s*   IG-G2 1I2	I;AH==IIz/dashboard/leaderboardc                 d  K   	 dddddd}| j                   }| j                  }|rt        |      }|rt        |      }t        j                         }|s|t        d      z
  }|s|}t        j                  |t        j                  j                               }t        j                  |t        j                  j                               }|j                  t        j                        j                  t        j                  j                  d	k(        j!                         }	g }
|	D ]b  }|j                  t        j"                        j%                  t        j&                  t        j"                  j(                  t        j&                  j(                  k(        j                  t        j&                  j*                  |j,                  k(  t        j"                  j*                  |j.                  k(  t        j&                  j0                  |k\  t        j&                  j0                  |k  t        j&                  j2                  |j5                  d
      k(        j7                         }|j                  t        j"                        j%                  t        j&                  t        j"                  j(                  t        j&                  j(                  k(        j                  t        j&                  j*                  |j,                  k(  t        j"                  j*                  |j.                  k(  t        j"                  j                  dk(  t        j&                  j0                  |k\  t        j&                  j0                  |k  t        j&                  j2                  |j5                  d
      k(        j7                         }|j                  t        j"                        j%                  t        j&                  t        j"                  j(                  t        j&                  j(                  k(        j                  t        j&                  j*                  |j,                  k(  t        j"                  j*                  |j.                  k(  t        j"                  j                  dk(  t        j&                  j0                  |k\  t        j&                  j0                  |k  t        j&                  j2                  |j5                  d
      k(        j7                         }d}|dkD  r||z  dz  }|d   }|dkD  r|d   }n |dkD  r|d   }n|dkD  r|d   }n
|dkD  r|d   }|
j9                  |j.                  |j:                  |||t=        |d      |d       e |
j?                  d d       d|
tA        |t              r|jC                         n|tA        |t              r|jC                         n|ddS # tD        $ r;}tG        tI        jJ                                tM        ddtO        |              d!}~ww xY ww)"z9
    Get advisor leaderboard data for the dashboard.
    z#76c487z#9ff9b3z#e6e8b3z#f2bc92z#f89595)bestgoodokbadworser   r   r   default_companyTFr   rb   r!  <   r%  (   r$     r#  
   r"     )r]   advisor_nametotal_callssuccessful_callsmissed_callsmissed_percentagebackground_colorc                     | d   S )Nr0  rU   xs    rW   <lambda>z!get_leaderboard.<locals>.<lambda>`  s
    !$7"8rV   keyreverser   r   r  z#Error retrieving leaderboard data: rn   N)(rO   rP   r1   r   r  r   r   r  r  r   r  r   r&   r   r   r   r   r-   joinr   twilio_call_idtransferred_tor   r   call_date_time
company_idr   r   r   r   roundsort
isinstancer   r   r   r  r  r   r   )r  re   ry   performance_colorsrO   rP   r  start_datetimeend_datetimeri   r   r}   r-  r.  r/  r0  r1  r   s                     rW   get_leaderboardrD    s    l

 ''
##'
3J%h/H

!33JH!))*hll6G6G6IJ''(,,2C2C2EF88FNN+226>>3H3HC3OPTTV G((6#8#89>>!6!6!E!EIgIg!g&OO22g6J6JJ))88GJJFOO22nDOO22lBOO..,2B2BCT2UU %'   "xx(=(=>CC!6!6!E!EIgIg!g &OO22g6J6JJ))88GJJF))00D8OO22nDOO22lBOO..,2B2BCT2UU %'  88F$9$9:??!6!6!E!EIgIg!g&OO22g6J6JJ))88GJJF))00E9OO22nDOO22lBOO..,2B2BCT2UU %'  !"Q%1K%?3$F!1&9 2%#5g#> "R'#5e#< "R'#5d#; "R'#5f#= MM%jj ' 1 1*$4 ,%*+<a%@$4 a  t 	8$G 8B:t8Tj224Zd4>x4NH..0T\
 	
  
i""$%8QA
 	

s)   X0W$W) (X0)	X-26X((X--X0z/dashboard/recent-callsr*  z Number of recent calls to returnc                 b  K   	 | s!t        j                         t        d      z
  } |st        j                         }|j                  ddd      }|j	                  t
        j                  j                  t
        j                  j                  t
        j                  j                  j                  d      t
        j                  j                  j                  d      t
        j                  j                  j                  d      t
        j                  j                  t
        j                  j                  t
        j                  j                  t
        j                   j"                  t
        j$                  j&                  j                  d	      
      j)                  t
        j                   t
        j                  j*                  t
        j                   j*                  k(        j)                  t
        j$                  t
        j                   j,                  t
        j$                  j                  k(        j/                  t
        j                  j                  | k\  t
        j                  j                  |k  t
        j                  j0                  |j3                  d
      k(        j5                  t
        j                  j                  j7                               j9                  |      j;                         }g }|D ]  }|j"                  rdnd}|j"                  d}|j                  rt=        |j                        nd}	|j?                  |j                  |j                  |j@                  |jB                  xs d|jD                  ||j                  xs d|j                  xs d|	|jF                  xs dd
        d|tI        ||       jK                         tI        ||      jK                         dtM        |      dS # tN        $ r}
tQ        ddt=        |
             d}
~
ww xY ww)aq  
    Get a list of recent calls with details, sorted by date (newest first).
    
    Args:
        start_date: Optional start date for filtering
        end_date: Optional end date for filtering
        limit: Number of recent calls to return (default: 10)
        
    Returns:
        List of recent calls with details including transfer status and advisor name
    r   r   r   r   r   	call_dater   r   r,  r&  
successfulfailedNnot transferredunknownr    Not transferred)
rl   r   rF  r   r   transfer_statusr   recording_urlcall_durationr,  Tr   )r   r   r   r   r  zError retrieving recent calls: rn   ))r   r   r   r  r   r&   r   r   rl   r<  labelcaller_namecaller_numberr   rN  rO  r-   r   r   r   	outerjoinr:  r;  r   r=  r   r   r   rd   r   r   r   rF  r   r   r,  r$   r   lenr   r   )rO   rP   rd   re   ry   calls_queryr   callrM  call_duration_strr   s              rW   get_recent_callsrX  r  s    &J
!)*<<J||~H##Br#B HH""''..44[A++11/B--334DE,,----%%,,((..~> Y%%..&2G2G2V2VV Y%%448I8II V..*<..(:**l.>.>?P.QQ
 Xfoo4499;<U5\SU9 	> D.2kklxO{{""3;?;M;MD$6$6 7S\MM<<gg!^^!%!3!3!@y"&"5"5#2 $ 1 1 7R!%!3!3!9r!2 $ 1 1 F5F   ( 3BzBLLN1"X>HHJ [
 	
  
4SVH=
 	

s)   P/P P P/	P,P''P,,P/call_datetimec                 ~    t        j                  d      }| j                  |      }|j                  }|dk\  xs |dk  S )zS
    Check if the given UTC datetime falls within off-hours (7 PM to 9 AM PST)
    r     	   )pytzr   
astimezoner   )rY  pstpst_timer   s       rW   is_off_timera    sC    
 ---
.C'',H ==D 2:!!rV   z/dashboard/call-logc                 "  K   	 | j                  d      }| j                  d      }| j                  dd      }| j                  d      }| j                  d      }| j                  d      }| j                  d      }	| j                  d	      }
| j                  d
      }| j                  dd      }| j                  dd      }|dz
  |z  }t        |t              r	 t        j                  |      }t        |t              r	 t        j                  |      }|rt        |      }|rt        |      }t        j                         }|s|t        d      z
  }|s|}t        |t              r$t        j                  |d      j                         }t        |t              r$t        j                  |d      j                         }t        j                  |t        j                  j                               }t        j                  |t        j                  j                               }|	dk(  rt        j                  |t        dd            }t        j                  |t        dd            }t        j                  |t        dd            }t        j                  |t        dd            }ndt        j                  |t        j                  j                               }t        j                  |t        j                  j                               }t!        d| d|        t!        d|        t!        d|        t!        d|        t!        d |	        t!        d!|
        |
r|
j#                         j%                         }
|j                  d"      }d#}d#}||j'                  t(        j*                        j-                  t(        j*                  j.                  |k(  t(        j*                  j0                  d$k(        j3                         }|r|j4                  }|j6                  }|j'                  t(        j8                        j;                  t(        j<                  t(        j8                  j>                  t(        j<                  j>                  k(        j-                  t(        j8                  j@                  |k\  t(        j8                  j@                  |k        }|
r?|j-                  tC        j$                  t(        j8                  jD                        |
k(        }|r,|j-                  t(        j8                  j>                  |k(        }|rR|j-                  tC        j$                  t(        j8                  jF                        tC        j$                  |      k(        }|r,|j-                  t(        j<                  jH                  |k(        }|s|rH|j-                  t(        j8                  jH                  |k(  t(        j<                  jH                  |k(        }|r<|j-                  t(        j8                  jJ                  jM                  d%| d%            }|jO                         }tQ        jR                  ||z        }|j-                  |t(        j8                  jH                  |k(  nd&t(        j<                  jT                  d&k(        jO                         }|j-                  |t(        j8                  jH                  |k(  nd&t(        j<                  jT                  d'k(        jO                         }|j'                  tC        jV                  t(        j8                  jX                              j[                  |j]                               j_                         }d} |r,t        |t              r|ja                         } ntc        |      } te        tg        |       d(      \  }!}"te        |"d)      \  }#}$tg        |!      d*d+tg        |#      d*d+tg        |$      d*}%|	r|	j%                         d,k(  r8t!        d-       |j-                  t(        j<                  jT                  d&k(        }nJ|	j%                         d.k(  r7t!        d/       |j-                  t(        j<                  jT                  d'k(        }|j'                  t(        j8                  j4                  t(        j8                  jh                  t(        j8                  j>                  t(        j8                  j@                  jk                  d0      t(        j8                  jl                  jk                  d1      t(        j8                  jJ                  jk                  d      t(        j8                  jn                  t(        j8                  jp                  t(        j8                  jX                  t(        j8                  jr                  t(        j8                  jD                  t(        j8                  jF                  jk                  d      t(        j<                  jT                  t(        j*                  jt                  jk                  d2      t(        j*                  j4                  jk                  d            j;                  t(        j<                  t(        j8                  j>                  t(        j<                  j>                  k(        j;                  t(        j*                  t(        j<                  jH                  t(        j*                  j4                  k(        }&|r<|j#                         }|&j-                  t(        j8                  j>                  |k(        }&|	dk(  r[|&j-                  |t(        j8                  jH                  |k(  nd&t(        j8                  jr                  tv        jx                  k(        }&nh|&j-                  |t(        j8                  jH                  |k(  nd&t(        j8                  j@                  |k\  t(        j8                  j@                  |k        }&|rR|&j-                  tC        j$                  t(        j8                  jF                        tC        j$                  |      k(        }&|
r?|&j-                  tC        j$                  t(        j8                  jD                        |
k(        }&|r,|&j-                  t(        j<                  jH                  |k(        }&|r<|&j-                  t(        j8                  jJ                  jM                  d%| d%            }&|	r|	j%                         d,k(  r-|&j-                  t(        j<                  jT                  d&k(        }&n?|	j%                         d.k(  r,|&j-                  t(        j<                  jT                  d'k(        }&|&jO                         }'t!        d3|'        |&j{                  t(        j8                  j@                  j}                               j                  |      j                  |      j                         }(g })|(D ]  }*|*jT                  rd,nd4}+|*jT                  d5}+|*jX                  rt        |*jX                        nd6},t!        |*d7       |)j                  |*j4                  |*jh                  |*j>                  |*j                  |*jr                  tv        jx                  k(  |*j                  xs d8|*j                  |+|*jn                  xs d9|*jp                  xs d9|,|*j                  xs d:|*j                  |*j                  xs d;|*jD                  d<        ||||'|%tg        |       d=}-g }.|r|.j                  d>| d?       |r|.j                  d@|        |r|.j                  dA| d?       |	r|.j                  dB|	 d?       |)ss|.rqdCj                  |.      }/d'dD|/ dE| dF| g |-t        |t              r|j                         n|t        |t              r|j                         n|dG||||	dH||||dIdJS d&|)|-t        |t              r|j                         n|t        |t              r|j                         n|dG||||	dH|'|||dIdKS # t
        $ r t        j                  |d      }Y w xY w# t
        $ r. t        j                  |d      }|j                  ddd      }Y w xY w# t        $ rS}0dd#lL}1t!        dLt        |0              t!         |1j                                t        dMdNt        |0       O      d#}0~0ww xY ww)Pz
    Get a filtered call log with details, sorted by date (newest first).
    Supports filtering by transfer status (successful/failed).
    rO   rP   r   UTC	sentimentr]   r   rM  
departmentr:  pager+  	page_sizer*  %Y-%m-%dr   r   r   r   r   offtimer5   r            zFiltering with: start_date=z, end_date=zSentiment filter: zAdvisor ID filter: zCustomer phone filter: zTransfer status filter: zDepartment filter: r   Nr}   %TF  r'  02:rG  z'Filtering for successful transfers onlyrH  z#Filtering for failed transfers onlyrF  r   r,  zTotal matching records: missedrI  rJ  z------r   rK  rL  neutral)r   rl   r:  rF  ra  r   r   rM  r   rN  rO  r,  r]   rd  re  )r-  total_successful_callstotal_missed_callsfiltered_countavg_call_timeavg_call_time_secondszsentiment=''zadvisor_id=zcustomer_phone='ztransfer_status='z, z#No records found matching filters: z for the date range z to r   )rd  r]   r   rM  )r   total_pagesrf  rg  )r   r   r   r  r   filters
pagination)r   r   r  r   rz  r{  zError in call-log endpoint: r  zError retrieving call log: rn   )Or   r@  r   r   fromisoformat
ValueErrorstrptimer  r1   r   r  r   r  r  r   r  r   striplowerr   r&   r   r   r   r   r   r   r   r   rS  r-   r:  r<  r   re  sentiment_scorer;  rR  liker   mathceilr   avgrO  select_fromsubqueryr   total_secondsfloatdivmodr^   rl   rP  rQ  r   rN  
is_offtimer   r*   YESr   r   r   rd   r   r   rF  r   r   r,  r]   rd  r9  r   r   r  r  r   )2r  re   ry   rO   rP   r   rd  req_advisor_idr   rM  re  callIdrf  rg  r   r  rB  rC  evening_startevening_endmorning_startmorning_endr   r]   r  r}   
base_queryr-  ry  rs  rt  avg_duration_resultavg_duration_secondshours	remainderminutessecondsrv  r   r   rU  r   rV  call_transfer_statusrW  r  filter_info
filter_strr   r  s2                                                     rW   get_call_logr    s0    n
 [[.
;;z*;;z51KK,	 \2 %56!++&78[[.
-.{{61%KKR0	(i' j#&G%33J?
 h$K#11(; '
3J%h/H

!33JH j#&!**:zBGGIJh$((:>CCEH!))*hll6G6G6IJ''(,,2C2C2EFi' %,,ZaDM"**:tAr{CK$,,ZaDM"**:tB|DK%--j(,,:K:K:MNN#++Hhll6G6G6IJL 	+N+;;|nUV"9+./#N#345''789((9:;#J<01#))+113J""4(
hhv~~.55fnn6L6LPW6WY_YgYgYlYlpyYyz  A  A  CG$ZZ
 ' 4 4 HHV__%Y%%..&2G2G2V2VV V...@..,> 	 #**

6??556*DJ #**6??+I+IV+STJ #**4::foo6U6U+VZ^ZdZdenZo+opJ #**6+@+@+O+OSa+abJ#**..-?%%44
BJ
 #**6??+H+H+M+MPQR`QaabNc+deJ !&&(iii 78 CPC\..-?bf%%,,4 eg	 	 CPC\..-?bf%%,,5 eg	 	 HHTXXfoo;;<=[,,./VX 	  !-y9':'H'H'J$ (--@'A$ "#&:";TBy!)R0u:b/3w<*;1S\"<MN $$&,6?@'..v/D/D/K/Kt/ST
 &&(H4;<'..v/D/D/K/Ku/TU
 HH""''....44[A++11/B--334DE,,----****//55kB%%,,((..~>!!''5" Y%%..&2G2G2V2VV Y%%448I8II- 	8 \\^FLL!?!?6!IJEi'LLCPC\..-?bf**gkk9E
 LLCPC\..-?bf...@..,>E LLFOO,K,K!LPTPZPZ[dPe!efELL

6??556*DE LL!6!6!E!E!WXELL!>!>!C!CaGWWXDY!Z[E $$&,6V%:%:%A%AT%IJ &&(H4V%:%:%A%AU%JK kkm(67 Xfoo4499;<VF^U9SU 	 D37;;<H {{"'8$;?;M;MD$6$6 7S\$x MMgg<<"&"5"5!^^#'++=!%!3!3!@y"&"5"5#7 $ 1 1 7R!%!3!3!9r!2 $ 1 1 F5F"oo!^^8y"oo   : '&<"4)*%()=%>
 YKq9:ZL9:!1.1ACD!2?2C1EF+;/J @L`ak`llpqypz{"<FzSW<X*"6"6"8^h8B8T8R 2 2 4X`
 "+",&4'6	 )#. !*	 0 8B:t8Tj224Zd4>x4NH..0T\
 '("0#2	 %*&	
 	
{	  G%..z:F
G  K#,,XzB#++Br+JKZ
  
,SVH56"i""$%0Q9
 	
	
s   AECAC: AB 0AC: AC  |-AC: AAEAAAC: BAEBAB=B9AC: B<AB=B=AC: C 3AC7C3AC: C6AC7C7AC: C:	AEDAAEEAEEAEz/dashboard/advisor-statsc                 $  K   	 | j                  d      }| j                  d      }| j                  d      }t        j                         }|s|t        d      z
  }|s|}t	        |t
              r	 t        j                  |      }n2t        j                  |t        j                  j                               }t	        |t
              r+	 t        j                  |      }|j                  ddd	      }n2t        j                  |t        j                  j                               }|j                  t         j"                        j%                  t         j"                  j&                  |k(        j)                         }	|	st+        d
d| d      |j                  t         j,                        j%                  t         j,                  j.                  |k(  t         j,                  j0                  dk(  t         j,                  j2                  |k\  t         j,                  j2                  |k        j5                         }
|j                  t         j,                        j%                  t         j,                  j.                  |k(  t         j,                  j0                  dk(  t         j,                  j2                  |k\  t         j,                  j2                  |k        j5                         }|
|z   }|dkD  r||z  dz  nd}|j                  t         j6                  j&                  t         j6                  j8                  t         j6                  j:                  t         j6                  j<                  t         j6                  j>                  t         j6                  j@                  t         j6                  jB                  t         j6                  jD                  t         j6                  jF                  t         j,                  j0                  
      jI                  t         j,                  t         j6                  jF                  t         j,                  jF                  k(        j%                  t         j,                  j.                  |k(  t         j6                  j8                  |k\  t         j6                  j8                  |k        jK                  t         j6                  j8                  jM                               jO                  d      jQ                         }g }|D ]  }|jS                  |j&                  |j8                  r$tU        ||j8                        jW                         nd|j:                  xs d|j<                  |j>                  xs d|j@                  xs d|jB                  rt        |jB                        nd|jD                  xs d|j0                  rdnd|jF                  d
        d|	j&                  |	jX                  |	jZ                  |	j\                  |	j0                  d|
||t_        |d      d||jW                         |jW                         ddS # t        $ r t        j                  |d      }Y w xY w# t        $ r. t        j                  |d      }|j                  ddd	      }Y w xY w# t`        $ rS}ddl1}te        d t        |              te         |jf                                t+        d!d"t        |             d}~ww xY ww)#a7  
    Get detailed statistics for a specific advisor within a date range.
    
    Args:
        request: Request body with advisor_id, start_date and end_date
        
    Returns:
        Dictionary with advisor statistics including calls missed, calls attended,
        and details of their last 10 calls
    r]   rO   rP   r   r   rh  r   r   r   r   r   r   rn   FTr   rb   r*  Nr   rK  rJ  rr  attendedrq  )
r   rF  r   r   r   rN  rO  rd  r   r:  )r   r   r   r   r   r+  )calls_missedcalls_attendedr-  attendance_rater   )r   r}   stats
last_callsr   z!Error in advisor-stats endpoint: r  z%Error retrieving advisor statistics: )4r   r   r  r   r@  r   r   r|  r}  r~  r  r  r   r  r  r   r&   r   r   r   r   r   r-   r;  r   rY  r   r   r<  rQ  rR  r   rN  rO  r  r:  r9  r   r   rd   r   r   r$   r   r   r   r   r>  r   r  r   r  )r  re   ry   r]   rO   rP   r  rB  rC  r}   r  r  r-  r  last_calls_queryr  rV  r   r  s                      rW   get_advisor_statsr  Y  s    "E
[[.
[[.
;;z*

!33JH j#&K!)!7!7
!C &--j(,,:K:K:MNNh$S'55h?+33Br3R
 $++Hhll6G6G6IJL ((6>>*11&..2C2Cz2QRXXZ)*Z@  xx 5 56==!!00J>!!((E1!!//>A!!//<?	

 %' 	 &"7"78??!!00J>!!((D0!!//>A!!//<?	

 %' 	 #^3BMPQ/>K7#=WX HH""..++--,,----//..%%,, T%%..&2G2G2V2VV V%%44
B...@..,>
 Xfoo4499;<U2YSU1 	8 
$DggZ^ZmZm22d6I6IJTTVsw!%!1!1!>Y"&"4"4 $ 1 1 7R!%!3!3!9r<@<N<NT%7%7!8T]!11>Y(,*"&"5"5  % jj))!(!6!6 ' 4 4!.. !-"0*#(!#<	 %,668(224!
 	
o  K!)!2!2:z!JK  S'00:F+33Br3RSH  
1#a&:;"i""$%:3q6(C
 	
	
st   \A,Z1 1Y AZ1 
)Y7 3UZ1 \Y40Z1 3Y44Z1 73Z.*Z1 -Z..Z1 1	\:A\\\z!/dashboard/call-details/{call_id}c                   K   	 |j                  t        j                        j                  t        j                  j                  | k(        j                         }|st        dd|  d      |j                  t        j                        j                  t        j                  j                  |j                  k(        j                         }d}|r|j                  r|j                  t        j                        j                  t        j                  j                  |j                  k(        j                         }|r3|j                  |j                  |j                  |j                  rdndd}d	|j                  |j                  |j                  |j                   xs d
|j"                  |j$                  xs d|j&                  xs d|j(                  xs d|j*                  rt-        |j*                        nd|j.                  xs dd
|dS # t0        $ rS}ddl}t5        dt-        |              t5         |j6                                t        ddt-        |             d}~ww xY ww)a!  
    Get detailed information about a specific call by its Twilio call ID.
    
    Args:
        call_log_id: The id of alpha_call_log table
        
    Returns:
        Dictionary with call details including customer information, recording URL,
        transcript, and call summary
    r   zCall with Twilio ID r   rn   Nr  rq  )r   r   r   r   Tr   rK  rJ  rr  )
rl   r:  rF  r   r   r   rq   rN  rO  rd  )r   call_detailstransfer_infor   z Error in call-details endpoint: r  zError retrieving call details: )r   r&   r   r   r   r   r   r-   r:  r;  r   r   r   r   rl   r<  rQ  rR  r   rq   rN  rO  r   r  r   r  r   r  )	rl   re   ry   rV  r  advisor_infor}   r   r  s	            rW   get_call_detailsr    s     9
xx(//OO')

%' 	 -gYjA  !6!67>>!!00D4G4GG

%' 	
 ]99hhv~~.55!!]%A%AAeg  !**#--$+$8$8,9,@,@jh	  <<"&"5"5!00!%!1!1!>Y"&"4"4 $ 1 1 7R"oo3!%!3!3!9r<@<N<NT%7%7!8T]!11>Y *
 	
"  
0Q9:"i""$%4SVH=
 	
	
s*   I4HH I4	I1AI,,I11I4z'/dashboard/download-recording/{call_id}c                 &  K   	 ddl m} |j                  |      j                  |j                  | k(        j                         }|st        dd|  d      |j                  }|st        dd|       t        ||       d{   \  }}|rt        d	d
|       |st        d	d      |S 7 *# t        $ rS}ddl
}	t        dt        |              t         |	j                                t        d	dt        |             d}~ww xY ww)z
    Download the MP3 recording for a specific call by its Twilio call ID.
    
    Args:
        twilio_call_id: The Twilio call ID to download the recording for
        
    Returns:
        Streaming response with the MP3 file
    r   )r   r   zCall with call_id z# not found in alpha_calls_log tablern   z.No Twilio call ID found for call with call_id Nr  zError streaming recording: z#Failed to create streaming responsez&Error in download-recording endpoint: zError downloading recording: )app.common.modelsr   r   r   rl   r   r   r:  rH   r   r  r   r   r  )
rl   re   ry   r   rV  r:  streaming_responseerrorr   r  s
             rW   download_recordingr  <  s>    +
. xx!(()9)9W)DEKKM+G94WX  ,,GGWX 
 +HXZ*[$[!E4UG< 
 "< 
 "! %\   
6s1vh?@"i""$%23q6(;
 	
	
s<   DBB2 B0)B2 /D0B2 2	D;AD		DDz/all-availablec                 $   K   t        |       }|S w)z8
    Get a list of all currently available advisors
    )r@   )re   ry   available_advisorss      rW   get_available_advisorsr  x  s      4B7r   z#/advisors/{advisor_id}/availabilityc                 &   K   t        ||       }|S w)z4
    Check if an advisor is currently available
    )r?   )r]   re   ry   availabilitys       rW   check_advisor_availabilityr    s      (J7Lr   z/advisors/time-statsc                    K   	 | j                   }| j                  }| j                  }t        j                  |t        j
                  j                               }t        j                  |t        j                  j                               }t        ||z
  j                  dz         D cg c]  }|t        |      z    }	}g }
||j                  t        j                        j                  t        j                  j                  |k(        j!                         }|st#        dd| d      t%        |||	|      }|
j'                  |       d	|j                  |j(                  d
|
|j+                         |j+                         ddS |j                  t        j                        j-                         }|s%d	g |j+                         |j+                         ddS |D ]   }t%        |||	      }|
j'                  |       " d	|
|j+                         |j+                         ddS c c}w # t.        $ rS}ddl}t3        dt5        |              t3         |j6                                t#        ddt5        |             d}~ww xY ww)av  
    Get aggregated statistics for an advisor's online time and calls within a date range.
    
    Args:
        request: JSON body with start_date, end_date, and optional advisor_id
        
    Returns:
        Dictionary with daily stats including online time, missed calls, and successful calls
        If advisor_id is not provided, returns stats for all advisors
    r+  r   Nr   r   r   rn   r   Tr   r   r   )r   r}   r   r   r   r   z&Error in advisor time stats endpoint: r  z%Error retrieving advisor time stats: )rO   rP   r]   r   r  r  r   r  ranger   r   r   r&   r   r   r   r   r   r  extendr   r   r   r   r  r   r   r  )r  re   ry   rO   rP   r]   rB  rC  idate_range_daysr   r}   r   ri   r   r  s                   rW   get_advisor_time_statsr    se     >f''
##''
!))*hll6G6G6IJ''(,,2C2C2EFEJHWaLaKgKgjkKkElmElJ)::Elm!hhv~~.55fnn6G6G:6UV\\^G#>NzlZd<eff,R/P\]LMM,'  !**#-- ","6"6"8 ( 2 2 4  xx/335H#&0&:&:&<$,$6$6$8#  $0WoNl+ $
  ","6"6"8 ( 2 2 4 S nd  f6s1vh?@"i""$%6[\_`a\b[c4dee	fsW   JB%H/ )H*?CH/ JAH/ J A	H/ )J*H/ /	J8AJJJc                 .   g }|D ]  }t        j                  |t         j                  j                               }t        j                  |t         j                  j                               }| j                  t        j                  t        j                  j                              j                  t        j                  j                  |j                  k(  t        j                  j                  |k(  t        j                  j                  dk7        j                         xs d}t!        |d      \  }}	t!        |	d      \  }
}t#        |      ddt#        |
      ddt#        |      d}| j                  t        j$                        j                  t        j$                  j&                  |j                  k(  t        j$                  j(                  dk(  t        j$                  j*                  |k\  t        j$                  j*                  |k        j-                         }| j                  t        j$                        j                  t        j$                  j&                  |j                  k(  t        j$                  j(                  dk(  t        j$                  j*                  |k\  t        j$                  j*                  |k        j-                         }|j/                  |j1                         |||||j                  |j2                  d	        |S )
zEGet time and call statistics for a specific advisor over a date rangeNr   rn  r'  ro  rp  FT)r   total_online_timer  r/  r.  r]   r,  )r   r  r  r   r  r   r   sumr&   LoginLogtotal_sessionr   r]   r   r\   r   r  r^   r-   r;  r   rY  r   r   r   r   )re   r}   r  r   day	day_startday_endr  r  r  r  r  r  r/  r.  s                  rW   r  r    s_   F$$S(,,*;*;*=>	""3(9(9(;< &//*G*G!HIPPOO&&'**4OO$$+OO))T1
 &(	 	 	 "-6y!)R0"5z"oQs7|B.?qWb@QR xx 5 56==!!00GJJ>!!((E1!!//9<!!//7:	

 %' 	 88F$9$9:AA!!00GJJ>!!((D0!!//9<!!//7:	

 %' 	 	MMO!2*( 0!**#--
 	A T MrV   z/advisors/daily-time-logsrequest_datac                 z  K   	 |j                  t        j                        j                  t        j                  j                  dk(        j                         }|rt        |j                        nd}| j                  }| j                  }|j                  t        j                        j                  t        j                  j                  |k(        j                         }|st        dd| d      |j                  t        j                        j                  t        j                  j                  |k(  t        j                  j                  |k(  t        j                  j                  dk7        j                  t        j                  j                         j#                         }g }	d}
|D ]  }|j                   t%        |	      z   }|j&                  r|j&                  t%        |	      z   nd}|j                  xs d}|
|z  }
t)        |d
      \  }}t)        |d      \  }}t        |      ddt        |      ddt        |      d}|	j+                  ||||d        t)        |
d
      \  }}t)        |d      \  }}t        |      ddt        |      ddt        |      d}d|j                  |j,                  d|j/                         |	||dS # t0        $ rS}ddl}t5        dt7        |              t5         |j8                                t        ddt7        |             d}~ww xY ww)zh
    Get detailed login/logout logs for an advisor on a specific day, adjusted for client timezone.
    TIMEZONE_OFFSETir   r   r   rn   Nr   )r  rn  r'  ro  rp  )
login_timelogout_timedurationduration_secondsTr  )r   r}   r\   	time_logs
total_timetimezone_offsetz+Error in advisor daily time logs endpoint: r  z*Error retrieving advisor daily time logs: )r   r&   rI   r   r   r   r^   valuer\   r]   r   r   r   r  r  r   r  r   r   r  r  r   r   r   r   r  r   r   r  )r  re   ry   timezone_settingr  r\   r]   r}   logsr  r  loglocal_loginlocal_logoutr  r  r  r  r  duration_strr  r   r  s                          rW   get_advisor_daily_time_logsr    s    Ck88FOO4;;OO  $55

%' 	 :J#.445r((!,,
 ((6>>*11&..2C2Cz2QRXXZC:J:,V`8abb xx(//OO&&*4OO$$0OO))T1
 (6??--
.ssu	 	 	C..9?+KKKQTQ`Q`3??Y_-MMfjL"005A--M  &&6=E9%i4GW!%j_Ac'l2->aGR?PQL)+($4	  * "-6y!)R0E
2aGR'8#g,r9JK
 jj)) !**,"$.

 
	
  k;CF8DE"i""$%6`adefag`h4ijj	ks*   L;KK L;	L8%AL33L88L;z
/customersr+  )ge)r  lerf  rg  c                 j   |dz
  |z  }| j                  t              j                  |      j                  |      j	                         }| j                  t              j                         }t        j                  ||z        }g }|D ]  }	|	j                  }
|	j                  }| j                  t        j
                  t        j                  j                              j                  t        j                  j                  |k(        j!                         }| j                  t        j
                  t        j"                  j                              j                  t"        j$                  |k(  t"        j&                  dk(        j!                         }| j                  t        j
                  t        j"                  j                              j                  t"        j$                  |k(  t"        j&                  dk7        j!                         }| j                  t        j(                  t        j                  j*                              j                  t        j                  j                  |k(        j!                         }|j-                  |	j                  |
|||||d       ! |||||ddS )Nr+  F)customer_idr   r   r-  r/  received_callslast_call_time)rf  rg  ry  total_customersr   r{  )r   r,   r   rd   r   r   r  r  r   r   r   r&   r   r   r   rR  r   r-   customer_numberr   r  r<  r   )re   ry   rf  rg  r   	customersr  ry  recordscustomerr   r   r-  r/  r  r  s                   rW   get_customersr  ^  s"    Qh)#F"))&177	BFFHIhhx(..0O))Oi78KG ..,, hhtzz&//*<*<=>EEOO))\9;;A68 	 xx

6+@+@+C+C DELL^MkMko{M{5C5J5Je5SUU[U[U] 	 $**V-B-B-E-E"FGNN~OmOmq}O}7E7L7LPU7UWW]W]W_ 	 $((6??+I+I"JKRROO))\9;;A68 	 	#;;*(&(,,
 	) D "&.	
 rV   c                   P    e Zd ZU  eddd      Zeed<    edddd	      Zeed
<   y)CustomerNameUpdate.r   q   )gtexampler  r+  rb   zUpdated Name)
min_length
max_lengthr  new_nameN)	rQ   rR   rS   r   r  r^   rT   r  r   rU   rV   rW   r  r    s*    SQ4K4#!^THcTrV   r  z/customers/update-name)ra   ro   payloadc                   K   |j                  t              j                  t        j                  | j                  k(        j                         }|st        t        j                  d      | j                  j                         |_        |j                          |j                  |       |j                  |j                  dS w)z
    Update customer name by ID (ID in request body).

    Client should send JSON like:
    {
        "customer_id": 113,
        "new_name": "New Customer Name"
    }
    Customer not foundrn   )r  r  )r   r,   r   r   r  r   r   r   rs   r  r  r   r   r   )r  re   ry   r  s       rW   update_customer_name_by_idr    s     " xx!((8K8K)KLRRTH11'
 	
 %--335HIIKJJx  {{** r   z/customers/detail/{customer_id}r  c                    |j                  t              j                  t        j                  | k(        j	                         }|st        dd      |j                  t        j                        j                  t        j                  j                  |j                  k(        j                  t        j                  j                  j                               j                  d      j                         }|r|d   j                  nd }|j                  t        j                  j                  t!        j"                  t        j                  j                        j%                  d            j                  t        j                  j                  |j                  k(        j'                  t        j                  j                        j                  t!        j"                  t        j                  j                        j                               j	                         }|d   }g }|D ]>  }|j                  t        j(                        j                  t        j(                  j                  |j*                  k(        j-                         }	|j                  t        j                        j                  t        j                  j                  |j                  k(        j-                         }|j/                  |j0                  |j2                  |j4                  |j                  |j6                  |j8                  |j                  |j:                  |	r|	j<                  nd d	       A |j4                  |j                  |||d}
d	|
iS )
Nr   r  rn   r*  r   r   )	rl   r:  r   	timestampr  rq   r  r  r,  )r   phonerecent_call_datetimeoverall_sentimentcall_recordsr   )r   r,   r   r   r   r   r&   r   rR  r   r   r<  r   rd   r   r  r   r   rP  group_byr   r;  r   r   rl   r:  r   rO  rq   r   r   )r  re   r  last_10_callsr  most_commonmost_common_sentimentcall_records_listrV  r}   records              rW   get_customer_by_idr    s   xx!(()CDJJLH4HII 	!	--1F1FF	G	&//00557	8	r	  ?L=+::QU 	OO++JJv667==gF	
 
--1F1FF	G	&//11	2	$**V__<<=BBD	E	  (N ((6>>*11&..2M2MtObOb2bcjjl88FOO,33FOO4P4PRVRdRd4delln  ||"11%33,,**//#33((18G--d
"
 
		 " "//&& 42)F FrV   z/catch-phrases/graphc                   K   | j                  dd      }| j                  dd      }|dz
  |z  }| j                  d      }| j                  d      }| j                  d      }| j                  d      }	| j                  d	d
      }
t        |t              r	 t        j                  |      }t        |t              r	 t        j                  |      }|rt        |      }|rt        |      }t        j                         }|s|t        d      z
  }|s|}t        j                  |t        j                  j                               }t        j                  |t        j                  j                               }|j                  t               j#                  t         j$                  dk(        j'                         }|st)        dd      |j*                  j-                  d      }|j/                  d      }|j                  t0        j2                        j#                  t0        j2                  j4                  |k\  t0        j2                  j4                  |k  t0        j2                  j6                  |j                  d      k(        }|r|j                  t0        j8                        j#                  t0        j8                  j:                  |k(        j'                         }|r6|j#                  t0        j2                  j<                  |j>                  k(        }|	rg }|	j/                  d      }|D ]m  }|jA                  tC        jD                  t0        j2                  jF                        jI                  d|j-                         jE                          d             o |j#                  tK        |       }|jM                         }|jO                  t0        j2                  j4                  jQ                               jS                  |      jU                  |      jM                         }|jW                         }tY        jZ                  ||z        }g }|D ]`  }g }|jF                  r|jF                  jE                         nd}|D ]4  }|j-                         jE                         |v s$|jA                  |       6 d}d}|j<                  {|j                  t0        j8                        j#                  t0        j8                  j>                  |j<                  k(        j]                         }|r|j^                  }|j>                  }|jA                  |j:                  |j`                  |jb                  |jd                  |j4                  |jf                  |jh                  |jj                  |||dd
       c |D ci c]!  }|j-                         jE                         d# } }|D ]`  }|jF                  s|jF                  jE                         }!|D ]2  }|j-                         jE                         }||!v s&| |xx   dz  cc<   4 b | jm                         D "cg c]
  \  }}"||"d }#}}"|#jo                  d d !       ||#||||d"d#S # t
        $ r t        j                  |d      }Y w xY w# t
        $ r. t        j                  |d      }|j                  ddd      }Y w xY wc c}w c c}"}w w)$z
        Get catch phrases graph data for a given date range.
        Returns catch phrases graph data along with total count.
    rf  r+  rg  r)  rO   rP   r]   catch_phrasesr   r  rh  r   r   r   r   r   CATCH_PHRASESr   z#Catch phrases not found in settingsrn   ",r&  rm  rK  N)r   r  )
r   rl   r:  r  r<  r   r   rq   catch_phrases_foundr}   r   )phraser   c                     | d   S )Nr   rU   r3  s    rW   r5  zbdc_dashboard.<locals>.<lambda>  s    !G*rV   Tr6  )rf  rg  ry  r-  )calls
graph_datar{  )8r   r@  r   r   r|  r}  r~  r  r1   r   r   r  r  r   r  r   rI   r   r   r   r   r  r  splitr&   r   r<  r=  r   r   r;  r   r   r   r  twilio_recording_textr  r    r   r   r   rd   r   r   r  r  r   r   rl   r:  r   rQ  rR  rq   itemsr?  )$r  re   ry   rf  rg  r   rO   rP   r]   filter_catch_phrasesr   r  rB  rC  catch_phrases_settingsr  catch_phrases_listcalls_log_data_queryr}   
conditionsphrasesr  calls_log_datacalls_log_data_paginatedr-  ry  retCallsrV  r  r	  r,  r  phrase_countstranscript_textr   r  s$                                       rW   bdc_dashboardr  "  s     ;;vq!DK,IQh)#F\*J{{:&H\*J";;7{{:'<=H*c"	C!//
;J (C 	G--h7H
 #J/
!(+LLNEYB//
%%j(,,2C2C2EFN##Hhll.?.?.ABLXXh/66(eg  "4YZZ*0066s;M&,,S188FOO4;;&&.8&&,6""l&6&67H&II ((6>>*11&..2C2Cz2QRXXZ#7#>#>v?]?]ahauau?u#v 
&,,S1Fdjj)N)NOTTWXY_YeYeYgYmYmYoXppqUrst 3::3
;KL)--/N3<<V__=[=[=`=`=bciijst{{  }C   D   H   H   J&,,.K))K)34KH( FJF`F` : : @ @ Bfh(F||~##%)>>#**62 ) *hhv~~.55fnn6Q6QSWSfSf6fgnnpG&00 ' 4 4''||"11(("11!--"00//#6$&
 	 )@ >PP=O6V\\^))+Q.=OMP %%"88>>@O,--/_,!&)Q.) -  +002
 3MFE 	
 3   OO,dO;  "&&	
	 	e  	C!**:zBJ	C  	G((:>H''R2'FH	Gj Qs{   B[8Z +[8<Z3 O[8(D[8<&[-"[86A[88$[8[2+"[8Z0,[8/Z00[833[*&[8)[**[8z/executive-summary/datac                   K   | j                  d      }| j                  d      }| j                  d      }| j                  dd      }t        j                         }|s|t        d      z
  }|s|}|j	                  t
        j                        j                  t
        j                  j                  |k(        j                         }|j	                  t
        j                        j                  t
        j                  j                  |k\  t
        j                  j                  |k        }	|	j                         }
|	j                  t
        j                  j                  t        j                  t
        j                  j                        j!                  d            j#                  t
        j                  j                        j%                  t'        d            j)                  d	      j+                         }|j	                  t
        j                  j                  t
        j                  j,                  t        j                  t/        t
        j0                  j2                  d
k(  df            j!                  d      t        j                  t/        t
        j0                  j2                  dk(  df            j!                  d            j5                  t
        j0                  t
        j0                  j6                  t
        j                  j                  k(        j                  t
        j0                  j8                  j;                  ||            j#                  t
        j                  j                  t
        j                  j,                        j+                         }|j	                  t
        j                  j                  t
        j                  j,                  t        j<                  t
        j                  j>                        j!                  d      t        j                  t/        t
        j                  j2                  dk(  df            j!                  d      t        j                  t/        t
        j                  j2                  dk(  df            j!                  d            j5                  t
        j                  t
        j                  j6                  t
        j                  j@                  k(        j                  t
        j                  j                  j;                  ||            j#                  t
        j                  j                  t
        j                  j,                        j+                         }|j	                  t
        j                  j                  t
        j                  j,                  t        jB                  t/        t
        j                  jD                  dk(  dft
        j                  jD                  dk(  dft
        j                  jD                  dk(  dfd            j!                  d      t        j                  t
        j                  jD                        j!                  d            jG                  t
        j                  t
        j                  j6                  t
        j                  j@                  k(        j                  t
        j                  j                  j;                  ||            j#                  t
        j                  j                  t
        j                  j,                        j+                         }d}|r<|j@                  r/|j	                  t
        j                  t
        j0                  j2                        j5                  t
        j0                  t
        j                  jH                  t
        j0                  jH                  k(        j                  tK        t
        j                  j                  |j@                  k(  t
        j                  j6                  |j@                  k(              j%                  t
        j                  j                  j'                               j+                         }|
|D cg c]  }|d   |d   d c}|D cg c]  }|d   |d   |d    |d!   d" c}|D cg c]  }|d   |d   |d    |d!   |d#   d$ c}|D cg c]%  }|d   |d   |d    rtM        |d          nd|d!   d%' c}|xs g D cg c]a  }|j                  j                  |j                  j>                  |j                  j                  |j2                  rd&n|j2                  d'nd(d)c c}d*S c c}w c c}w c c}w c c}w c c}w w)+zr
    Get executive summary for a given date range.
    Returns executive summary data along with total count.
    rO   rP   r]   r   r  r   r   
call_countr*  Fr+  r/  Tanswered_callstotal_call_timer   online_countr   offline_countPositive      ?Neutral        Negative      Nelse_avg_sentimentrated_callsr   )numberr   r5      )r]   r,  r/  r     )r]   r,  total_call_time_secondsonline_hoursoffline_hours)r]   r,  r%  r&  rG  rq  znot-transferred)rl   r  r   r   )incoming_callstop_callersadvisor_statsadvisor_time_statssentiment_statscustomer_history)'r   r   r  r   r   r&   r   r   r   r   r   r<  r   with_entitiesrR  r   rP  r  r   r   rd   r   r   r   r-   r   rS  r;  rY  betweenr  rO  r   r  r  r9  r:  r    r  )r  re   ry   rO   rP   r]   r   r  r}   rU  r-  r.  r/  r0  r1  r2  cstatrV  s                      rW   get_executive_summaryr7    s     \*J{{:&H\*J{{:'<=HJJLEYB//
hhv~~&--fnn.?.?:.MNTTVG ((6??+22&&*4&&(2K !&&(N 		OO))JJv))*00>

 
&////	0	$|$	%	r	  	NNNN$$JJtV2299UBAFGHNN~^JJtV2299TA1EFGMMN^_		
 
6((&*?*?*N*NRXR`R`RcRc*c	d	%%33;;JQ	R	&..##V^^%=%=	>	  	NNNN$$HHV__22399:KLJJtV^^22c91=>?EEnUJJtV^^22c91=>?EEoV	
 
6??FOO$B$BfnnFaFa$a	b	..66z8L	M	&..##V^^%=%=	>	   	NNNN$$HH__44
BCH__44	A3G__44
BDI	 eO$JJv667==mL	
 
foov==A\A\\	]	..66z8L	M	&..##V^^%=%=	>	# * 7''HH%%,, Y%%..&2G2G2V2VV VOO11W5I5IIOO22g6J6JJ Xfoo4499;<SU! 	( )ALMA1Q4!A$7M (
 ($	 #1g $Q $Q"&q'	
 (
 -
 -$ #1g $Q+/7 $Q!%a -
 *
 *$	 #1g $Q377tAw#Aw	
 *
 ,1r1
 2$	  ==++ MM77"mm::*.++,t{{G^8du	
 2
9$ $M



sC   b*g ,f'>g f,g $f1
g *f62
g <A&f;"g z/reports/incoming-calls-reportc           
        K   t        j                         j                  }| j                  t	        j
                  dt        j                  j                        j                  d      t	        j                  t        j                  j                        j                  d      t	        j                  t        t        j                  j                  dk(  dfd            j                  d            j!                  t        j                  t        j                  j"                  t        j                  j"                  k(        j%                  t	        j
                  dt        j                  j                        |k(  t        j                  j&                  |j)                  d	      k(        j+                  d      j-                  d      j/                         }g }|D ]q  }t1        |j2                        }|j5                  t6        |   |j8                  |j8                  r%t;        |j<                  |j8                  z  d
z        nd dd       s d|iS w)zU
    Get monthly incoming calls and missed call percentage for the current year.
    monthr-  Fr+  r   r#  r/  yearr&  rb   rm  )r9  r  rq  r   )r   r   r:  r   r   extractr&   r   r<  rP  r   r   r  r   r-   r   r9  r:  r   r=  r   r  r   r   r^   r9  r   rK   r-  r>  r/  )re   ry   current_yearr  r   row	month_idxs          rW   incoming_calls_reportr?  S	  s     <<>&&LHHWfoo<<=CCGL

6??%%&,,];v,,33u<a@JKQQR`a d&&&*?*?*N*NN fVV__;;<L""l&6&67H&II hw)##% 
 D		N		*__NQoo 0 03?? BcIJcdeefg
 	  D>s   IIz/reports/top-calling-numbersc                 .
  K   | j                  d      }| j                  d      }t        |t              r	 t        j                  |      }t        |t              r	 t        j                  |      }t        j                         }|s|t        d      z
  }|s|}|rt        |      }|rt        |      }t        j                  |t        j                  j                               }t        j                  |t        j                  j                               }|j                  t         j"                  j$                  t         j"                  j&                  t)        j*                  t         j"                  j,                        j/                  d	      t)        j                  t         j"                  j0                        j/                  d
      t)        j                  t         j"                  j2                        j/                  d      t)        j                  t         j"                  j4                        j/                  d      t)        j                  t         j"                  j6                        j/                  d      t)        j                  t         j"                  j8                        j/                  d      t)        j                  t         j"                  j:                        j/                  d      t)        j                  t         j"                  j<                        j/                  d      
      j?                  t         j@                  jB                  dk(  t         j"                  j0                  |k\  t         j"                  j0                  |k        jE                  t         j"                  j$                  t         j"                  j&                        jG                  tI        d	            jK                  d      jM                         }g }	|D ]  }
|	jO                  |
j&                  |
jP                  |
j2                  xs d|
j$                  |
jR                  |
jT                  rt        |
jT                        nd|
jV                  xs d|
j4                  |
j8                  |
j6                  d
        d|	iS # t
        $ r t        j                  |d      }Y w xY w# t
        $ r. t        j                  |d      }|j                  ddd      }Y w xY ww)a  
    Get top 10 calling numbers (numbers that called the most) with their details.
    
    Request body:
    {
        "start_date": "2023-01-01",  // Optional, defaults to 30 days ago
        "end_date": "2023-01-31"     // Optional, defaults to current date
    }
    rO   rP   rh  r   r   r   r   r   r  r  rQ  rl   r   r  last_durationlast_transcriptr}   r*  r   r   rK  )
r:  r<  r   r  r  r  rq   rl   r  r   r   ),r   r@  r   r   r|  r}  r~  r  r   r   r1   r  r  r   r  r   r&   r   rR  r:  r   r   r   rP  r<  rQ  rl   r   r  rO  rq   r   r   r   r  r   r   rd   r   r   r  r  rA  rB  )r  re   ry   rO   rP   r  rB  rC  	top_callsr   rV  s              rW   top_calling_numbersrD  t	  s     \*J{{:&H*c"	C!//
;J (C 	G--h7H
 LLNEYB//
#J/
!(+%%j(,,2C2C2EFN##Hhll.?.?.ABL 	OO))OO**JJv))*00>HHV__334::;KLHHV__00177FHHV__,,-33I>HHV__11288HHHV__445;;<MNHHV__22399/JHHV__//0667HI	
 
NN9,OO**n<OO**l:

 
&////1O1O	P	$|$	%	r	- 2 D"11"11!--:#11//373E3ED../3..4"||#33 --
 	  D>G  	C!**:zBJ	C  	G((:>H''R2'FH	GsM   3TR5 TS 1QT5STST3TTTTz/reports/worst-attendeesc                 t  K   | j                  d      }| j                  d      }t        |t              r	 t        j                  |      }t        |t              r	 t        j                  |      }t        j                         }|s|t        d      z
  }|s|}|rt        |      }|rt        |      }t        j                  |t        j                  j                               }t        j                  |t        j                  j                               }|j                  t         j"                  j$                  t'        j(                  t+        t-        t         j.                  j0                  d	k(  t         j.                  j2                  f                  j5                  d
      t'        j(                  t+        t-        t         j.                  j0                  dk(  t         j.                  j2                  f                  j5                  d      t'        j6                  t-        t'        j(                  t+        t         j.                  j2                              dk(  dft'        j8                  t-        t         j.                  j0                  d	k(  dfd            dz        d      j5                  d      t'        j6                  t-        t'        j(                  t+        t         j.                  j2                              dk(  dft'        j8                  t-        t         j.                  j0                  dk(  dfd            dz        d      j5                  d            j;                  t         j"                  j<                  dk(  t         j>                  j@                  |k\  t         j>                  j@                  |k        jC                  t         j.                  t         j.                  jD                  t         j"                  j2                  k(        j;                  t         j.                  jF                  |k\  t         j.                  jF                  |k        jI                  t         j"                  j$                        jK                  t'        j(                  t+        t         j.                  j2                              dkD        jM                  tO        d            jQ                  d      jS                         }g }	|D ]Q  }
|	jU                  |
j$                  |
jV                  |
jX                  |
jZ                   d|
j\                   dd       S d|	iS # t
        $ r t        j                  |d      }Y /w xY w# t
        $ r. t        j                  |d      }|j                  ddd      }Y Cw xY ww)z@
    Get top 10 worst call attendees based on missed calls.
    rO   rP   rh  r   r   r   r   r   Fr/  Tattended_callsr   rb   r+  r#  r5   missed_calls_percentageattended_calls_percentager}   r*  rm  )r,  r  r  average_missedaverage_attendedr   /r   r@  r   r   r|  r}  r~  r  r   r   r1   r  r  r   r  r   r&   r   r   r   r   r!   r   r-   r   r   rP  r>  r  r   r   r   r<  r9  r;  rY  r  havingr   r   rd   r   r   r/  rF  rG  rH  r  re   ry   rO   rP   r  rB  rC  r/  r   r6  s              rW   worst_call_attendeesrN  	  s^     \*J{{:&H*c"	C!//
;J (C 	G--h7H
 LLNEYB//
#J/
!(+%%j(,,2C2C2EFN##Hhll.?.?.ABL 	NN$$JJxf&;&;&B&Be&KVMbMbMeMe%f ghioop~JJxf&;&;&B&Bd&JFLaLaLdLd%e fghnno  AJJZZ)>)>)A)A BCqH#N((4)>)>)E)E)NPQ(RZ[#\]`cc  e-.JJZZ)>)>)A)A BCqH!L((4)>)>)E)E)Mq(QYZ#[\_bb  e/0#	
& 
NN9,OO**n<OO**l:

 
!!!!00FNN4E4EE

 
!!//>A!!//<?

 
&..**	+	

8F$9$9$<$<=>B	C	$01	2	r	M R D NN --"11!%!=!= >a@#'#A#A"B! D
 	  D>[  	C!**:zBJ	C  	G((:>H''R2'FH	GM   3V8U V8U> 1S'V8U;7V8:U;;V8>3V51V84V55V8z/reports/best-attendeesc                 t  K   | j                  d      }| j                  d      }t        |t              r	 t        j                  |      }t        |t              r	 t        j                  |      }t        j                         }|s|t        d      z
  }|s|}|rt        |      }|rt        |      }t        j                  |t        j                  j                               }t        j                  |t        j                  j                               }|j                  t         j"                  j$                  t'        j(                  t+        t-        t         j.                  j0                  d	k(  t         j.                  j2                  f                  j5                  d
      t'        j(                  t+        t-        t         j.                  j0                  dk(  t         j.                  j2                  f                  j5                  d      t'        j6                  t-        t'        j(                  t+        t         j.                  j2                              dk(  dft'        j8                  t-        t         j.                  j0                  d	k(  dfd            dz        d      j5                  d      t'        j6                  t-        t'        j(                  t+        t         j.                  j2                              dk(  dft'        j8                  t-        t         j.                  j0                  dk(  dfd            dz        d      j5                  d            j;                  t         j"                  j<                  dk(  t         j>                  j@                  |k\  t         j>                  j@                  |k        jC                  t         j.                  t         j.                  jD                  t         j"                  j2                  k(        j;                  t         j.                  jF                  |k\  t         j.                  jF                  |k        jI                  t         j"                  j$                        jK                  t'        j(                  t+        t         j.                  j2                              dkD        jM                  tO        d            jQ                  d      jS                         }g }	|D ]Q  }
|	jU                  |
j$                  |
jV                  |
jX                  |
jZ                   d|
j\                   dd       S d|	iS # t
        $ r t        j                  |d      }Y /w xY w# t
        $ r. t        j                  |d      }|j                  ddd      }Y Cw xY ww)zA
    Get top 10 best call attendees based on attended calls.
    rO   rP   rh  r   r   r   r   r   Fr/  TrF  r   rb   r+  r#  r5   rG  rH  r}   r*  rm  )r,  r  r  rI  avg_attendedr   rK  rM  s              rW   best_call_attendeesrR  -
  s^     \*J{{:&H*c"	C!//
;J (C 	G--h7H
 LLNEYB//
#J/
!(+%%j(,,2C2C2EFN##Hhll.?.?.ABL 	NN$$JJxf&;&;&B&Be&KVMbMbMeMe%f ghioop~JJxf&;&;&B&Bd&JFLaLaLdLd%e fghnno  AJJZZ)>)>)A)A BCqH#N((4)>)>)E)E)NPQ(RZ[#\]`cc  e-.JJZZ)>)>)A)A BCqH!L((4)>)>)E)E)Mq(QYZ#[\_bb  e/0#	
& 
NN9,OO**n<OO**l:

 
!!!!00FNN4E4EE

 
!!//>A!!//<?

 
&..**	+	

8F$9$9$<$<=>B	C	$23	4	r	M R D NN --"11!%!=!= >a@#==>a@
 	  D>[  	C!**:zBJ	C  	G((:>H''R2'FH	GrO  z/reports/time-utilisationc           
      
  K   | j                  d      }| j                  d      }t        |t              r	 t        j                  |      }t        |t              r	 t        j                  |      }t        j                         }|s|t        d      z
  }|s|}|rt        |      }|rt        |      }t        j                  |t        j                  j                               }t        j                  |t        j                  j                               }t        j                   }t        j"                  }	|j%                  t'        |	j(                  t*              j-                  d	            j/                  |	j(                  |k\  |	j(                  |k        j1                  t'        |	j(                  t*                    j3                  t5        j6                  |	j8                        d
kD        j;                         }
|j%                  |j<                  j-                  d      |j>                        j/                  |j@                  dk(        j;                         }|j%                  |jB                  jD                  |jB                  j>                  |
jB                  j(                        jG                  |      jI                  |
tK        d            j;                         }|j%                  |jB                  j(                  |jB                  j>                  t5        jL                  t5        j6                  |	j8                        d
      j-                  d            jO                  |	tQ        |	jD                  |jB                  jD                  k(  t'        |	j(                  t*              |jB                  j(                  k(              j1                  |jB                  j(                  |jB                  j>                        jS                  |jB                  j(                  |jB                  j>                        jU                         }g }|D ]  }|jV                  xs d
}tY        |d      \  }}tY        |d      \  }}t[        |      ddt[        |      ddt[        |      d}|j]                  |j(                  r|j(                  j_                         nd|j>                  |d        |dddddS # t
        $ r t        j                  |d      }Y w xY w# t
        $ r. t        j                  |d      }|j                  ddd      }Y w xY ww)z.
    Get advisor time utilisation report.
    rO   rP   rh  r   r   r   r   r   r\   r   r]   r}   truer  rn  r'  ro  rp  r   )r   r,  total_time_onliner+  r)  ry  rf  rg  r  )0r   r@  r   r   r|  r}  r~  r  r   r   r1   r  r  r   r  r&   r   r  r   r   r\   r   rP  r   r  rL  r   r  r  r  r   r   r   r5  r]   r  r9  r   coalescerS  r   r   r   r  r  r^   r   r   )r  re   ry   rO   rP   r  rB  rC  r   r  active_dates_subqadvisors_subqadvisor_dates
time_statsr   r6  r  r  r  r  r  time_strs                         rW   advisor_time_utilisationr]  
  s;     \*J{{:&H*c"	C!//
;J (C 	G--h7H
 LLNEYB//
#J/
!(+%%j(,,2C2C2EFN##Hhll.?.?.ABLnnGH
""D)//
;	
 
!!^3!!\1
3	$x(($/	0	//014	5	  	JJ\*	
 
	)	*	  	OO&&OO%%((	

 
]	#	!7	8	  	OO$$OO%%MM$((8#9#9:A>DDEXY	

 
##}'A'AAX&&-1I1II

 
-//**MOO,E,E	F	-//**MOO,E,E	F	 $ D..3!!-6y!)R0%j_Ac'l2%6aGR7HI15DMM++-C NN!)
 	  
 u  	C!**:zBJ	C  	G((:>H''R2'FH	GsM   3US2 UT 1RU2TUTU3UUUUz/reports/customer-ratingsc                   K   | j                  d      }| j                  d      }t        |t              r	 t        j                  |      }t        |t              r	 t        j                  |      }t        j                         }|s|t        d      z
  }|s|}|rt        |      }|rt        |      }t        j                  |t        j                  j                               }t        j                  |t        j                  j                               }|j                  t         j"                  j$                  t         j"                  j&                  t         j"                  j(                  t+        j,                  t/        t         j0                  j2                  d	k(  d
ft         j0                  j2                  dk(  dft         j0                  j2                  dk(  dfd            j5                  d      t+        j6                  t         j0                  j2                        j5                  d            j9                  t         j"                  j:                  dk(  t         j0                  j<                  |k\  t         j0                  j<                  |k        j?                  t         j0                  t         j0                  j@                  t         j"                  j(                  k(        jC                  t         j"                  j$                  t         j"                  j&                        jE                  t+        j6                  t         j0                  j2                        dkD        jG                  tI        d            jK                         }g }	|D ]  }
|
jL                  tO        |
jL                        nd}|dkD  rd	n|dk  rdnd}|	jQ                  |
j$                  |
j&                  |
j(                  tS        |d      ||
jT                  d        d|	iS # t
        $ r t        j                  |d      }Y w xY w# t
        $ r. t        j                  |d      }|j                  ddd      }Y  w xY ww)zF
    Get advisor-wise customer ratings based on sentiment scores.
    rO   rP   rh  r   r   r   r   r   r  r  r  r   r!  r"  Nr#  r%  r&  r}   r   r5   )r]   r,  r  average_sentimentsentiment_categorytotal_rated_callsr   )+r   r@  r   r   r|  r}  r~  r  r   r   r1   r  r  r   r  r   r&   r   r   r   r   r   r  r   r   r  rP  r   r   r   r<  r9  r;  r  rL  r   r   r   r%  r  r   r>  r&  )r  re   ry   rO   rP   r  rB  rC  r1  r   r6  r%  r`  s                rW   advisor_customer_ratingsrb  
  sn     \*J{{:&H*c"	C!//
;J (C 	G--h7H
 LLNEYB//
#J/
!(+%%j(,,2C2C2EFN##Hhll.?.?.ABL 	NNNN$$NN''HH__44
BCH__44	A3G__44
BDI	 eO$JJv667==mL	
 
NN9,OO**n<OO**l:

 
OOOO**fnn.I.II

 
NNNN$$

 


6??::;a?	@	$'	(	? D D595G5G5Sd001YZ+81+<ZP]`aPa*gp'' NN!..!&}a!8"4!%!1!1
 		   D>U  	C!**:zBJ	C  	G((:>H''R2'FH	GsM   3Q5P Q5P; 1N$Q5P84Q57P88Q5;3Q2.Q51Q22Q5z/customers/searchz'Search by customer name or phone numberqc           
         |j                  t        j                        j                  t	        t        j                  j
                  j                  d|  d      t        j                  j                  j                  d|  d                  j                  d      j                         }|D cg c]&  }|j                  |j
                  |j                  d( c}S c c}w )z
    Search customers by name or phone number (case-insensitive, partial match).
    Returns: id, customer_name, customer_phone
    rm  r*  )r   r   r   )r   r&   r,   r   r    r   r   r   rd   r   r   )rc  re   ry   resultsr  s        rW   search_customersrf  Z  s     	!	--33as!H=,,22Qqc8<

 
r	 $    H	 ++%33&33	

    s   0+Cz/customers/call-historyc                 
   | j                  d      }| j                  dd      }| j                  dd      }| j                  d      }| j                  d      }|st        dd	
      |dkD  rd}t        |t              r	 t	        j
                  |      }t        |t              r	 t	        j
                  |      }t	        j                         }|s|t        d      z
  }|s|}|rt        |      }|rt        |      }t	        j                  |t        j                  j                               }	t	        j                  |t        j                  j                               }
|j!                  t"        j$                        j'                  t"        j$                  j(                  |k(        j+                         }|st        dd
      |dz
  |z  }|j!                  t"        j,                        j'                  t"        j,                  j.                  |j0                  k(  t"        j,                  j2                  |	k\  t"        j,                  j2                  |
k        j5                         }t7        j8                  ||z        }|j!                  t"        j,                  t"        j:                  j<                  j?                  d            jA                  t"        j:                  t"        j,                  jB                  t"        j:                  j0                  k(        j'                  t"        j,                  j.                  |j0                  k(  t"        j,                  j2                  |	k\  t"        j,                  j2                  |
k        jE                  t"        j,                  j2                  jG                               jI                  |      jK                  |      jM                         }tO        tP              }|D ]  \  }}|jR                  xs djU                         }|dk(  rd}n
|dk(  rd}nd}||j2                  jW                            jY                  |j(                  |jZ                  |jR                  |||j\                  |j^                  |j2                  |j`                  |jb                  d
        g }te        |jg                         d      D ]  }|jY                  |||   d        |jh                  |j0                  |||||ddS # t        $ r t	        j                  |d      }Y w xY w# t        $ r. t	        j                  |d      }|j                  ddd      }Y w xY w)Nr  rf  r+  rg  r)  rO   rP   i  zCustomer ID is requiredrn   rb   rh  r   r   r   r   r   r   r  r,  rK  positivenegativerr  )
r   r:  rd  sentiment_iconr,  r  r  r   rq   rl   T)r8  )r   r  rV  )r   r   r-  historyr{  )5r   r   r@  r   r   r|  r}  r~  r  r   r   r1   r  r  r   r  r   r&   r,   r   r   r   r   rR  r   r<  r   r  r  r   r   rP  rS  r;  r   r   r   rd   r   rL   listr  r  r   r   r:  r   rO  rq   rl   sortedkeysr   )r  re   ry   r  rf  rg  rO   rP   r  rB  rC  r  r   r-  ry  r  groupedrV  r,  rd  rj  rk  r   s                          rW   get_customer_call_historyrp  z  sk    ++m,K;;vq!DK,I\*J{{:&H4MNN3	*c"	C!//
;J (C 	G--h7H
 LLNEYB//
#J/
!(+%%j(,,2C2C2EFN##Hhll.?.?.ABLxx(//0B0Bk0QRXXZH4HIIQh)#F((6??+226??3P3PT\TiTi3i39??3Q3QUc3c39??3Q3QUa3a5 6;UW	 
 ))K)34K 	OONN$$**>:	
 
NNOO**fnn.I.II

 
--1F1FF...@..,>

 
&//00557	8		y		# 
( $G#l))/R668	
"'N*$'N&N##((*+22''"11--,(((++''//||4
 	 $, Gw||~t4T]
 	 5 "//"//"&"

 
q  	C!**:zBJ	C  	G((:>H''R2'FH	Gs$   ?T %T4 T10T143U+*U+z/call/processc                 `  K   | j                          d {   }|j                  d      }|st        d      |j                  t        j
                        j                  t        j
                  j                  |k(        j                         }|st        d|      	 t        ||       d {    t        j                  d      |j                          S 7 7 ,# t        $ r0}t        j                  d      cY d }~|j                          S d }~ww xY w# |j                          w xY ww)Nrl   zCall ID is requiredCallzCall processed successfully.)r   z/Something went wrong while processing the call.)jsonr   r3   r   r&   r   r   r   r   r2   r9   r4   postcloser   r  )r  re   ry   r   rl   rV  r   s          rW   process_callrv    s      Dhhy!G23388FOO$++FOO,>,>',IJPPRD00$T2...}}%CD 	
   	/ Y~~&WXX

Y 	
sd   D.CBD.C .C/C D.C 	D&D;D<D  D.DD D++D.)r  r  fastapir   r   r   r   r   r   r	   r
   sqlalchemy.ormr   typingr   r   r   r   r   r   r   r   r   pydanticr   r   
sqlalchemyr   r   r   r   r   r   r   r   r   r    r!   r"   fastapi.responsesr#   )app.advisor_service.services.time_servicer$   
app.commonr%   r&   firebase_adminr'   r(   loggingapp.common.ai_helpersr)   app.common.constantsr*   r  r+   r,   r-   app.common.databaser.   app.common.twillio_helperr/   r0   app.common.utilsr1   app.utils.exceptionsr2   r3   app.utils.responser4   services.advisor_servicer6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   services.auth_utilsrA   services.dashboard_servicerB   rC   rD   rE   zoneinforF   -app.twilio_service.services.recording_servicerG   rH   rI   &auth_service.services.settings_servicerJ   calendarrK   collectionsrL   r]  routerCertificatecredr   initialize_apprN   rY   r[   r`   r   r   r^   rj   r   rw   r   r   r   rt  UpdateTokenRequestr   r   AdvisorDetailr   HTTP_201_CREATEDr   putAdvisorUpdater   deleter   r   patchr   boolr   r  r	  r  r  r  rD  rX  ra  r  r  r  r  r  r  r  AdvisorDailyTimeLogResponser  dictr  r  HTTP_200_OKr  r  r  r7  r?  rD  rN  rR  r]  rb  rf  rp  rv  rU   rV   rW   <module>r     s     Y Y Y " , , > > % m m m m / K &  & $  4 ( < < & W + C '    1   r & >  # 	{@A d   d #(y (y i 
%i %
 KW__(=>&/
 	 ?4 12).s@g)h H3 H 3H" %&q&AB&/ 0RRR R 'Rh ,-&/ 0000 .0d ./&/ 0    0 D #$ &/ 0((  
#s(^	 %  )*&/ 0 
#s(^ +@ $W5J5JK &/ 0222 2 L2 [f&=&=>c&/ 0999 9 ?9v $W__E &/ 0	#I#I""#I 	#I 	#I F#IJ '( &/ 0888 8 )8 3DDYZ &/ 0  [ ,W__M &/ 0	KKK 	K 	K NK )* c.&/ 0	 	 	
 
 +B $% ;t&/ 0	$
$
$
 	$
 	$

 
#s(^$
 &$
L $% ;t&/ 0	,
,
,
 	,
 	,

 
#s(^,
 &,
\ %& ;t&/ 0	$
$
$
 	$
 	$

 
#s(^$
 '$
L  ! ;t %d8N O&/ 0+
+
+
 +
 		+

 +
 
#s(^+
 "+
Z  &/ 0F
F
F
 F
 
#s(^	F
 F
P %& $S	&/ 0t
t
t
 t
 
#s(^	t
 't
l &'%*4[#(;r'IJ&/ 0\
"\
x \
 \
 		\

 \
 
#s(^\
 (\
|"x "D " "#"3i&/ 0w
#s(^w
w
 w
 
#s(^	w
 $w
r '( #3i&/ 0	U
#s(^U
 	U
 	U

 
#s(^U
 )U
n /0 &/ 0H
H
H
 H
 
#s(^	H
 1H
T 56 &/ 09
9
9
 9
 79
v T$sCx.-AB&/ 0 C 1$sCx.Q &/ 0			 	 R	 #$'+Cy&/ 0Mf$MfMf Mf %Mf`.` (9\9\]$(I&/ 0Kk!KkKk Kk 
#s(^	Kk ^KkZ L.!(")."9$Q1~$)"s$;Vw VV "V /VpU U
 % ++  - '+3ifo$^4# -> -dC7>v ?C ?W ? D?F #$"3i&/ 0Q#s(^QQ Q %Qh %&"3i&/ 0Y#s(^YY Y 'Yv ,-&/ 0 .@ +,"3i&/ 0W#s(^WW W -Wr '("3i&/ 0\#s(^\\ \ )\| &'"3i&/ 0\#s(^\\ \ (\| ()"3i&/ 0o#s(^oo o *ob ()"3i&/ 0X#s(^XX X *Xv  3$MN&/ 0
  !> &'"3i&/ 0v#s(^vv v (vp _ &/ 0  rV   