o
    g~                     @   s  d dl mZmZmZmZmZmZmZmZ d dl	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mZ d dlmZ d dl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%m&Z&m'Z' d dl(m)Z) d dl*m+Z+m,Z,m-Z-m.Z.m/Z/ d dl0m0Z0m1Z1 d dl2m3Z3m4Z4m5Z5 d dl6Z6d dl7Z7d dl8Z8d dl9Z9d dl:Z:d dl;m<Z< e=dZ>e7?e>Z@W d   n1 sw   Y  de@d  de@d  de@d  de@d  ZAeeAddddddZBe%ddeBd ZCe# ZDG d!d" d"eDZEG d#d$ d$eDZFG d%d& d&eDZGeDjHjIeBd' G d(d) d)e3ZJG d*d+ d+eJZKG d,d- d-e3ZLG d.d/ d/eJZMG d0d1 d1e3ZNG d2d3 d3e3ZOG d4d5 d5e3ZPG d6d7 d7ePZQG d8d9 d9ePZRG d:d; d;e3ZSG d<d= d=eSZTG d>d? d?eSZUe<d@gdAdBZVe8jWXdCe8YdDZ Z[dEZ\dFZ]dGdH Z^dIdJ Z_dKdL Z`ddMeadNe1fdOdPZbedQdRZcdSefdTdUZdeedee^fdQeedVe'fdWdXZfeeffdYeEfdZd[Zged\d]Zhehjiee8jWXdCe8YdDZ d^ ed_d`Zjehjkdaedbd`dcdd G dedf dfZlel ZmehndgdSefdhdiZoddSedkeedleefdmdnZpehjXde
doee^fdSedVe'fdpdqZqehjXdre
dodSefdsdtZrehjXdue
dodSefdvdwZsehjXdxe
dodSefdydzZtehjXd{e
doee^fdSedVe'fd|d}ZuehjXd~e
doee^fdSedevdVe'fddZwehjwdeOde ee^fdedVe'fddZxehjXde
dodSefddZyehjwde
doededededededee^fdSedeedeedeedeedeedeedVe'fddZzehjXde
doddSede+ee fddZ{ehjXde
doeefee^fdSedYeEdVe'fddZ|ehjXde
doeeffdSedYeEfddZ}ehwdeefee^fdSedYeEdVe'fddZ~ehjXde
doeefee^fdSedevdYeEdVe'fddZehjXde
doeegee^fdSedYeEdVe'fddZehjXde
ddeefee^fdSedYeadVe'fddZehjXde
ddeefee^fdSedYeadVe'fddZehjXde
ddeefee^fdSedYeEdVe'fddZehjXde
ddeeffdSedYeafddZehjXde
ddeefee^fdevdSedYeEdVe'fddZehjXde
ddeefee^fdevdSedYeadVe'fddZehXddSefddZehjXde
dodSefddZehjXde
ddeefee^fdSedYeadVe'fddZehjXde
ddeefee^fdevdSedYeadVe'fddńZehjXde
ddeefee^fdevdSedYeadVe'fddȄZehjXde
ddeefee^fdevdSedYeadVe'fdd˄ZehjXde
ddeeffdSedYeafdd΄ZehjXde
ddeefee^fdevdSedYeadVe'fddфZehjXde
ddeefee^fdSedYeEdVe'fddZehjXde
ddeefee^fdSedYeEdVe'fddZehjXde
ddeefee^fdevdSedYeEdVe'fddZehjXde
ddeefee^fdevdSedYeEdVe'fddZehjXde
ddeeffdSedYeEfddZehjXde
ddeefee^fdSedYeEdVe'fddZehjXde
ddeefee^fdevdSedYeEdVe'fddńZehjXde
ddeefee^fdSedYeEdVe'fddZehjXde
ddeefee^fdSedYeEdVe'fddZehjXde
ddeefee^fdevdSedYeEdVe'fddȄZehjXde
ddeefee^fdevdSedYeEdVe'fdd˄ZehjXde
ddeeffdSedYeEfdd΄ZehjXde
ddeefee^fdevdSedYeEdVe'fddфZedkrd dlZejddddd dS dS )    )FastAPIDependsHTTPExceptionstatusRequestFormFile
UploadFile)HTMLResponseRedirectResponseJSONResponse)StaticFiles)Jinja2Templates)OAuth2PasswordBearerOAuth2PasswordRequestForm)SessionMiddleware)BaseHTTPMiddleware)	create_engineColumnIntegerStringTextEnumDateTime
ForeignKeyJSON)declarative_base)sessionmakerrelationshipSession)func)OptionalListDictAnyUnion)datetime	timedelta)	BaseModelEmailStrFieldN)CryptContextzdb_config.yamlzmysql+pymysql://
mysql_user:mysql_password@
mysql_host/mysql_dbTi  
      F)pool_pre_pingpool_recycle	pool_sizemax_overflowecho)
