
    xi                     
   d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dl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 d dlmZmZ d dlmZmZ d dlmZ d d	lmZ d d
lmZ d dl Z d dl!m!Z!m"Z" d dl#m$Z% d dl&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z- d dl.m/Z/ d dl0m1Z1 ddl2 d dl3 d dl4 d dl5m6Z6 d dl7m8Z8 d dl9m:Z: d dl;m<Z<  e
       Z= e       Z> ej~                  ej                          ej                  eB      ZC e        dZD e j                  dd      ZF e j                  dd      ZGe=j                  de/j                        ddddd  ee%j                        fdeKdeKdeKd eKd!eLd"eLd#efd$       ZMe=j                  d%e/j                         ee%j                        fd&e/j                  d#efd'       ZPe=j                  d(e/j                         ee%j                        fd)eKd#efd*       ZQe=j                  d+e/j                         ee%j                        fd)eKd#efd,       ZRe=j                  d-e/j                         ee%j                        fd)eKd.e/j                  d#efd/       ZTe=j                  d0e/j                        d1 ee%j                        fd)eKd&e/j                  d2eKd#efd3       ZW ee%j                        fd)eKd4e/j                  d#efd5ZYe=j                  d6e/j                         ee%j                        fd)eKd#efd7       Z[e=j                  d8e/j                         ee%j                        fd)eKd9eLd#efd:       Z\e=j                  d;      d<eKfd=       Z]e=j                  d>       ee%j                        fd)eKdeLd#efd?       Z^ ee%j                        fd)eKd#efd@Z_e=j                  dA      dB ee%j                        fd)eKdCeKd#efdD       Z`e=j                  dE       ee%j                        fd)eKd#efdF       Zae=j                  dG       ee%j                        fd)eKd#efdH       Zbe=j                  dI       ee%j                        fd)eKd#efdJ       Zce=j                  dK       ee%j                        fdeKd#efdL       Zde=j                  dM       ee%j                        fdNeKdOeKd#efdP       ZedeLfdQZfe=j                  dR       ee%j                        fdeLd#efdS       Zgy)T    N)List)	APIRouterDependsRequestHTTPExceptionstatus)
HTTPBearerHTTPAuthorizationCredentials)jsonable_encoder)JSONResponseFileResponse)Session
joinedload)text)load_dotenv)BeautifulSoup)datetimetimezone)CoursesCourseModulesUserUserCourseLogAccessTokenLMSPlatformLMSCourseLog   )*)CourseCreator)	S3Service)process_course_celery)AsyncResult)levelz0^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$OUTPUT_FOLDERz./resultS3_DIRSyllabuild_Coursesz/list)response_modelReady
   emailuser_idcourse_statussearchlimitoffsetdbc           
        K   	 t        || |       d{   }t        j                  d|       |d   1t        t        j
                  t        j
                  d|d    d      S |j                  t              j                  t        j                  d	k(        j                  t        j                  j                               }| r"|j                  t        j                  | k(        }|r"|j                  t        j                  |k(        }|rd
| d
}	|j                  t        j                  j                  |	      t        j                   j                  |	      z  t        j"                  j                  |	      z  t        j$                  j                  |	      z  t        j&                  j                  |	      z  t        j(                  j                  |	      z        }|j+                         }
|j-                  |      j/                  |      j1                         }|st3        dg       S |D cg c]!  }t4        j6                  j9                  |      # }}t;        |      }t        t        j
                  t        j
                  d||
||d      S 7 c c}w # t<        $ r}t?        ddtA        |             d}~ww xY ww)zB
    Get list of all courses with pagination (limit & offset)
    r*   r)   r/   Nz	Token: %saccess_tokenzInvalid or expired token.redirect_url)r   messager3   status_codecontentno%zNo courses found.zData retrieved successfully)r   r4   datatotalr-   r.     Something went wrong: r6   detail)!validate_tokenloggerinfor   r   HTTP_200_OKqueryr   filter