autocommit	autoflushbindc                   @   s   e Zd ZdZeeddZeeddddZeeddddZ	eedddZ
eedZeedZeed	d
ddd	dZeee dZedddZedddZdS )UserusersTprimary_keyd   F)uniquenullable   rC   clientadmin
role_typesnamedefaultBlogPostauthorback_populatesQuestionnaireuserN)__name__
__module____qualname____tablename__r   r   idr   usernameemailpassword
first_name	last_namer   roler   r    now
created_atr   
blog_postsquestionnaires rb   rb   )/home/mproulx/AI/FinPlanner/server/app.pyr=   )   s    r=   c                   @   s   e Zd ZdZeeddZeedddZee	ddZ
eeedddZeedZeee d	Zeee e d
ZedddZdS )rM   r`   Tr?      FrE   users.idrD   rK   rL   onupdater=   rO   N)rS   rT   rU   rV   r   r   rW   r   titler   contentr   	author_id	image_urlr   r    r^   r_   
updated_atr   rN   rb   rb   rb   rc   rM   8   s    rM   c                   @   s   e Zd ZdZeeddZeeedddZee	dZ
eeZeedd	d
ddddZeee dZeee e dZedddZdS )rQ   ra   Tr?   re   FrE   rd   draft	submittedreviewedstatus_typesrI   rK   rf   r=   rO   N)rS   rT   rU   rV   r   r   rW   r   user_idr   rh   r   datar   r   r   r    r^   r_   rl   r   rR   rb   rb   rb   rc   rQ   E   s    rQ   )r<   c                   @   s>   e Zd ZU eed< eed< dZee ed< dZee ed< dS )UserBaserX   rY   Nr[   r\   )	rS   rT   rU   str__annotations__r)   r[   r!   r\   rb   rb   rb   rc   rs   V   s
   
 rs   c                   @      e Zd ZU eed< eed< dS )
UserCreaterZ   confirm_passwordNrS   rT   rU   rt   ru   rb   rb   rb   rc   rw   \      
 rw   c                   @   rv   )	UserLoginrX   rZ   Nry   rb   rb   rb   rc   r{   `   rz   r{   c                   @   s4   e Zd ZU eed< eed< eed< G dd dZdS )UserResponserW   r]   r_   c                   @      e Zd ZdZdS )zUserResponse.ConfigTNrS   rT   rU   from_attributesrb   rb   rb   rc   Configi       r   N)rS   rT   rU   intru   rt   r&   r   rb   rb   rb   rc   r|   d   s
   
 r|   c                   @   s&   e Zd ZU eed< eed< eed< dS )	TokenDatarX   rq   r]   N)rS   rT   rU   rt   ru   r   rb   rb   rb   rc   r   l   s   
 r   c                   @   rv   )Tokenaccess_token
token_typeNry   rb   rb   rb   rc   r   q   rz   r   c                   @   s.   e Zd ZU eed< eed< dZee ed< dS )BlogPostBaserh   ri   Nrk   )rS   rT   rU   rt   ru   rk   r!   rb   rb   rb   rc   r   u   s   
 r   c                   @      e Zd ZdS )BlogPostCreateNrS   rT   rU   rb   rb   rb   rc   r   z       r   c                   @   <   e Zd ZU eed< eed< eed< eed< G dd dZdS )BlogPostResponserW   rj   r_   rl   c                   @   r}   )zBlogPostResponse.ConfigTNr~   rb   rb   rb   rc   r      r   r   NrS   rT   rU   r   ru   r&   r   rb   rb   rb   rc   r   }      
 r   c                   @   s2   e Zd ZU eed< dZeed< eeef ed< dS )QuestionnaireBaserh   rm   r   rr   N)rS   rT   rU   rt   ru   r   r#   r$   rb   rb   rb   rc   r      s   
 r   c                   @   r   )QuestionnaireCreateNr   rb   rb   rb   rc   r      r   r   c                   @   r   )QuestionnaireResponserW   rq   r_   rl   c                   @   r}   )zQuestionnaireResponse.ConfigTNr~   rb   rb   rb   rc   r      r   r   Nr   rb   rb   rb   rc   r      r   r   bcryptauto)schemes
deprecated
SECRET_KEY   HS256<   c                  c   s   d } d}d}||k r_z
t  } | d W nI tyZ } z9| r#|   ||d k rEtd| d|d  d| dd	d
 |d7 }td ntd| dd	d
  W Y d }~nd }~ww ||k sz[z| V  W nJ ty } z>td| d	d
 t|trdt|v sdt|v sdt|v sdt|v rtdd	d
 |   t  } | V  n W Y d }~nd }~ww W | r|   d S d S | r|   w w )N   r   zSELECT 1   zDatabase connection error: z. Retrying... (r1   )Tflushz(Failed to connect to the database after z	 attemptszDatabase operation error: 20132006zMySQL server has gone awayzLost connectionz1MySQL connection lost. Attempting to reconnect...)	SessionLocalexecute	Exceptioncloseprinttimesleep
isinstancert   )dbmax_retriesretry_counterb   rb   rc   get_db   sZ   
$


r   c                 C   s   t | |S N)pwd_contextverify)plain_passwordhashed_passwordrb   rb   rc   verify_password   s   r   c                 C   s
   t | S r   )r   hash)rZ   rb   rb   rc   get_password_hash      
r   rr   expires_deltac                 C   sN   |   }|rt | }n	t ttd }|d|i tj|tt	d}|S )Nminutesexp)	algorithm)
copyr&   utcnowr'   ACCESS_TOKEN_EXPIRE_MINUTESupdatejwtencoder   	ALGORITHM)rr   r   	to_encodeexpireencoded_jwtrb   rb   rc   create_access_token   s   r   token)tokenUrlrequestc                    s   | j d}|r|dr|dd}tddd |S | jd}|r,tddd |S | jd	}|r<td
dd |S tddd ttj	dddid)NAuthorizationBearer  z#Token found in Authorization headerTr   r   zToken found in cookiesr   z0Token found in URL query parameters (deprecated)zNo token found in requestzNot authenticatedWWW-AuthenticateBearerstatus_codedetailheaders)
r   get
startswithreplacer   cookiesquery_paramsr   r   HTTP_401_UNAUTHORIZED)r   authorizationr   token_cookietoken_paramrb   rb   rc   get_token_from_request   s(   r   r   c              
      s  t tjdddid}td| d d  ddd	 z0tj| ttgd
}|d}td| dd	 |d u r;td |t	||d|dd}W n t
yb } ztdt| dd	 |d }~ww |ttj|jk }|d u rtd| ddd	 |td|j d|j  |S )NzCould not validate credentialsr   r   r   z Authenticating user with token: r3   z...Tr   
algorithmssubz&Token decoded successfully, username: z!Username is None in token payloadrq   r]   )rX   rq   r]   z#Exception during token validation: zUser z not found in databasez$Authentication successful for user: z, role: )r   r   r   r   r   decoder   r   r   r   r   rt   queryr=   filterrX   firstr]   )r   r   credentials_exceptionpayloadrX   
token_datar   rR   rb   rb   rc   get_current_user   s4   
r   current_userc                    s   | j dkrtddd| S )NrG   i  zNot enough permissionsr   r   )r]   r   )r   rb   rb   rc   get_admin_user  s   
r   zFinancial Planner)rh   )
secret_keyz../UI/templates)	directoryz/staticz../UI/staticstaticrI   c                   @   s8   e Zd Zdd ZddedefddZdd	 Zd
d ZdS )MessageStorec                 C   s
   g | _ d S r   messagesselfrb   rb   rc   __init__0  r   zMessageStore.__init__infotextcategoryc                 C   s   | j ||d d S )Nr   r   )r   append)r   r   r   rb   rb   rc   add_message3  s   zMessageStore.add_messagec                 C   s   | j S r   r   r   rb   rb   rc   get_messages6  s   zMessageStore.get_messagesc                 C   s   | j  }g | _ |S r   )r   r   )r   r   rb   rb   rc   clear9  s   