is_deletedorder_by
created_atdescr)   topicilikeskillsdegreemode_of_deliverytonelanguagecountr.   r-   allsuccessResponseschemasCoursesResponsefrom_ormr   	Exceptionr   str)r)   r*   r+   r,   r-   r.   r/   tokencourses_querysearch_patternr;   coursescoursecourse_dataencoded_dataes                   ./var/www/html/content_weaver/routers/course.pyget_coursesrb   (   s{    9W$WEbIIK' ("..$00:',^'<&=  )001C1Ct1KLUUV]VhVhVmVmVop)00%1GHM)00=1PQM ]N)00$$^4%%n57%%n57 ))//?A ##N3	5
 !!''79M ##%&&v.44U;??A"# 
 OVVFw..77?VV'4** ,,8$ 

 
	
Y JR W  W6LSQRVH4UVVWsd   K	J JAJ %K	&G	J /K	0J 4&J<J K	J J 	K(KKK	z/creater]   c                   K   	 t        j                  d       dt        j                          }| j	                         }||d<   d|d<   d|d<   g d}t        j                  t        |d	         s,t        t        j                  t        j                  d
d      S |D ]\  }||vs||   r|j                  dd      j                         }t        t        j                  t        j                  | dd      c S  |d   rVt        |d         dkD  rt        d      S t        |d         dk  rt        d      S |d   j                         st        d      S |j!                  t"              j%                  t"        j&                  |d	   k(        j)                         }|r|j*                  |d<   nd|d<   t-        |d   |      d   dk  rt        d      S t/        d i |}|j1                  |       |j3                          |j5                  |       |j!                  t.              j%                  t.        j6                  |k(        j)                         } t9        d|        t;        t<        j>                  jA                  |       j	                               }	tC        d|	      S # tD        $ r}
tG        ddtI        |
             d}
~
ww xY ww)!z
    Create a new course
    COURSE_PREFIX-	course_idPendingr   r   course_step)rJ   r)   rL   rM   allocated_timerN   rO   rP   taxonomyoutlinelearning_approachno_of_modulesr)   zEmail: Invalid value.r   r4   r5   _  is required.rJ   d   z4Topic is too long. Maximum length is 100 characters.   z3Topic is too short. Minimum length is 5 characters.z$Topic contains non-ASCII characters.r*   Nr*   r/   available_creditszQInsufficient course credits. Please purchase more credits to create a new course.zCourse created with ID: zCourse created successfullyr<   r=   r>    )%osgetenvuuiduuid4dictrematchEMAIL_REGEXr   r   HTTP_400_BAD_REQUESTreplace
capitalizelenerrorResponseisasciirD   r   rE   r)   firstidfetch_total_course_creditsr   addcommitrefreshrf   printr   rT   rU   rV   rS   rW   r   rX   )r]   r/   rf   r^   required_fieldsfield
filed_nameuser
new_courser_   r`   s              ra   create_courser   p   s    XW		/231TZZ\NC	kkm#,K  )H%&M"
 xx[%9:"77$996  % 		EK'{5/A"]]34??A
# & ; ;"("="=&0\#? 		 w;w'(3.$J  ;w'(1,$I  w'//1$:  xx~$$TZZ;w3G%GHNNP%)WWK	"%)K	"%	*
  "## !c  +{+

z
		


:'"))'*;*;y*HIOOQ" 	(45'(?(?(H(H(P(U(U(WX)
 	
  W6LSQRVH4UVVWsz   KBJ& KJ& +AJ& ;K<!J& KJ& 9K:J& KA=J& KCJ& %K&	K/KKKz/regenerate/{course_id}rf   c                   K   	 |j                  t              j                  t        j                  | k(        j	                         }|st        d      S |j                  st        d      S t        j                  |j                  |       }t        d|j                          |j                  |_        d|_        |j                          |j                  |       t        t         j"                  j%                  |      j'                               }t)        d|      S # t*        $ r}t-        ddt/        |             d	}~ww xY ww)
z0
    Regenerate course content by course_id
    Course not found.z/Course topic is required to regenerate content.Regeneration Task ID: 
Processingz*Course regeneration initiated successfullyr<   r=   r>   N)rD   r   rE   rf   r   r   rJ   r    delayr   r   task_idr   r   r   r   rT   rU   rV   r{   rS   rW   r   rX   )rf   r/   r]   taskr_   r`   s         ra   regenerate_courser      s     W'"))'*;*;y*HIOOQ #  || A  %**6<<C&twwi01$
		