zMessageStore.clearNr   )rS   rT   rU   r   rt   r   r   r   rb   rb   rb   rc   r   /  s
    r   httpc              
      s  d }t ddd d }| jd}t d| dd |r-|dr-|dd}t ddd |s?| jd	}|r?|}t d
dd |rz-tj|tt	gd}|d}t d| dd |rmt
t }|ttj|k }W n ty }	 zt dt|	 dd W Y d }	~	nd }	~	ww zt| dr| jdg ng }
W n ttfy   t }
Y nw || j_|
| j_t | j_|| I d H }|S )Nztesting middlewareTr   r   zAuthorization header: r   r   z#Found token in Authorization headerr   z#Found token in URL query parametersr   r   zDecoded token, username: zToken validation error: sessionr   )r   r   r   r   r   r   r   r   r   r   nextr   r   r=   r   rX   r   r   rt   hasattrr   popAssertionErrorAttributeError_message_storer   staterR   r   r&   r^   )r   	call_nextrR   r   r   r   r   rX   r   r   r   responserb   rb   rc   add_context_dataB  sJ   

" r	  r   r   r   c              	   C   sX   zt | jdsg | jd< | jd ||d W d S  ttfy+   t|| Y d S w )Nr   r   )r  r   r   r  r  r  r   )r   r   r   rb   rb   rc   flash_messagex  s   
r
  )response_classc              	      s   | tjtjtjtjtjtjtj	
ttj d }g }|D ]}|j|j|jd d |j|j|j|j	d}|| q%td| |t | jj| jjdS )Nr   rd   rW   rh   excerptrk   r_   r[   r\   z
index.htmlr   postsr^   rR   r   )r   rM   rW   rh   ri   rk   r_   r=   r[   r\   joinorder_bydesclimitallr   	templatesTemplateResponser&   r^   r  rR   r   )r   r   latest_postsr  post	post_dictrb   rb   rc   index  s6   	r  z/aboutc                    $   t d| t | jj| jjdS )Nz
about.htmlr   r^   rR   r   r  r  r&   r^   r  rR   r   r   rb   rb   rc   about     r  	/servicesc                    r  )Nzservices.htmlr  r  r  rb   rb   rc   services  r   r"  /contactc                    r  )Nzcontact.htmlr  r  r  rb   rb   rc   contact  r   r$  /blogc              	      s   | tjtjtjtjtjtjtj	
ttj  }g }|D ]}|j|j|jd d |j|j|j|j	d}|| q"td| |t | jj| jjdS )Nrd   r  zblog/blog.htmlr  )r   rM   rW   rh   ri   rk   r_   r=   r[   r\   r  r  r  r  r   r  r  r&   r^   r  rR   r   )r   r   
posts_datar  r  r  rb   rb   rc   blog  s6   	r'  z/blog/post/{post_id}post_idc              	      s   | tjtjtjtjtjtjtj	
ttj|k }|s&tddd|j|j|j|j|j|j|j	d}td| |t | jj| jjdS )N  zPost not foundr   )rW   rh   ri   rk   r_   r[   r\   zblog/post.html)r   r  r^   rR   r   )r   rM   rW   rh   ri   rk   r_   r=   r[   r\   r  r   r   r   r  r  r&   r^   r  rR   r   )r   r(  r   r  r  rb   rb   rc   r    s4   
r  z/token)response_model	form_datac              	      s   | ttj| jk }|rt| j|js"ttj	dddidt
td}t|j|j|jd|d}t|d|j|jd	}tjd
ddk}|jd|d|dtd dd |S )NzIncorrect username or passwordr   r   r   r   )r   rq   r]   )rr   r   bearer)r   r   rX   r]   ENVIRONMENTdevelopment
productionr   Tstrictr   r1   )keyvaluehttponlysecuresamesitemax_agepath)r   r=   r   rX   r   r   rZ   r   r   r   r'   r   r   rW   r]   r   osenvironr   
set_cookie)r+  r   rR   access_token_expiresr   r  cookie_securerb   rb   rc   login_for_access_token  s<   