6'(?(?(H(H(P(U(U(WX8
 	
  W6LSQRVH4UVVWsB   EAD ED *E+B2D E	E'E  EEz/get/{course_id}c                 .  K   	 |j                  t              j                  t        j                  | k(        j	                         }|st        d      S t        j                  j                  |      j                         }|j                  r?t        j                  |j                        }|j                  dk(  r|j                  }||d<   |d   |d<   t        |      }t!        d|      S # t"        $ r}t%        ddt'        |             d	}~ww xY ww)
)
    Get course details by course_id
    r      markdown_contentcourse_contentzCourse retrieved successfullyr<   r=   r>   N)rD   r   rE   rf   r   r   rT   rU   rV   r{   markdown_urlrequestsgetr6   r   r   rS   rW   r   rX   )rf   r/   r]   r^   responser   r_   r`   s           ra   
get_courser      s    W'"))'*;*;y*HIOOQ #  --66v>CCE||F$7$78H##s*#+== 2B./(34F(G$%'4+
 	
  W6LSQRVH4UVVWs6   DAC+ DBC+ *D+	D4DDDz/generate-ai	form_datac                 z  K   	 |j                  t              j                  t        j                  | k(        j	                         }|st        d      S |j                  st        d      S |j                         }|d   }|d   }g d}||vrt        ddj                  |             S |r-|dk(  r(||_	        |j                          |j                  |       t        |	      }|d
k(  rd}	n|}	|j                  |	      }
t        |||
       |j                          |j                  |       t        t         j"                  j%                  |      j                               }t'        |j)                  dd      j+                          d|      S # t,        $ r}t/        ddt1        |             d}~ww xY ww)z0
    Generate AI content for a course field
    r   z0Course topic is required to generate AI content.
field_typerj   )content_descriptioncontent_outcomesrl   z'Invalid field type. Valid options are: , r   r]   r   zcourse descriptionro   rp   z generated successfullyr<   r=   r>   N)rD   r   rE   rf   r   r   rJ   r{   joinrj   r   r   r   generate_ai_contentsetattrr   rT   rU   rV   rS   r   r   rW   r   rX   )rf   r   r/   r]   formr   rj   valid_fieldscourse_creatorcontent_type
ai_contentr_   r`   s                ra   generate_ai_courser     s    3W'"))'*;*;y*HIOOQ #  || B  ~~,'

#
 \) 9$))L:Q9RS  
&88&FOIIKJJv&
 ../L%L#77E
 	
J/
		


6'(?(?(H(H(P(U(U(WX!!#s+66899PQ
 	
  W6LSQRVH4UVVWsN   F;AF F;F *F;+>F )F;*C&F F;	F8F33F88F;z/update/{course_id}1stepc                   K   	 |j                  t              j                  t        j                  | k(        j	                         }|st        d      S |dk(  rg d}n(|dk(  rg d}n|dk(  rg d}n|dk(  rd	g}nt        d
      S t        |      |_        |j                         }|D ]\  }||vs||   r|j                  dd      j                         }t        t        j                  t        j                  | dd      c S  |j                         j                         D ]  \  }	}