r=  z	/registerc                    s   t d| t dS )Nauth/register.html)r   r^   r  r  r&   r^   r  rb   rb   rc   register_form.  s   r@  .rX   rY   rZ   rx   r[   r\   c                    s   ||krt d| dt dS |ttj|ktj|kB 	 }|r1t d| dt dS t
|}	t|||	||d}
||
 |  tdddS )	Nr>  zPasswords do not match)r   errorr^   z Username or email already exists)rX   rY   rZ   r[   r\   z/login?success=registrationi/  )urlr   )r  r  r&   r^   r   r=   r   rX   rY   r   r   addcommitr   )r   rX   rY   rZ   rx   r[   r\   r   existing_userr   new_userrb   rb   rc   register2  s6   

rG  z/loginsuccessc                    s*   d }|dkr	d}t d| |t dS )Nregistrationz+Registration successful! You can now login.zauth/login.html)r   messager^   r?  )r   rH  rJ  rb   rb   rc   
login_form]  s   rK  z/client/dashboardc              	      sr   t ddd t d|j dd |ttj|jk }t dt| d t	
d| ||t | jjdS )	NzClient dashboard accessedTr   z#Client dashboard accessed by user: zFound z questionnaires for userclient/dashboard.htmlr   ra   rR   r^   r   )r   rX   r   rQ   r   rq   rW   r  lenr  r  r&   r^   r  r   r   r   r   ra   rb   rb   rc   client_dashboardi  s$   

rP  z/client/questionnairec                    s    t d| |t | jjdS )Nclient/questionnaire.html)r   rR   r^   r   )r  r  r&   r^   r  r   r   r   rb   rb   rc   questionnaire_form  s   rS  z/client/questionnaire/savec           
         s   |   I d H }t|}|ddt d }|dd}t|}|d}|rT|t	
t	jt|kt	j|jk }	|	sJtddd	id
S ||	_||	_||	_nt	|j|||d}	||	 |  ||	 dd|	jdS )Nrh   zQuestionnaire z%Y-%m-%dr   rm   questionnaire_idr)  rA  Questionnaire not found)r   ri   )rq   rh   rr   r   Tz Questionnaire saved successfully)rH  rJ  rT  )formdictr   r&   r^   strftimejsondumpsr   rQ   r   rW   r   rq   r   r   rh   rr   r   rC  rD  refresh)
r   r   r   r+  rr   rh   r   	json_datarT  questionnairerb   rb   rc   save_questionnaire  sF   





r^  z(/client/questionnaire/{questionnaire_id}rT  c              	      sV   | ttj|ktj|jk }|stdddtd| ||t	
 | jjdS )Nr)  rU  r   rQ  )r   r]  rR   r^   r   )r   rQ   r   rW   rq   r   r   r  r  r&   r^   r  r   )r   rT  r   r   r]  rb   rb   rc   load_questionnaire  s$   

r_  z/admin/dashboardc                    s   | ttjdk }| t }| t }| ttjtj	ttj
dktj d }td| |||||t | jjdS )NrF   rn      admin/dashboard.html)r   rR   
user_count
post_countquestionnaire_countrecent_submissionsr^   r   )r   r=   r   r]   countrM   rQ   r[   r\   r  r   r  r_   r  r  r  r  r  r&   r^   r  r   )r   r   r   rb  rc  rd  re  rb   rb   rc   admin_dashboard  s0   
rg  z/admin/blog/newadmin_blog_post_new)r  rJ   c                    sN   |r|j dkrtddS |ttj ddg }td| ||dS )'Admin page for creating new blog posts.rG   /auth/loginrB  advisoradmin/admin_blog_post_new.html)r   rR   authors)	r]   r   r   r=   r   in_r  r  r  r   r   r   rn  rb   rb   rc   rh    s   
 z/admin/questionnairesadmin_questionnairesc                    sJ   |r|j dkrtddS |ttjtjt }t	
d| ||dS )'Admin page for managing questionnaires.rG   rj  rk  admin/questionnaires.html)r   rR   ra   )r]   r   r   rQ   r=   r[   r\   r  r  r  r  rO  rb   rb   rc   rq    s   


z/admin/usersadmin_usersc                    s<   |r|j dkrtddS |t }td| ||dS )Admin page for managing users.rG   rj  rk  admin/users.html)r   rR   r>   )r]   r   r   r=   r  r  r  r   r   r   r>   rb   rb   rc   rt  $  s   
z/admin/users/newadmin_user_newc                    s,   |r|j dkrtddS td| |dS )#Admin page for creating a new user.rG   rj  rk  admin/user-form.html)r   rR   r]   r   r  r  rR  rb   rb   rc   rx  6  s   
z/admin/users/{user_id}admin_user_viewrq   c                    X   |r|j dkrtddS |ttj| k }|s"tdddt	d|||dS )	'Admin page for viewing a specific user.rG   rj  rk  r)  User not foundr   admin/user-view.html)r   rR   viewed_user
r]   r   r   r=   r   rW   r   r   r  r  rq   r   r   r   rR   rb   rb   rc   r|  E     
z/admin/users/{user_id}/editadmin_user_editc                    r}  )	Admin page for editing a user.rG   rj  rk  r)  r  r   rz  )r   r   rR   r  r  rb   rb   rc   r  \  r  z/debug/authc              
      sf  t | j}td| dd |dd}td| dd d}|dr+|dd	}d|v ||du|d
}|rz[tj|tt	gd}d|d< |d|d|d|dd|d< |dt
t  |drx|dt
t   nd|dr|dt
t  k ndd|d< W |S  ty } zd|d< t||d< W Y d}~|S d}~ww |S )z.Debug endpoint to check authentication headerszDEBUG AUTH - Request headers: Tr   r   z	Not foundz#DEBUG AUTH - Authorization header: Nr   r   )auth_header_existsauth_headertoken_extractedall_headersr   token_validr   rq   r]   r   )r   rq   r]   r   token_payload)exp_timestampcurrent_timestampexpires_in_seconds
is_expiredtoken_expirationFtoken_error)rW  r   r   r   r   r   r   r   r   r   r   r&   r^   	timestampr   rt   )r   r   r  r   resultr   r   rb   rb   rc   
debug_auth  sF   


&&
r  z/client/templates/dashboardc              
      s6   t d td| g ddddt ddd	gd
S )zGDebug endpoint that renders the client dashboard without authenticationz6Accessing client dashboard template directly (no auth)rL  
debug_userDebugr=   )rX   r[   r\   z+This is a debug view without authenticationwarningr   rM  )r   r  r  r&   r^   r  rb   rb   rc   client_templates_dashboard  s   