|
s	t        ||	|
        |j!                          |j#                  |       |j                  t              j                  t        j                  | k(        j	                         }t%        j&                  dd      j)                         dk(  r|dk(  rt+        d       t-        j.                  |j0                  |       }t+        d|j2                          |j2                  |_        d|_        |j!                          |j#                  |       |j                  t6              j                  t6        j2                  |j8                  k(        j	                         }t;        |j8                  |j<                  dd      }|j?                  |       |j!                          nt+        d       t@        jB                  jE                  |      j                         }tG        |      }tI        d|      S # tJ        $ r}tM        ddtO        |             d}~ww xY ww)z0
    Update an existing course by course_id
    r   r   )rJ   r)   rL   rM   ri   rN   rO   rP   2)rj   r   r   3)level_of_difficultytype_of_assessmentno_of_questionsrm   rk   rl   4module_titlez*Invalid step. Valid steps are: 1, 2, or 3.ro   rp   rq   rn   r5   CELERY_ENABLEDFalsetruez7Celery is enabled, processing course in the background.r   r   r   Debit)r*   platform_idnumber_of_coursetypez7Celery is not enabled, processing course synchronously.zCourse updated successfullyr<   r=   r>   N)(rD   r   rE   rf   r   r   intrh   r{   r   r   r   r   r   itemsr   r   r   rw   rx   lowerr   r    r   rJ   r   r   r   r*   r   r   r   rT   rU   rV   r   rS   rW   r   rX   )rf   r]   r   r/   existing_courser   r^   r   r   keyvaluer   r   r   UserCourseLogEntryr_   r`   s                    ra   update_courser   Y  s    aW((7+2273D3D	3QRXXZ #  3;O S[O S[O S[O !<  !Ykkm$ 		EK'{5/A"]]34??A
# & ; ;"("="=&0\#? 		 !++---/ 	5JCe4	5 			


?#HHW-44W5F5F)5STZZ\99%w/5576AdckKL" )../@/F/F	RD*477)45(,%'3$IIKJJ()88D>((4E4M4M)MNTTVD!.)11 ,,!"	" FF%&IIKKL--667HINNP'4)
 	
  W6LSQRVH4UVVWs[   MAL, M1L, M.L, 5AL, M'L, .G=L, +M,	M5MMMmodule_datac           	         t        | |j                  |j                  |j                  |j                  |j
                  |j                        }|j                  |       |j                          |j                  |       |S )z1
    Helper function to save a course module
    )rf   r   module_subtopicestimated_time
assessmentrecommended_resoursesrL   )
r   r   r   r   r   r   rL   r   r   r   )rf   r   r/   
new_modules       ra   save_course_moduler     sp      --#33"11)))??!!J FF:IIKJJz    z/delete/{course_id}c                   K   	 |j                  t              j                  t        j                  | k(        j	                         }|st        d      S d|_        t        j                  t        j                        |_        |j                          t        di       S # t        $ r}t        ddt!        |             d}~ww xY ww)z&
    Delete a course by course_id
    r   yeszCourse deleted successfullyr<   r=   r>   N)rD   r   rE   rf   r   r   rF   r   nowr   utc
deleted_atr   rS   rW   r   rX   )rf   r/   r   r`   s       ra   delete_courser     s     W((7+2273D3D	3QRXXZ #  &+"%-\\(,,%?" 			)
 	
  W6LSQRVH4UVVWs6   C	AB C	A
B C		C(CCC	z/{course_id}/citation/{index}indexc                   K   	 |j                  t              j                  t        j                  | k(        j	                         }|st        d      S |j                  rt        j                  |j                        ng }|dk  s|t        |      k\  rt        d      S ||   }t        dd|i      S # t        $ r}t        ddt        |             d	}~ww xY ww)
z9
    Get citation for a specific index in the course
    r   r   zIndex out of range.zCitation retrieved successfullycitationr<   r=   r>   N)rD   r   rE   rf   r   r   weblinksjsonloadsr   rS   rW   r   rX   )rf   r   r/   r]   r   r   r`   s          ra   get_citationr     s     W'"))'*;*;y*HIOOQ #  39//4::foo.r19X. %  E?-"
 	
  W6LSQRVH4UVVWsB   CAB2 CA
B2 CB2 1C2	C;CCCz/task/{task_id}r   c                   K   t        |       }|j                  dk(  r|j                  ddS |j                  dk(  r)|j                  |j                  j                  dd      dS |j                  dk(  rdddS |j                  d	k(  rd
dt	        |j                        dS |j                  d|j
                  t	        |j                        |j                  dS w)NPENDINGr   )stateprogressPROGRESSr   SUCCESS	COMPLETEDrr   FAILUREFAILED)r   r   error)r   r   r   result	traceback)r!   r   rB   r   rX   r   r   r   )r   task_results     ra   get_task_statusr     s     g&KI%$**::			j	( &&#((,,Z;
 	

 
		i	'$#66			i	'!q3{?O?O;PQQ ""$$k(() ** s   CCz/import-coursec           	        K   	 |j                  t              j                  t        j                  | k(        j	                         }|st        d      S |j                  }t        |j                  dd      j                  dd            }t        | |       d{   }|j                  t              j                  t        j                  |k(        j	                         }|j                  t              j                  t        j                  |j                  k(        j	                         }|r+|j                  rt        j                   |j                        ng }	|	r|	d   d   nd}
t#        ||j$                  |	       d{   }t'        | |
|j                  ||d
   ||       d{   }t)        j*                  d      }t(        j,                  j/                  ||      }t(        j,                  j1                  |      rt3        j4                  |       t7        dd|i      S 7 7 7 # t8        $ r"}t        dt;        |       d      cY d}~S d}~ww xY ww)z$
    Import course by course_id
    r   rp   ro   /)rf   r/   Nr   r   r1   r2   WORKING_DIRzCourse imported successfully
imscc_pathr=   r<   )rD   r   rE   rf   r   r   rJ   truncate_filenamer   upload_imscc_on_s3r   r   r   r   accountsr   r   r@   r)   create_and_migrate_courserw   rx   pathr   existsshutilrmtreerS   rW   rX   )rf   r*   r/   r]   rJ   article_titleimscc_course_pathr   	plateformr   
account_idrY   canvas_course_resultworking_dirarticle_dirr`   s                   ra   import_courser  .  s    1
'"))'*;*;y*HIOOQ #  )MM#s#++C5
 #5#
 

 xx~$$TWW%78>>@HH[)004CSCS1STZZ\	5>9CUCU4::i001[]*2Xa[&
$WDJJ2NN%>LL.!&
  
 ii.ggll;>77>>+&MM+&*/
 	
5
 O 
,  
$SVH-
 	

sz   IAH/ IAH/ H(C*H/ H+%H/ ,H--A:H/ 'I(H/ +H/ -H/ /	I8IIIIIc                 @  K   |j                  t              j                  t        j                  | k(        j	                         }|j
                  }t        |j                  dd      j                  dd            }| d}t        |      }|j                  rAt        j                  |j                        }|j                  dk(  r|j                  }||_        t        j                   dd|j                  t        j"                  	      }|j%                  |      }	t'               }