r  z/admin/blog-postsadmin_blog_postsc              	      sh   |r|j dkrtddS |tjtjtjtjtjt	j
t	jt	tj  }td| ||dS )#Admin page for managing blog posts.rG   rj  rk  admin/blog-posts.html)r   rR   r  )r]   r   r   rM   rW   rh   ri   rk   r_   r=   r[   r\   r  r  r  r  r  r  r   r   r   r  rb   rb   rc   r    s    
z /admin/blog-posts/{post_id}/editadmin_blog_post_editc                    sz   |r|j dkrtddS |ttj| k }|s"tddd|ttj 	ddg
 }td||||d	S )
#Admin page for editing a blog post.rG   rj  rk  r)  Blog post not foundr   rl  admin/blog-editor.html)r   rR   r  rn  )r]   r   r   rM   r   rW   r   r   r=   ro  r  r  r  r(  r   r   r   r  rn  rb   rb   rc   r    s   
 z'/admin/questionnaire/{questionnaire_id}admin_questionnaire_viewc                    j   |r|j dkrtddS |ttjtjttj	| k
 }|s)tdddtd||||jdS )	0Admin page for viewing a specific questionnaire.rG   rj  rk  r)  rU  r   admin/questionnaire-view.htmlr   rR   r]  rr   r]   r   r   rQ   r=   r[   r\   r  r   rW   r   r   r  r  rr   rT  r   r   r   r]  rb   rb   rc   r    $   

z./admin/questionnaire/{questionnaire_id}/reviewadmin_questionnaire_reviewc                    r  )	CAdmin page for reviewing and providing feedback on a questionnaire.rG   rj  rk  r)  rU  r   admin/questionnaire-review.htmlr  r  r  rb   rb   rc   r  7  r  z/admin/analyticsadmin_analyticsc              	      s   |r|j dkrtddS dddddd	d
dd}ddddddddddddddddg}ddddddd d!d"d#d$dd%d&d'd(d)dg}td*| ||||d+S ),Admin analytics dashboard.rG   rj  rk  -         )@   皙 @  ffffff.@4  @	new_usersuser_growth_trendrd  questionnaire_trend
page_viewspage_views_trend
blog_viewsblog_views_trendr1     2m 15srB  viewsavg_timer%  E  3m 45sr!    2m 30sr#     1m 30sRetirement Planning Basics      5m 20sApr 15, 2023rh   r  commentsavg_read_timepublished_at#Investment Strategies for Beginners      4m 45sMay 2, 2023Tax Planning Tipsn      3m 30sJun 10, 2023admin/analytics.html)r   rR   statspopular_pagestop_blog_postsr{  r   r   r  r  r  rb   rb   rc   r  Q  s<   




z./admin/questionnaire/{questionnaire_id}/reportadmin_generate_reportc                    sb   |r|j dkrtddS |tttj| k }|s%t	dddt
d||||jdS )	DAdmin page for generating a financial report based on questionnaire.rG   rj  rk  r)  rU  r   admin/report-generator.htmlr  )r]   r   r   rQ   r  r=   r   rW   r   r   r  r  rr   r  rb   rb   rc   r  |  s   
 z/adminc           	         s   |r|j dkrtddS |t }|t }|t }|ttjdk }|tt	ttjdk
tj d }|t
tj d }td| |||||||t d	S )zAdmin dashboard page.rG   rj  rk  rn   r`  ra  )	r   rR   rb  rd  rc  pending_review_countre  recent_usersr^   )r]   r   r   r=   rf  rQ   rM   r   r   r  r  rl   r  r  r  r_   r  r  r&   r^   )	r   r   r   rb  rd  rc  r  re  r  rb   rb   rc   rg    s4   
 c                    sN   |r|j dkrtddS |tttj }t	d| ||t
 dS )ru  rG   rj  rk  rv  )r   rR   r>   r^   )r]   r   r   r=   options
joinedloadra   r  r  r  r&   r^   rw  rb   rb   rc   rt    s    

c                    sj   |r|j dkrtddS |tttjtj| k	 }|s(t
dddtd|||t dS )	r~  rG   rj  rk  r)  r  r   r  )r   rR   r  r^   )r]   r   r   r=   r  r  ra   r   rW   r   r   r  r  r&   r^   )rq   r   r   r   r  rb   rb   rc   r|    s$   

c                    s^   |r|j dkrtddS |ttj| k }|s"tdddt	d|||t
 dS )	r  rG   rj  rk  r)  r  r   rz  )r   r   rR   r^   )r]   r   r   r=   r   rW   r   r   r  r  r&   r^   r  rb   rb   rc   r    s   
c                    s2   |r|j dkrtddS td| |t dS )ry  rG   rj  rk  rz  )r   rR   r^   r]   r   r  r  r&   r^   rR  rb   rb   rc   rx    s   
c                    Z   |r|j dkrtddS |tttjtj	 
 }td| ||t dS )r  rG   rj  rk  r  )r   rR   r  r^   )r]   r   r   rM   r  r  rN   r  r_   r  r  r  r  r&   r^   r  rb   rb   rc   r        

c              	      s   |r|j dkrtddS |ttj| k }|s"tddd|tt	tj dktj dk
 }td||||t d	S )
r  rG   rj  rk  r)  r  r   rl  r  )r   rR   r  rn  r^   )r]   r   r   rM   r   rW   r   r   r=   or_r  r  r  r&   r^   r  rb   rb   rc   r  )  s    
&c                    sZ   |r|j dkrtddS |tttj dktj dk }td| ||t	
 dS )ri  rG   rj  rk  rl  rm  )r   rR   rn  r^   )r]   r   r   r=   r   r  r  r  r  r&   r^   rp  rb   rb   rc   rh  F  s   
&c                    r  )rr  rG   rj  rk  rs  )r   rR   ra   r^   )r]   r   r   rQ   r  r  rR   r  rl   r  r  r  r  r&   r^   rO  rb   rb   rc   rq  Z  r  c              	      n   |r|j dkrtddS |tttjtj| k	 }|s(t
dddtd||||jt dS )	r  rG   rj  rk  r)  rU  r   r  r   rR   r]  rr   r^   r]   r   r   rQ   r  r  rR   r   rW   r   r   r  r  rr   r&   r^   r  rb   rb   rc   r  p  &   

c              	      r  )	r  rG   rj  rk  r)  rU  r   r  r  r  r  rb   rb   rc   r    r  c              
      s   |r|j dkrtddS dddddd	d
dd}ddddddddddddddddg}ddddddd d!d"d#d$dd%d&d'd(d)dg}td*| ||||t d+S ),r  rG   rj  rk  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  r  r  r  r  r  r  r  r  r  r  r  r  r  r  )r   rR   r  r  r  r^   r  r  rb   rb   rc   r    s>   




c              	      r  )	r  rG   rj  rk  r)  rU  r   r  r  r  r  rb   rb   rc   r    r  __main__zapp:appz0.0.0.0i@  )hostportreloadr   r   )fastapir   r   r   r   r   r   r   r	   fastapi.responsesr
   r   r   fastapi.staticfilesr   fastapi.templatingr   fastapi.securityr   r   starlette.middleware.sessionsr   starlette.middleware.baser   
sqlalchemyr   r   r   r   r   r   r   r   r   sqlalchemy.ext.declarativer   sqlalchemy.ormr   r   r   sqlalchemy.sqlr    typingr!   r"   r#   r$   r%   r&   r'   pydanticr(   r)   r*   r   yamlr8  rY  r   passlib.contextr+   openf	safe_load	db_configDATABASE_URLenginer   Baser=   rM   rQ   metadata
create_allrs   rw   r{   r|   r   r   r   r   r   r   r   r   r   r9  r   urandomhexr   r   r   r   r   r   rW  r   oauth2_schemer   rt   r   r   appadd_middlewarer  mountr   r  
middlewarer	  r
  r  r  r"  r$  r'  r   r  r=  r@  rG  rK  rP  rS  r^  r_  rg  rh  rq  rt  rx  r|  r  r  r  r  r  r  r  r  r  rS   uvicornrunrb   rb   rb   rc   <module>   s  ( ,
,	
,
  

5!  %*1&&&T,&*&#&&&&+