|
j)                  |	t*         d|  
      }t,        j/                  d|       |d   }t,        j/                  d|       ||_        |j3                          |j5                  |       |S w)z!
    Upload IMSCC file to S3
    rp   ro   r   .imsccr   r   ^#### Subtopic:\s*\n? flags)
local_paths3_directoryzS3 Upload Result: %s
public_urlzCourse IMSCC S3 Path: %s)rD   r   rE   rf   r   rJ   r   r   r   r   r   r   r6   r   r   r|   sub	MULTILINEgenerate_imsccr   upload_imscc_to_s3r$   rA   rB   course_imscc_urlr   r   )rf   r/   r]   rJ   r   filenamer   r   r   r   
s3_service	s3_resultcourse_paths                ra   r   r   j  sh     XXg%%g&7&79&DEKKMFLLE%c3''S1M  'H"N << 3 343&'}}&6F#vv6F<S<S[][g[gh../?@JJ--U[T\\]^g]hRi-jI
KK&	2L)K
KK*K8)FIIKJJvs   FFz/download-imsccimscc	file_typec                    |j                  t              j                  t        j                  | k(        j	                         }|st        d      S |j                  }|st        d      S t        |j                  dd      j                  dd            }| d}|j                  rW|j                  t              j                  t        j                  |j                  k(        j	                         j                  nd}|rN|j                  t              j                  t        j                  |k(        j	                         j                  }nd}t        |      }	|j                   rAt#        j$                  |j                         }
|
j&                  d	k(  r|
j(                  }||_        t-        j.                  d
d|j*                  t,        j0                        }|dk(  r|	j3                  |      }d}n|dk(  r|	j5                  ||      }|d   }| d}d}nj|dk(  r|	j7                  |      }|d   }| d}d}nG|dk(  r/t8        j:                  j=                  t>        | d      }| d}d}n|	j3                  |      }d}t9        j@                  d      }t8        j:                  j=                  ||      }t8        j:                  jC                  |      rtE        jF                  |       tI        |||      S )zG
    Generate a course and return it as a downloadable IMSCC file.
    r   z+Course topic is required to generate IMSCC.rp   ro   r   r  Nr   r   r  r  r	  r  zapplication/zippdfpdf_filez.pdfzapplication/pdfhtml	html_filez.htmlz	text/htmlmdz.mdztext/markdownr   )
media_typer  )%rD   r   rE   rf   r   r   rJ   r   r   r*   r   r   r   r   tenant_namer   r   r   r   r6   r   r   r|   r  r  r  export_to_html_and_pdfexport_to_htmlrw   r   r   r#   rx   r   r   r   r   )rf   r  r/   r]   rJ   r   r  lms_plateform_idr   r   r   r   r   r  file_responser  r  s                    ra   download_imsccr%    s    XXg%%g&7&79&DEKKMF
 	
 LLE9
 	
 &c3''S1M  'H_e_m_mrxx~,,TWW-FGMMO[[swhh{+22;>>EU3UV\\^jj"N << 3 343&'}}&6F#vv6F<S<S[][g[ghG#223CD
&
	e	&==>NP[\":.
#_D)&
	f	&556FG";/
#_E* 
	d	WW\\-M?#1FG
#_C($
#223CD
&
 ))M*K'',,{M:K	ww~~k"k"  r   z/details/{course_id}c                   K   	 |j                  t              j                  t        j                  | k(        j	                         }|st        d      S |j                  rAt        j                  |j                        }|j                  dk(  r|j                  }||_        |j                  st        d      S t        j                  dd|j                  t        j                        }g d}t        j                   ||      }t#        |d	      }t%        |      }t'        d
|      S # t(        $ r}	t+        ddt-        |	             d}	~	ww xY ww)r   r   r    Course content is not available.r  r  r	  )zfenced-code-blockszcode-friendlytableszcuddled-listszbreak-on-newline)extraszhtml.parser%Course details retrieved successfullyr<   r=   r>   N)rD   r   rE   rf   r   r   r   r   r   r6   r   r   r|   r  r  	markdown2markdownr   build_nested_tocrS   rW   r   rX   )
rf   r/   r]   r   r   r)  r  soup
nested_tocr`   s
             ra   get_course_detailsr0    s7     W'"))'*;*;y*HIOOQ #  ||F$7$78H##s*#+== *:'&& 2  66":B@W@W_a_k_klg!!"26BT=1%d+
3
 	
  W6LSQRVH4UVVWsC   EAD' EA#D' 7E8A.D' &E'	E0E		EEz/course-modules/{course_id}c                   K   	 |j                  t              j                  t        j                  | k(        j	                         }|st        d      S |j                  rAt        j                  |j                        }|j                  dk(  r|j                  }||_        |j                  st        d      S |j                  }g }t        |      }|j                  |      }t        |d      D ]X  \  }	}
|
d   s|
d   rdj                  d	 |
d   D              nd
}|	|
d   ||
j                  dd
      d}|j!                  |       Z t#        d|      S # t$        $ r}t'        ddt)        |             d}~ww xY ww)z)
    Get course modules by course_id
    r   r   r'  r   r   )start	subtopicsr   c              3   "   K   | ]  }|  	 y w)Nrv   ).0sts     ra   	<genexpr>z%get_course_modules.<locals>.<genexpr>0  s     %L"g%Ls   r  r   r   )	module_idmoduler3  r   z%Course modules retrieved successfullyr<   r=   r>   N)rD   r   rE   rf   r   r   r   r   r   r6   r   r   r   get_module_titles	enumerater   appendrS   rW   r   rX   )rf   r/   r]   r   r   markdown_textmodulesr   module_titlesir9  r3  r:   r`   s                 ra   get_course_modulesrA    s    -W'"))'*;*;y*HIOOQ #  ||F$7$78H##s*#+== *:'&& 2  //&
 '88G"=: 		%IAvk"PVWbPcDII%L{8K%LLik	!"$^4!*&,jj1A2&F	 t$		% 3
 	

  W6LSQRVH4UVVWsJ   FAE FA#E 7F8AE <AE F	E> E99E>>Fz/course-pdf/{course_id}c                 .  K   	 |j                  t              j                  t        j                  | k(        j	                         }|st        d      S |j                  rAt        j                  |j                        }|j                  dk(  r|j                  }||_        |j                  st        d      S t        |      }|j                  |j                        }t        dg       S # t        $ r}t!        ddt#        |             d	}~ww xY ww)
z%
    Get course PDF by course_id
    r   r   r'  r   r*  r<   r=   r>   N)rD   r   rE   rf   r   r   r   r   r   r6   r   r   r   r!  rS   rW   r   rX   )rf   r/   r]   r   r   r   pdf_pathr`   s           ra   get_course_pdfrD  B  s    W'"))'*;*;y*HIOOQ #  ||F$7$78H##s*#+== *:'&& 2  '
 "889P9PQ3
 	

  W6LSQRVH4UVVWsB   DAC+ DA#C+ 7D82C+ *D+	D4DDDz/get-usage-report/{email}c           	        K   	 |j                  t              j                  t        j                  | k(        j	                         }|st        d      S |j                  }|j                  s t        d      }|j                  |d|i      }n)t        d      }|j                  |d|j                  i      }|j                         }|j                         }g }|D ]S  }	t        t        ||	            }
|j                  |
d   r|
d   j                  d      nd|
d	   |
d
   |
d   |
d   d       U dd|dS # t         $ r}t#        ddt%        |             d}~ww xY ww)z%
    Get course reports by email
    zUser not found.a  
                SELECT 
                    platform_id,
                    DATE(created_at) AS date,
                    SUM(CASE WHEN type = 'Credit' THEN number_of_course ELSE 0 END) AS added,
                    SUM(CASE WHEN type = 'Debit' THEN number_of_course ELSE 0 END) AS used,
                    SUM(SUM(CASE WHEN type = 'Credit' THEN number_of_course ELSE 0 END) -
                        SUM(CASE WHEN type = 'Debit' THEN number_of_course ELSE 0 END))
                        OVER (ORDER BY DATE(created_at)) AS balance
                FROM user_course_logs
                WHERE user_id = :user_id
                GROUP BY DATE(created_at)
                ORDER BY DATE(created_at);
                r*   a  
                SELECT 
                    platform_id,     
                    DATE(created_at) AS date,
                    SUM(CASE WHEN type = 'Credit' THEN number_of_course ELSE 0 END) AS added,
                    SUM(CASE WHEN type = 'Debit' THEN number_of_course ELSE 0 END) AS used,
                    SUM(SUM(CASE WHEN type = 'Credit' THEN number_of_course ELSE 0 END) -
                        SUM(CASE WHEN type = 'Debit' THEN number_of_course ELSE 0 END))
                        OVER (ORDER BY DATE(created_at)) AS balance
                FROM user_course_logs
                WHERE platform_id = :platform_id
                GROUP BY DATE(created_at)
                ORDER BY DATE(created_at);
                r   datez%d-%m-%YNaddedusedbalance)rF  rG  rH  rI  r   success Usage log retrieved successfullyr   r4   r:   r<   r=   r>   )rD   r   rE   r)   r   r   r   r   r   executefetchallkeysr{   zipr<  strftimerW   r   rX   )r)   r/   r   r*   rD   r   rowscolumnsreportsrowrow_dictr`   s               ra   get_usage_reportsrW  j  s{    =Wxx~$$TZZ5%89??A !  ''  E ZZ	7';<F  E ZZt7G7G'HIF ++- 	CC-.HNNAI&AQ(11*=W[!'* (#I.'6 	  9
 	
  W6LSQRVH4UVVWs6   EAD5 EC D5 4E5	E>EEEz$/report-details/{date}/{platform_id}rF  r   c                 J  K   	 t        d      }|j                  || |d      }|j                         }|j                         }g }|D ](  }t	        t        ||            }	|j                  |	       * dd|dS # t        $ r}
t        ddt        |
             d	}
~
ww xY ww)
z;
    Get course report details by date and platform_id
    aG  
            SELECT user_course_logs.user_id,user_course_logs.number_of_course, user_course_logs.type, users.name
            FROM user_course_logs
            JOIN users ON user_course_logs.user_id = users.id
            WHERE DATE(user_course_logs.created_at) = :date AND user_course_logs.platform_id = :platform_id;
        )rF  r   rJ  z%Report details retrieved successfullyrL  r<   r=   r>   N)
r   rM  rN  rO  r{   rP  r<  rW   r   rX   )rF  r   r/   rD   r   rR  rS  report_detailsrU  rV  r`   s              ra   get_report_detailsrZ    s     W   ED#MN ++- 	,CC-.H!!(+	,
  >"
 	
  W6LSQRVH4UVVWs)   B#A4A9 8B#9	B BB  B#c                    |j                  t              j                  t        j                  | k(        j	                         }	 |j
                  s t        d      }|j                  |d| i      }n)t        d      }|j                  |d|j
                  i      }|j                         }i }|r$	 |d   }|d   }|d   }	|xs d	|xs d	|	xs d	d}|S d	d	d	d}|S # t        $ r t        |d      rR|j                  j                  d      }|j                  j                  d      }|j                  j                  d      }	n?t        |      d	kD  r|d	   nd }t        |      d
kD  r|d
   nd }t        |      dkD  r|d   nd }	Y w xY w)Na  
            SELECT 
                SUM(CASE WHEN type = 'Credit' THEN number_of_course ELSE 0 END) AS total_credits,
                SUM(CASE WHEN type = 'Debit' THEN number_of_course ELSE 0 END) AS used_credits,
                SUM(CASE WHEN type = 'Credit' THEN number_of_course ELSE 0 END) -
                SUM(CASE WHEN type = 'Debit' THEN number_of_course ELSE 0 END) AS available_credits
            FROM user_course_logs
            WHERE user_id = :user_id;
        r*   a  
            SELECT 
                SUM(CASE WHEN type = 'Credit' THEN number_of_course ELSE 0 END) AS total_credits,
                SUM(CASE WHEN type = 'Debit' THEN number_of_course ELSE 0 END) AS used_credits,
                SUM(CASE WHEN type = 'Credit' THEN number_of_course ELSE 0 END) -
                SUM(CASE WHEN type = 'Debit' THEN number_of_course ELSE 0 END) AS available_credits
            FROM user_course_logs
            WHERE platform_id = :platform_id;
        r   total_creditsused_creditsru   _mappingr   r      )r\  r]  ru   )rD   r   rE   r   r   r   r   rM  fetchonerW   hasattrr^  r   r   )
r*   r/   r   credit_queryr   rU  r:   r;   rH  	availables
             ra   r   r     s    88D>  G!34::<D    L9g*>?   L=$:J:J*KL
//
CD
	=(E~&D/0I #Za IA!*a
 K	 !"

 K/  
	=sJ'((9||''7LL,,-@A	 #&c(Q,AD!$SAs1v4&)#hlCF	
	=s   /C B&FFz/total-credits/{user_id}c                 0   K   t        | |      }dd|dS w)z-
    Get total course credits for a user
    rt   rJ  rK  rL  )r   )r*   r/   r:   s      ra   get_total_course_creditsre    s-      &D
 5 s   )hrw   ry   r|   r   r   r   loggingtypingr   fastapir   r   r   r   r   fastapi.securityr	   r
   fastapi.encodersr   fastapi.responsesr   r   sqlalchemy.ormr   r   
sqlalchemyr   dotenvr   bs4r   r+  r   r   db_config.databasedatabasedbasedb_config.modelsr   r   r   r   r   r   r   db_config.schemasrT   db_config.authauthr   dependencies.helperdependencies.content_weaverdependencies.CourseCreatorr   dependencies.awsutilsr   syllabuild_celery_workerr    celery.resultr!   routersecuritybasicConfigINFO	getLogger__name__rA   r~   rx   r#   r$   r   rU   get_dbrX   r   rb   postCoursesCreater   r   r   CourseAISchemar   putCoursesUpdater   CourseModuleCreater   deleter   r   r   r  r   r%  r0  rA  rD  rW  rZ  r   re  rv   r   ra   <module>r     si   	  	      F F E - 8 .     ' " o o o #   ! ) 4 + : %	<   ',, '			8	$ A		/:6	81	2GG$;$;<  %,,'EWEWEW EW 	EW
 EW EW 	EW =EWN Yw'>'>? %,,'_W!!_W_W @_WB %g6M6MN %,,''W'W'W O'WR w/F/FG %,,'WWW HW< ^G,C,CD %,,';W;W%%;W 	;W E;Wz !'2I2IJ %,,'	jWjW!!jW jW 		jW KjW^ %,,'++ 	. $W5L5LM %,,'WWW NW2 +G<S<ST %,,'WWW 	W UW: 3  0  %,,'9
9
9
 	9
 9
z %,,'%%%N  %,,'MMM 	M M^ "# %,,''W'W'W $'WR )* %,,'4W4W4W +4Wl %& %,,'%W%W%W '%WN '( %,,'DWDWDW )DWL 23 %,,'W
WW 	W 4W@>>@ &' %,,' (r   