Ë
    Íµ&j˜m  ã                  óž  — d dl mZ d dlmZmZ d dlmZmZ d dlm	Z	m
Z
 d dl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mZ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%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z, d d
l-m.Z.m/Z/m0Z0m1Z1 d dl2m3Z3 d*d„Z4d+d„Z5d,d„Z6d-d„Z7d.d„Z8	 d/ddœ	 	 	 	 	 	 	 d0d„Z9d1d„Z:d ddddœ	 	 	 	 	 	 	 	 	 	 	 d2d„Z;d3d„Z<d4d„Z=ddddœ	 	 	 	 	 	 	 	 	 d5d„Z>d6d„Z?d7d„Z@d7d„ZA	 	 	 	 	 	 	 	 	 	 	 	 	 	 d8d„ZBd9d „ZCd:d!„ZD	 	 	 	 	 	 d;d"„ZE	 	 	 	 	 	 	 	 	 	 	 	 	 	 d<d#„ZF	 	 	 	 d=d$„ZGd>d%„ZH	 	 	 	 	 	 	 	 d?d&„ZI	 	 	 	 	 	 	 	 	 	 d@d'„ZJdAd(„ZK	 	 	 	 	 	 	 	 dBd)„ZLy)Cé    )Úannotations)ÚHTTPExceptionÚstatus)ÚfuncÚor_)ÚSessionÚselectinload)ÚUserÚUserCompletedAssessmentÚUserCompletedSessionÚUserRegisterStepÚUserRole)ÚMemberSessionProgress)	ÚProgrammeAssessmentÚProgrammeLevelÚProgrammeModuleÚProgrammeSessionÚProgrammeWeekÚnormalize_programme_level_slugÚnormalize_programme_module_kindÚprogramme_level_slug_strÚprogramme_module_kind_str)Ú_complete_entire_weekÚload_user_programme_summaryÚresolve_sessionÚuser_programme_load_optionsÚ!validate_user_programme_selection)	Ú$AdminMemberPersonalInfoUpdateRequestÚMarkMemberWeekCompleteRequestÚMemberWeekDetailOutÚMemberWeekSessionDetailOutÚMemberWeeksDetailResponseÚRoleEnumÚUpdateUserProgrammeRequestÚUserProgrammeProgressPublicÚ
UserPublic)Úcalculate_member_pointsÚlist_member_session_progressÚmedia_public_urlÚrefresh_member_points)Úget_user_dashboardc                ó@   — | €y | dz   }|dk(  ry|dk(  ry|dk(  ry|› d�S )Né   z1st weeké   z2nd weeké   z3rd weekzth week© )Ú
week_indexÚns     úF/var/www/html/kelly/kelly-backend/app/services/admin_member_service.pyÚ_format_week_labelr4   *   s>   € ØÐØØ�Q‰€AØˆA‚vØØˆA‚vØØˆA‚vØØˆS�ˆ=Ðó    c                ó  — | €y| j                   xs d| j                  xs dz   }| j                  xs d}| j                  xs d}t	        d|dz  |dz  z   |dz  z   «      }|dk(  r| j
                  s| j                  rd}|S )Nr   éd   é   é   r.   é   )Ú prior_completed_assessment_countÚ%prior_completed_session_markers_countr1   Úsession_numberÚminÚlevel_display_nameÚmodule_display_name)Ú	programmeÚ	completedÚweekÚsessionÚpcts        r3   Úcompute_member_progress_percentrF   7   s“   € ØÐØà×;Ñ;Ò@¸qØ×7Ñ7Ò<¸1ñ€Ið ×ÑÒ$ 1€DØ×&Ñ&Ò+¨!€Gä
ˆc�9˜q‘= 4¨!¡8Ñ+¨g¸©kÑ9Ó
:€CØ
ˆa‚x�Y×1Ò1°Y×5RÒ5RØˆØ€Jr5   c                ó`  —  | j                  t        «      j                  t        «       Ž j	                  t        j
                  |k(  «      j                  «       }|€t        t        j                  d¬«      ‚|j                  t        j                  k7  rt        t        j                  d¬«      ‚|S )NzUser not found©Ústatus_codeÚdetailzUser is not a member)Úqueryr
   Úoptionsr   ÚfilterÚidÚfirstr   r   ÚHTTP_404_NOT_FOUNDÚroler   ÚuserÚHTTP_400_BAD_REQUEST)ÚdbÚuser_idrR   s      r3   Ú_load_member_userrV   G   s„   € ð	ˆ�‰”‹ß	‰Ô-Ó/ð	1ç	‰”—‘˜7Ñ"Ó	#ß	‰‹ð	 	ð €|Ü¬×(AÑ(AÐJZÔ[Ð[Ø‡y�y”H—M‘MÒ!Ü¬×(CÑ(CÐLbÔcÐcØ€Kr5   c                ó@  — ddl m}  || |«      }|sy | j                  t        j                  t
        j                  «      «      j                  t
        j                  |j                  k(  «      j                  «       xs d}| j                  t        j                  t        j                  «      «      j                  t        j                  |j                  k(  «      j                  «       xs d}t        |«      |d<   t        |«      |d<   t        j                  |«      S )Nr   ©Úresolve_user_programme_summaryr;   r<   )Úapp.services.user_track_servicerY   rK   r   Úcountr   rU   rM   rN   Úscalarr   Úintr%   Úmodel_validate)rT   rR   rY   ÚrawÚcaÚcss         r3   Ú_build_programme_publicrb   U   sä   € ÝNá
(¨¨TÓ
2€CÙØð 	�‰”—‘Ô3×;Ñ;Ó<Ó=ß	‰Ô'×/Ñ/°4·7±7Ñ:Ó	;ß	‰‹ò	ð ð	 ð 	�‰”—‘Ô0×8Ñ8Ó9Ó:ß	‰Ô$×,Ñ,°·±Ñ7Ó	8ß	‰‹ò	ð ð	 ô /2°"«g€CÐ*Ñ+Ü36°r³7€CÐ/Ñ0Ü&×5Ñ5°cÓ:Ð:r5   c                óP   — t        | j                  xs dj                  «       «      S )NÚ )ÚboolÚgoogle_drive_linkÚstrip)rR   s    r3   Ú_has_google_drive_linkrh   m   s!   € Ü�×'Ñ'Ò-¨2×4Ñ4Ó6Ó7Ð7r5   N©Úprogramme_levelsc               óp   — |�ddl m}  ||| |¬«      }nt        | «      }|sy t        j                  |«      S )Nr   rX   ri   )rZ   rY   r   r%   r^   )rR   rT   rj   rY   r_   s        r3   Ú_build_programme_public_lightrl   q   s<   € ð 
€~ÝRá,¨R°ÐHXÔY‰ä)¨$Ó/ˆÙØÜ&×5Ñ5°cÓ:Ð:r5   c           
     óþ   — t        | «      }| j                  | j                  | j                  | j                  | j
                  t        | «      |r|j                  nd |r|j                  nd |r|j                  dœ	S d dœ	S )N)	rN   Ú	full_nameÚemailÚphone_numberrf   Úhas_google_drive_linkÚ
week_labelr?   r@   )
rl   rN   rn   ro   rp   rf   rh   rr   r?   r@   )rR   rT   rA   s      r3   Ú#serialize_member_google_drive_entryrs   ‚   s{   € Ü-¨dÓ3€Ià�g‰gØ—^‘^Ø—‘Ø×)Ñ)Ø!×3Ñ3Ü!7¸Ó!=Ù.7�i×*Ò*¸TÙ>G˜i×:Ò:ÈTÙ@I˜y×<Ñ<ñ
ð 
ð PTñ
ð 
r5   é2   )ÚskipÚlimitÚsearchÚlink_statusc          
     ó¾  — | j                  t        «      j                  t        j                  t        j
                  k(  «      }|ry|j                  «       rid|j                  «       › d�}|j                  t        t        j                  j                  |«      t        j                  j                  |«      «      «      }|xs dj                  «       j                  «       }|dk(  rg|j                  t        j                  j                  d «      t        j                  t        j                   t        j                  «      «      dkD  «      }ns|dv ro|j                  t        t        j                  j#                  d «      t        j                  t        j                   t        j                  «      «      dk(  «      «      }|j%                  «       } |j&                  t)        «       Ž j+                  t        j                  j-                  «       t        j.                  j-                  «       «      j1                  |«      j3                  |«      j5                  «       }	|	|fS )NÚ%ÚallÚ	with_linkr   )Úwithout_linkÚmissing)rK   r
   rM   rQ   r   rR   rg   r   rn   Úilikero   Úlowerrf   Úisnotr   ÚlengthÚtrimÚis_r[   rL   r   Úorder_byÚascrN   Úoffsetrv   r{   )
rT   ru   rv   rw   rx   rK   ÚtermÚnormalized_statusÚtotalÚmemberss
             r3   Úlist_members_google_drive_linksrŒ   ‘   s¤  € ð �H‰H”T‹N×!Ñ!¤$§)¡)¬x¯}©}Ñ"<Ó=€Eá�&—,‘,”.Ø�6—<‘<“>Ð" !Ð$ˆØ—‘œS¤§¡×!5Ñ!5°dÓ!;¼T¿Z¹Z×=MÑ=MÈdÓ=SÓTÓUˆà$Ò-¨×4Ñ4Ó6×<Ñ<Ó>ÐØ˜KÒ'Ø—‘Ü×"Ñ"×(Ñ(¨Ó.Ü�K‰KœŸ	™	¤$×"8Ñ"8Ó9Ó:¸QÑ>ó
‰ð 
Ð9Ñ	9Ø—‘ÜÜ×&Ñ&×*Ñ*¨4Ó0Ü—‘œDŸI™I¤d×&<Ñ&<Ó=Ó>À!ÑCóó
ˆð �K‰K‹M€Eàˆ�‰Ô2Ó4Ð5ß	‰”$—.‘.×$Ñ$Ó&¬¯©¯©«Ó	6ß	‰�‹ß	‰ˆu‹ß	‰‹ð ð �Eˆ>Ðr5   c                óR  — ddl m} t        | |«      } ||«      }||_        | j	                  «        | j                  |«        | j                  t        «      j                  t        «       Ž j                  t        j                  |j                  k(  «      j                  «       xs |S )Nr   ©Ú!validate_google_drive_folder_link)Úapp.google_drive_linkr�   rV   rf   ÚcommitÚrefreshrK   r
   rL   r   rM   rN   rO   )rT   rU   rf   r�   rR   Úlinks         r3   Úupdate_member_google_drive_linkr”   ¸   s…   € ÝGä˜R Ó)€DÙ,Ð->Ó?€DØ!€DÔØ‡I�I„KØ‡J�JˆtÔð	ˆ�‰”‹ß	‰Ô-Ó/ð	1ç	‰”—‘˜4Ÿ7™7Ñ"Ó	#ß	‰‹ò	ð ðr5   c                ó   — t        || «      }t        || j                  «      }	 t        || «      }t	        |j                  d«      xs d«      }t        | j                  t        «      r| j                  j                  nt        | j                  «      }t        | dd «      }t        |«      }t        di d| j                  “d| j                   “d| j"                  “d| j$                  “d| j&                  “d	| j(                  “d|“d
|“dt+        |«      “dt-        |«      “d| j.                  “dt+        | j0                  «      “d| j2                  “d|“d|d   “d|d   “d|d   “d|“d| j4                  “ŽS # t        $ r t        |«      }Y �Œ>w xY w)NÚlast_progress_percentr   Úprofile_imagerN   ro   rn   rp   ÚaddressÚpostal_codeÚprofile_image_urlÚhas_profile_imagerQ   Ú	is_activeÚemail_verifiedÚ
created_atrA   Útotal_pointsÚavailable_pointsÚassigned_points_totalÚprogress_percentrf   r0   )rb   r'   rN   r+   r]   ÚgetÚ	ExceptionrF   Ú
isinstancerQ   r   ÚvalueÚstrÚgetattrr)   r&   ro   rn   rp   r˜   r™   re   r#   rœ   r�   rž   rf   )	rR   rT   rA   ÚpointsÚdashr¢   rQ   r—   rš   s	            r3   Úserialize_admin_memberr«   É   s¾  € Ü'¨¨DÓ1€IÜ$ R¨¯©Ó1€FðFÜ! " dÓ+ˆÜ˜tŸx™xÐ(?Ó@ÒEÀAÓFÐô )¨¯©´HÔ=ˆ4�9‰9�?Š?Ä3ÀtÇyÁyÃ>€Dä˜D /°4Ó8€MÜ(¨Ó7Ðäò Ø�7Š7ðà�jŠjðð —.’.ðð ×&Ò&ð	ð
 —’ðð ×$Ò$ðñ $ðñ ,ðô ˜}Ô-ðô �dŒ^ðð —.’.ðô ˜D×/Ñ/Ô0ðð —?’?ðñ ðð Ð.Ò/ðð  %Ð%<Ò=ð!ð"  Ð 2Ò3ð#ñ$ *ð%ð& ×0Ò0ð'ð øô ò FÜ:¸9ÓEÓðFús   ¤*E5 Å5FÆF)rT   rj   r©   c               óú  — t        | ||¬«      }t        |«      }t        | j                  t        «      r| j                  j
                  nt        | j                  «      }t        | dd«      }t        |«      }|xs dddœ}	t        |	j                  d«      xs d«      }
t        |	j                  d«      xs d«      }t        di d| j                  “d	| j                  “d
| j                  “d| j                  “d| j                   “d| j"                  “d|“d|“dt%        |«      “dt'        |«      “d| j(                  “dt%        | j*                  «      “d| j,                  “d|“d|
“d|“d|
“d|“d| j.                  “ŽS )zUFast member serializer for list endpoints (no dashboard + no per-user count queries).)rT   rj   r—   Nr   )r¡   r    r    r¡   rN   ro   rn   rp   r˜   r™   rš   r›   rQ   rœ   r�   rž   rA   rŸ   r¢   rf   r0   )rl   rF   r¥   rQ   r   r¦   r§   r¨   r)   r]   r£   r&   rN   ro   rn   rp   r˜   r™   re   r#   rœ   r�   rž   rf   )rR   rT   rj   r©   rA   r¢   rQ   r—   rš   Úptsr    r¡   s               r3   Úserialize_admin_member_lightr®   ï   s£  € ô .¨d°rÐL\Ô]€IÜ6°yÓAÐÜ(¨¯©´HÔ=ˆ4�9‰9�?Š?Ä3ÀtÇyÁyÃ>€Dä˜D /°4Ó8€MÜ(¨Ó7Ðà
Ò
G¨aÀQÑG€CÜ˜3Ÿ7™7Ð#5Ó6Ò;¸!Ó<ÐÜ §¡Ð(?Ó @Ò EÀAÓFÐäò Ø�7Š7ðà�jŠjðð —.’.ðð ×&Ò&ð	ð
 —’ðð ×$Ò$ðñ $ðñ ,ðô ˜}Ô-ðô �dŒ^ðð —.’.ðô ˜D×/Ñ/Ô0ðð —?’?ðñ ðñ &ðñ  4ð!ñ" *ð#ñ$ *ð%ð& ×0Ò0ð'ð r5   c                ó>  — t        | j                  t        «      r| j                  j                  nt	        | j                  «      }t        | dd«      }t        |«      }t        di d| j                  “d| j                  “d| j                  “d| j                  “d| j                  “d| j                  “d|“d	|“d
t        |«      “dt        |«      “d| j                   “dt        | j"                  «      “d| j$                  “dd“dd“dd“dd“dd“d| j&                  “ŽS )zFSuper fast serializer for members list (no programme/progress/points).r—   NrN   ro   rn   rp   r˜   r™   rš   r›   rQ   rœ   r�   rž   rA   rŸ   r¡   r    r¢   rf   r0   )r¥   rQ   r   r¦   r§   r¨   r)   r&   rN   ro   rn   rp   r˜   r™   re   r#   rœ   r�   rž   rf   )rR   rQ   r—   rš   s       r3   Úserialize_admin_member_minimalr°     sD  € ä(¨¯©´HÔ=ˆ4�9‰9�?Š?Ä3ÀtÇyÁyÃ>€DÜ˜D /°4Ó8€MÜ(¨Ó7ÐÜò Ø�7Š7ðà�jŠjðð —.’.ðð ×&Ò&ð	ð
 —’ðð ×$Ò$ðñ $ðñ ,ðô ˜}Ô-ðô �dŒ^ðð —.’.ðô ˜D×/Ñ/Ô0ðð —?’?ðñ ðñ ðñ  #ð!ñ" ð#ñ$ ð%ð& ×0Ò0ð'ð r5   c                ót   — 	 t        | «      S # t        $ r!}t        t        j                  d¬«      |‚d }~ww xY w)Nzlevel slug is requiredrH   )r   Ú
ValueErrorr   r   rS   ©r¦   Úexcs     r3   Ú_parse_level_slugrµ   5  s@   € ðÜ-¨eÓ4Ð4øÜò ÜÜ×3Ñ3Ø+ô
ð ð	ûðúó   ‚
 �	7–2²7c                ót   — 	 t        | «      S # t        $ r!}t        t        j                  d¬«      |‚d }~ww xY w)Nzmodule kind is requiredrH   )r   r²   r   r   rS   r³   s     r3   Ú_parse_module_kindr¸   ?  s@   € ðÜ.¨uÓ5Ð5øÜò ÜÜ×3Ñ3Ø,ô
ð ð	ûðúr¶   c               óî  — | j                  t        «      j                  t        j                  |j                  k(  «      j                  «       }|€y | j                  t        «      j                  t        j                  |k(  «      j                  «       }|r_| j                  t        «      j                  t        j                  |j                  k(  t        j                  |k(  «      j                  «       nd }|r_| j                  t        «      j                  t        j                  |j                  k(  t        j                  |k(  «      j                  «       nd }	|r"|j                  |_	        |j                  |_        |r"|j                  |_        |j                  |_        |	r"|	j                  |_        |	j$                  |_        |j                  |_        |j*                  |_        d|_        d|_        y )NrB   T)rK   r   rM   rU   rN   rO   r   Úslugr   Úlevel_idÚkindr   Ú	module_idr1   Údisplay_nameÚ
level_nameÚmodule_nameÚweek_idÚdisplay_labelÚ	week_nameÚ
session_idÚtitleÚsession_nameÚcurrent_stepÚis_completed)
rT   rR   Ú
level_slugÚmodule_kindr1   rD   ÚrowÚlevelÚmodulerC   s
             r3   Ú"_sync_register_step_from_programmerÎ   I  sy  € ð �(‰(Ô#Ó
$×
+Ñ
+Ô,<×,DÑ,DÈÏÉÑ,OÓ
P×
VÑ
VÓ
X€CØ
€{Øð 	�‰”Ó ß	‰”×#Ñ# zÑ1Ó	2ß	‰‹ð 
ñ ð 	�‰”Ó!ß	‰”×(Ñ(¨E¯H©HÑ4´o×6JÑ6JÈkÑ6YÓ	Zß	‰Œàð ñ ð 	�‰”Óß	‰”×'Ñ'¨6¯9©9Ñ4´m×6NÑ6NÐR\Ñ6\Ó	]ß	‰Œàð 	ñ Ø—x‘xˆŒØ×+Ñ+ˆŒÙØŸ	™	ˆŒØ ×-Ñ-ˆŒÙØ—g‘gˆŒØ×*Ñ*ˆŒØ—Z‘Z€C„NØ—}‘}€CÔØ"€CÔØ€CÕr5   c                ó^  — t        | |j                  «      }t        |j                  «      }t	        |j
                  «      }t        | |||j                  |j                  ¬«      }|€t        t        j                  d¬«      ‚| j                  t        «      j                  t        j                  |j                   k(  «      j#                  t        j$                  j'                  «       «      j)                  «       }	 t+        | |||j                  |j                  |r|j                   nd ¬«      \  }}|j                   |_        |r|j                   nd |_        t5        | ||||j                  |¬«       | j7                  «        | j9                  |«        | j                  t:        «      j<                  t?        «       Ž j                  t:        j                   |j                   k(  «      j)                  «       xs |S # t,        $ r*}t        t        j                  t/        |«      ¬«      |‚d }~ww xY w)N)rÉ   rÊ   r1   r=   z0No matching session for the given programme pathrH   )rÉ   rÊ   r1   r=   Úassessment_id)rÉ   rÊ   r1   rD   ) rV   rU   rµ   Úprogramme_level_slugr¸   Úprogramme_module_kindr   Úprogramme_week_indexÚprogramme_session_numberr   r   rS   rK   r   rM   rÄ   rN   r…   Ú
sort_orderr†   rO   r   r²   r§   Úprogramme_session_idÚprogramme_assessment_idrÎ   r‘   r’   r
   rL   r   )	rT   ÚbodyrR   rÉ   rÊ   rD   Úfirst_assessmentÚ
assessmentr´   s	            r3   Úassign_user_programmerÛ   y  sÔ  € Ü˜R §¡Ó.€DÜ" 4×#<Ñ#<Ó=€JÜ$ T×%?Ñ%?Ó@€KäØ
ØØØ×,Ñ,Ø×4Ñ4ô€Gð €ÜÜ×3Ñ3ØEô
ð 	
ð 	�‰Ô$Ó%ß	‰Ô#×.Ñ.°'·*±*Ñ<Ó	=ß	‰Ô%×0Ñ0×4Ñ4Ó6Ó	7ß	‰‹ð	 ð
_Ü?ØØ!Ø#Ø×0Ñ0Ø×8Ñ8Ù1AÐ*×-Ò-Àtô
Ñˆ�ð !(§
¡
€DÔÙ4> :§=¢=ÀD€DÔ Ü&Ø
ØØØØ×,Ñ,Øõð ‡I�I„KØ‡J�JˆtÔð	ˆ�‰”‹ß	‰Ô-Ó/ð	1ç	‰”—‘˜4Ÿ7™7Ñ"Ó	#ß	‰‹ò	ð ðøô ò _Ü¬×(CÑ(CÌCÐPSËHÔUÐ[^Ð^ûð_ús   Ã;6G9 Ç9	H,È%H'È'H,c           
     óJ  — t        | |j                  «      }|j                  �>|j                  j                  «       }|st	        t
        j                  d¬«      ‚||_        |j                  �ddlm	}  ||j                  «      |_        |j                  �#|j                  j                  «       xs d |_
        |j                  |j                  |j                  |j                  f}t        d„ |D «       «      �r|j                  �|j                  €t	        t
        j                  d¬«      ‚t!        | |«      }|j                  �|j                  n|r|j"                  �|j"                  nd}|j                  �|j                  n|r|j$                  �|j$                  nd}t'        | t)        |j                  |j                  |j                  ||¬«      «       | j+                  |«       t        | |j                  «      }|S | j-                  «        | j+                  |«       |S )	Nzfull_name cannot be emptyrH   r   rŽ   c              3  ó$   K  — | ]  }|d u–— Œ
 y ­w©Nr0   )Ú.0r¦   s     r3   Ú	<genexpr>z.update_member_personal_info.<locals>.<genexpr>Ê  s   è ø€ Ð
;Ñ*: ˆ5˜ÔÑ*:ùs   ‚zSprogramme_level_slug and programme_module_kind are required when updating programmer-   )rU   rÑ   rÒ   rÓ   rÔ   )rV   rU   rn   rg   r   r   rS   rf   r�   r�   rp   rÑ   rÒ   rÓ   rÔ   Úanyrb   r1   r=   rÛ   r$   r’   r‘   )	rT   rØ   rR   Úcleanedr�   Úprogramme_fieldsrA   r1   r=   s	            r3   Úupdate_member_personal_inforä   ³  sö  € Ü˜R §¡Ó.€Dà‡~�~Ð!Ø—.‘.×&Ñ&Ó(ˆÙÜ¬F×,GÑ,GÐPkÔlÐlØ ˆŒà×ÑÐ)ÝKá!BÀ4×CYÑCYÓ!ZˆÔà×ÑÐ$Ø ×-Ñ-×3Ñ3Ó5Ò=¸ˆÔð 	×!Ñ!Ø×"Ñ"Ø×!Ñ!Ø×%Ñ%ð	Ðô Ñ
;Ñ*:Ó
;Õ;Ø×$Ñ$Ð,°×0JÑ0JÐ0RÜÜ"×7Ñ7Ølôð ô
 ,¨B°Ó5ˆ	ð ×(Ñ(Ð4ð ×%Ò%á*3¸	×8LÑ8LÐ8X�)×&Ò&Ð^_ð 	ð ×,Ñ,Ð8ð ×)Ò)á.7¸I×<TÑ<TÐ<`�)×*Ò*Ðfgð 	ô 	ØÜ&ØŸ™Ø%)×%>Ñ%>Ø&*×&@Ñ&@Ø%/Ø)7ôô		
ð 	�
‰
�4ÔÜ   T§\¡\Ó2ˆð
 €Kð 	�	‰	ŒØ
�
‰
�4Ôà€Kr5   c                óv  ‡— ddl m}  || |«      }|rt        j                  |«      nd }|r!|j                  rt        |j                  «      nd}|r!|j                  rt        |j                  «      ndŠ| j                  t        «      j                  t        t        j                  «      j                  t        j                  «      j                  t        j                   «      j                  t"        j$                  «      «      j'                  t        j(                  |k(  «      j+                  «       }|€t-        t.        j0                  d¬«      ‚t3        ˆfd„|j                  D «       d «      }|€'|j                  rt5        |j                  d„ ¬	«      d   }|€t-        t.        j0                  d
¬«      ‚|||fS )Nr   rX   ÚbeginnerÚfoundationszProgramme level not foundrH   c              3  óB   •K  — | ]  }|j                   ‰k(  sŒ|–— Œ y ­wrÞ   )r¼   )rß   ÚmrÊ   s     €r3   rà   z)_resolve_member_module.<locals>.<genexpr>  s   øè ø€ ÐE™m˜¨q¯v©v¸Ó/D”1™mùs   ƒ˜c                ó   — | j                   S rÞ   ©rÕ   ©Úitems    r3   Ú<lambda>z(_resolve_member_module.<locals>.<lambda>  s   € ¸¿ºr5   ©ÚkeyzProgramme module not found)rZ   rY   r%   r^   rÉ   rµ   rÊ   r¸   rK   r   rL   r	   Úmodulesr   Úweeksr   Úsessionsr   ÚassessmentsrM   rº   rO   r   r   rP   ÚnextÚsorted)	rT   rR   rY   r_   rA   rÉ   rÌ   rÍ   rÊ   s	           @r3   Ú_resolve_member_moduler÷   ð  sf  ø€ õ Oá
(¨¨TÓ
2€CÙCFÔ+×:Ñ:¸3Ô?ÈD€Iñ ˜×-Ò-ô 	˜)×.Ñ.Ô/àð ñ ˜×.Ò.ô 	˜9×0Ñ0Ô1àð ð 	�‰”Ó ß	‰Üœ×/Ñ/Ó0ß‰\œ/×/Ñ/Ó0ß‰\œ-×0Ñ0Ó1ß‰\Ô*×6Ñ6Ó7ó	

÷ 
‰”×#Ñ# zÑ1Ó	2ß	‰‹ð 
ð €}Ü¬×(AÑ(AÐJeÔfÐfäÓE˜eŸmšmÓEÀtÓL€FØ€~˜%Ÿ-š-Ü˜Ÿ™Ñ+GÔHÈÑKˆØ€~Ü¬×(AÑ(AÐJfÔgÐgà�&˜)Ð#Ð#r5   c               ó"  ‡— |j                  | j                  «      xs' |j                  |j                  | j                  f«      }|�|j                  ryt        | j                  d„ ¬«      }|rt        ˆfd„|D «       «      S | j                  |v S )NTc                ó   — | j                   S rÞ   rë   rì   s    r3   rî   z'_session_is_completed.<locals>.<lambda>(  s   € ¸t¿ºr5   rï   c              3  ó:   •K  — | ]  }|j                   ‰v –— Œ y ­wrÞ   )rN   )rß   rÚ   Úcompleted_assessment_idss     €r3   rà   z(_session_is_completed.<locals>.<genexpr>*  s   øè ø€ Ð[É{À�:—=‘=Ð$<Ô<É{ùs   ƒ)r£   rN   r1   r=   rÈ   rö   rô   r{   )rD   rC   Úcompleted_session_idsrû   Úprogress_by_session_idÚprogress_by_week_sessionÚprogressrô   s      `    r3   Ú_session_is_completedr     sˆ   ø€ ð &×)Ñ)¨'¯*©*Ó5ò Ð9Q×9UÑ9UØ	�‰˜'×0Ñ0Ð1ó:€Hð Ð × 5Ò 5Øä˜×,Ñ,Ñ2NÔO€KÙÜÓ[É{Ó[Ó[Ð[à�:‰:Ð.Ð.Ð.r5   c                óÀ   — i }i }| D ]R  }|j                   �|||j                   <   |j                  €Œ+|j                  €Œ8|||j                  |j                  f<   ŒT ||fS rÞ   )rÄ   r1   r=   )ÚrowsÚby_session_idÚby_week_sessionrË   s       r3   Ú_progress_lookupr  /  sk   € ð 79€MØDF€OÛˆØ�>‰>Ð%Ø,/ˆM˜#Ÿ.™.Ñ)Ø�>‰>Ñ%¨#×*<Ñ*<Ñ*HØDGˆO˜SŸ^™^¨S×-?Ñ-?Ð@ÒAð	 ð
 ˜/Ð)Ð)r5   c                óR  — t        | |«      }t        | |«      \  }}}t        | |«      }t        |«      \  }}| j	                  t
        «      j                  t
        j                  |k(  «      j                  «       D �	ch c]  }	|	j                  ’Œ }
}	| j	                  t        «      j                  t        j                  |k(  «      j                  «       D �	ch c]  }	|	j                  ’Œ }}	|r|j                  nd }g }t        t        |j                  d„ ¬«      «      D �]„  \  }}g }d}t        |j                   d„ ¬«      D �]§  }|j#                  |j$                  «      xs' |j#                  |j                  |j&                  f«      }t)        |||
|||¬«      }|r|dz  }t        |j*                  d„ ¬«      }|r|d   nd }t-        |xr |j.                  xs dj1                  «       «      }|j3                  t5        |j$                  |j&                  |j6                  |rd	nd
||||r|j.                  nd |rt9        |j:                  «      nd|r|j$                  nd |r!|j<                  rt?        |j<                  «      nd |r>|j@                  xs g D �cg c]$  }|j<                  sŒt?        |j<                  «      ‘Œ& c}ng |r|j$                  nd |r|j6                  nd ¬«      «       �Œª tC        |«      }|dkD  xr ||k(  }tE        | |j$                  |«      }|d uxr t9        |j:                  xs d«      dkD  }|j3                  tG        |j$                  |j                  |j                  dz   |jH                  |||xs |||j                  |k(  xs |dk(  |¬«
      «       �Œ‡ tK        | |j$                  «      }tM        |j$                  tO        |jP                  «      |jR                  tU        |jV                  «      |jR                  ||d   |d   |¬«	      S c c}	w c c}	w c c}w )Nc                ó   — | j                   S rÞ   ©r1   rì   s    r3   rî   z)get_member_weeks_detail.<locals>.<lambda>O  s   € ÀTÇ_Â_r5   rï   r   c                ó   — | j                   S rÞ   ©r=   rì   s    r3   rî   z)get_member_weeks_detail.<locals>.<lambda>S  ó
   € ¸d×>QÒ>Qr5   )rü   rû   rý   rþ   r-   c                ó   — | j                   S rÞ   rë   rì   s    r3   rî   z)get_member_weeks_detail.<locals>.<lambda>b  s   € ÀtÇÂr5   rd   Úvideo_submittedÚpending_submission)rÄ   r=   rÅ   r   r  rÈ   Úhas_feedbackÚfeedbackÚassigned_pointsÚprogress_idÚ	image_urlÚ
image_urlsÚfirst_assessment_idÚfirst_assessment_title)
rÁ   r1   Úweek_numberrÂ   Útotal_sessionsÚcompleted_sessionsrÈ   Úweek_point_awardedÚexpandedró   r¡   r    )	rU   rÉ   r?   rÊ   r@   Úcurrent_week_indexr¡   r    rò   ),rV   r÷   r(   r  rK   r   rM   rU   r{   rÄ   r   rÐ   r1   Ú	enumeraterö   rò   ró   r£   rN   r=   r   rô   re   r  rg   Úappendr!   rÅ   r]   r  Ú
image_pathr)   ÚimagesÚlenÚ_week_completion_bonus_rowr    rÂ   r'   r"   r   rº   r¾   r   r¼   )rT   rU   rR   rÌ   rÍ   rA   Úprogress_rowsrý   rþ   rË   rü   rû   r  Ú	weeks_outÚidxrC   Úsessions_outÚcompleted_countrD   rÿ   rÈ   rô   rÙ   r  Úimgr  Úweek_completedÚ	bonus_rowr  r©   s                                 r3   Úget_member_weeks_detailr+  <  s  € Ü˜R Ó)€DÜ5°b¸$Ó?Ñ€Eˆ6�9ä0°°WÓ=€MÜ7GÈÓ7VÑ4ÐÐ4ð —8‘8Ô0Ó1×8Ñ8Ô9M×9UÑ9UÐY`Ñ9`Óa×eÑeÔgóágˆCð 	�‹Øgð ð ð —8‘8Ô3Ó4×;Ñ;Ô<S×<[Ñ<[Ð_fÑ<fÓg×kÑkÔmó ámˆCð 	×ÓØmð ð  ñ
 2;˜×-Ò-ÀÐØ+-€Iäœv f§l¡lÑ8TÔU×V‰	ˆˆTØ9;ˆØˆä˜dŸm™mÑ1Q×RÐRˆGØ-×1Ñ1°'·*±*Ó=ò ÐAY×A]ÑA]Ø—‘ '×"8Ñ"8Ð9óBˆHô 1ØØØ&;Ø)AØ'=Ø)AôˆLñ Ø 1Ñ$�ä  ×!4Ñ!4Ñ:VÔWˆKÙ1<˜{¨1š~À$ÐÜ Ò N¨h×.?Ñ.?Ò.EÀ2×-LÑ-LÓ-NÓOˆLà×ÑÜ*Ø&Ÿz™zØ#*×#9Ñ#9Ø!Ÿ-™-Ù0<Ñ,ÐBVØ$0Ø!-Ø!-Ù2:˜X×.Ò.ÀÙEM¤C¨×(@Ñ(@Ô$AÐSTÙ/7 §¢¸TÙGOÐT\×TgÒTgÔ.¨x×/BÑ/BÔCÐmqñ $ð GOÇoÁoÒF[ÐY[ÐF[ÓoÑF[¸cÐ`c×`nÓ`nÔ)¨#¯.©.Õ9ÐF[Òoàá?OÐ(8×(;Ò(;ÐUYÙEUÐ+;×+AÒ+AÐ[_ô%öð' SôT ˜\Ó*ˆØ'¨!Ñ+ÒQ°À>Ñ0QˆÜ.¨r°4·7±7¸DÓAˆ	Ø&¨dÐ2Ò^´s¸9×;TÑ;TÒ;YÐXYÓ7ZÐ]^Ñ7^ÐØ×ÑÜØŸ™ØŸ?™?Ø ŸO™O¨aÑ/Ø"×0Ñ0Ø-Ø#2Ø+ÒAÐ/AØ#5ØŸ™Ð,>Ñ>ÒJÀ#ÈÁ(Ø%ôö	
ðe WôB % R¨¯©Ó1€FÜ$Ø—‘Ü+¨E¯J©JÓ7Ø ×-Ñ-Ü-¨f¯k©kÓ:Ø"×/Ñ/Ø-Ø$Ð%<Ñ=ØÐ 2Ñ3Øô
ð 
ùò]ùò ùòZ ps   Á<PÃPÊP$&Ê&P$&c                óä   — | j                  t        «      j                  t        j                  |k(  t        j                  |j                  k(  t        j
                  dk(  «      j                  «       S )Nr   )rK   r   rM   rU   r1   r=   rO   )rT   rU   rC   s      r3   r"  r"  ž  sW   € ð 	�‰Ô&Ó'ß	‰Ü!×)Ñ)¨WÑ4Ü!×,Ñ,°·±Ñ?Ü!×0Ñ0°AÑ5ó

÷
 
‰‹ðr5   c                óº  — t        | |j                  |«      }|€(t        |j                  d¬«      }| j                  |«       |j                  |_        |j
                  |_        |j                  |_        d |_        |j
                  › d�|_	        d|_
        d|_        d|_        |j                  |_        | j                  «        t        | |j                  «       y )Nr   )rU   r=   z completionr-   zWeek marked as completedT)r"  rN   r   ÚaddrÁ   rÂ   rÃ   r1   rÄ   rÆ   r  r  rÈ   Úassigned_by_idÚflushr*   )rT   ÚadminrR   rC   rË   s        r3   Ú_award_week_completion_pointr2  ¬  s°   € ô % R¨¯©°$Ó
7€CØ
€{Ü#¨D¯G©GÀAÔFˆØ
�‰ˆsŒØ—'‘'€C„KØ×&Ñ&€C„MØ—_‘_€C„NØ€C„NØ×,Ñ,Ð-¨[Ð9€CÔØ€CÔØ-€C„LØ€CÔØŸ™€CÔØ‡H�H„JÜ˜"˜dŸg™gÕ&r5   c                ó~   — t        | ||«      }|�.| j                  |«       | j                  «        t        | |«       y y rÞ   )r"  Údeleter0  r*   )rT   rU   rC   rË   s       r3   Ú_remove_week_completion_pointr5  Ã  s8   € Ü
$ R¨°$Ó
7€CØ
€Ø
�	‰	�#ŒØ
�‰Œ
Ü˜b 'Õ*ð r5   c                ó6  ‡— t        | ‰j                  «      }t        | |«      \  }}}t        ˆfd„|j                  D «       d «      }|€t        t        j                  d¬«      ‚‰j                  �rPt        | |j                  |«       t        |j                  d„ ¬«      D �]  }| j                  t        «      j                  t        j                  |j                  k(  t        j                   |j                  k(  «      j#                  «       }	|	€2t        |j                  |j                  ¬«      }	| j%                  |	«       |j                  |	_        |j(                  |	_        |j,                  |	_        |j                  |	_        |j.                  |	_        |j2                  |	_        d|	_        �Œ t5        | |||«       �nþ|j                  D �cg c]  }|j                  ‘Œ }
}|
�rE| j                  t6        «      j                  t6        j                  |j                  k(  t6        j                   j9                  |
«      «      j;                  d¬	«       | j                  t<        j                  «      j                  t<        j                   j9                  |
«      «      j?                  «       D �cg c]  }|d
   ‘Œ	 }}|rm| j                  t@        «      j                  t@        j                  |j                  k(  t@        jB                  j9                  |«      «      j;                  d¬	«       | j                  t        «      j                  t        j                  |j                  k(  t        j,                  |j,                  k(  «      jE                  t        j                  did¬	«       tG        | |j                  |«       d
dl$m%}  || |«       | jM                  «        	 d
dl'm(}  |«        tU        | |j                  «      S c c}w c c}w # tR        $ r Y Œ+w xY w)Nc              3  óV   •K  — | ]   }|j                   ‰j                   k(  sŒ|–— Œ" y ­wrÞ   r  )rß   ÚwkrØ   s     €r3   rà   z,mark_member_week_complete.<locals>.<genexpr>Ñ  s!   øè ø€ ÐO™l˜¨b¯m©m¸t¿¹Ó.N”™lùs   ƒ)¢)zWeek not foundrH   c                ó   — | j                   S rÞ   r
  rì   s    r3   rî   z+mark_member_week_complete.<locals>.<lambda>×  r  r5   rï   )rU   rÄ   TF)Úsynchronize_sessionr   )Úsync_user_programme_pointer)Úinvalidate_list_users_cache)+rV   rU   r÷   rõ   rò   r   r   rP   rÈ   r   rN   rö   ró   rK   r   rM   rÄ   rO   r.  rÁ   rÂ   rÃ   r1   rÅ   rÆ   r=   r2  r   Úin_r4  r   r{   r   rÐ   Úupdater5  rZ   r;  r‘   Úapp.routers.admin.usersr<  r¤   r+  )rT   rØ   r1  rR   Ú_levelrÍ   Ú
_programmerC   rD   rÿ   Úsession_idsrË   Úassessment_idsr;  r<  s    `             r3   Úmark_member_week_completerD  Ë  s>  ø€ ô ˜R §¡Ó.€DÜ!7¸¸DÓ!AÑ€FˆF�JäÓO˜fŸlšlÓOÐQUÓV€DØ€|Ü¬×(AÑ(AÐJZÔ[Ð[à×ÓÜ˜b $§'¡'¨4Ô0Ü˜dŸm™mÑ1Q×RÐRˆGà—‘Ô.Ó/ß‘Ü)×1Ñ1°T·W±WÑ<Ü)×4Ñ4¸¿
¹
ÑBó÷ ‘“ð ð ÐÜ0¸¿¹ÈWÏZÉZÔX�Ø—‘�xÔ Ø#Ÿw™wˆHÔØ!%×!3Ñ!3ˆHÔØ"&§/¡/ˆHÔØ")§*¡*ˆHÔØ$+§M¡MˆHÔ!Ø&-×&<Ñ&<ˆHÔ#Ø$(ˆHÖ!ð% Sô& 	% R¨°°dÖ;à15·²Ó?± g�w—z“z°ˆÐ?ÚØ�H‰HÔ)Ó*×1Ñ1Ü$×,Ñ,°·±Ñ7Ü$×/Ñ/×3Ñ3°KÓ@ó÷ ‰f¨ˆfÔ/ð Ÿ8™8Ô$7×$:Ñ$:Ó;ß‘Ô+×6Ñ6×:Ñ:¸;ÓGÓHß‘“ðóñ�Cð �A“ðð ð ñ Ø—‘Ô0Ó1×8Ñ8Ü+×3Ñ3°t·w±wÑ>Ü+×9Ñ9×=Ñ=¸nÓMó÷ ‘&¨U�&Ô3Ø
�‰Ô&Ó'×.Ñ.Ü!×)Ñ)¨T¯W©WÑ4Ü!×,Ñ,°·±Ñ?ó	
÷ ‰&Ô'×4Ñ4°eÐ<ÐRWˆ&Ô
XÜ% b¨$¯'©'°4Ô8åKá  DÔ)Ø‡I�I„KðÝGá#Ô%ô # 2 t§w¡wÓ/Ð/ùòC @ùòøô2 ò Ùðús   ÇPÊ/PÏP Ð	PÐP)r1   z
int | NoneÚreturnú
str | None)rA   ú"UserProgrammeProgressPublic | NonerE  r]   )rT   r   rU   r]   rE  r
   )rT   r   rR   r
   rE  rG  )rR   r
   rE  re   rÞ   )rR   r
   rT   úSession | Nonerj   úlist[ProgrammeLevel] | NonerE  rG  )rR   r
   rT   r   rE  Údict)rT   r   ru   r]   rv   r]   rw   rF  rx   rF  rE  ztuple[list[User], int])rT   r   rU   r]   rf   rF  rE  r
   )rR   r
   rT   r   rE  r&   )
rR   r
   rT   rH  rj   rI  r©   zdict | NonerE  r&   )rR   r
   rE  r&   )r¦   r§   rE  r§   )rT   r   rR   r
   rÉ   r§   rÊ   r§   r1   r]   rD   r   rE  ÚNone)rT   r   rØ   r$   rE  r
   )rT   r   rØ   r   rE  r
   )rT   r   rR   r
   rE  zJtuple[ProgrammeLevel, ProgrammeModule, UserProgrammeProgressPublic | None])rD   r   rC   r   rü   úset[int]rû   rL  rý   z dict[int, MemberSessionProgress]rþ   z,dict[tuple[int, int], MemberSessionProgress]rE  re   )r  zlist[MemberSessionProgress]rE  zUtuple[dict[int, MemberSessionProgress], dict[tuple[int, int], MemberSessionProgress]])rT   r   rU   r]   rE  r"   )rT   r   rU   r]   rC   r   rE  zMemberSessionProgress | None)
rT   r   r1  r
   rR   r
   rC   r   rE  rK  )rT   r   rU   r]   rC   r   rE  rK  )rT   r   rØ   r   r1  r
   rE  r"   )MÚ
__future__r   Úfastapir   r   Ú
sqlalchemyr   r   Úsqlalchemy.ormr   r	   Ú
app.modelsr
   r   r   r   r   Úapp.models_adminr   Úapp.programme.models_programmer   r   r   r   r   r   r   r   r   Ú(app.programme.services.programme_servicer   r   r   r   r   Úapp.schemasr   r   r    r!   r"   r#   r$   r%   r&   Úapp.services.admin_servicer'   r(   r)   r*   Ú#app.services.user_dashboard_servicer+   r4   rF   rV   rb   rh   rl   rs   rŒ   r”   r«   r®   r°   rµ   r¸   rÎ   rÛ   rä   r÷   r   r  r+  r"  r2  r5  rD  r0   r5   r3   Ú<module>rX     s­  ðÝ "ç )ß  ß 0ç fÕ fÝ 2÷
÷ 
õ 
÷õ ÷
÷ 
õ 
÷ Fó  FÝ Bó
óó ó;ó08ð ð;ð 59ñ	;Ø
ð;àð;ð 2ð	;ð
 (ó;ó"ð$ ØØØ"ñ$Øð$ð ð$ð ð	$ð
 ð$ð ð$ð ó$óNó"#ðR Ø48Øñ'Ø
ð'ð 	ð'ð 2ð	'ð
 ð'ð ó'óTó8óð-Øð-à
ð-ð ð	-ð
 ð-ð ð-ð ð-ð 
ó-ó`7ót:ðz&$Øð&$Øð&$àOó&$ðR/Øð/à
ð/ð $ð	/ð
 'ð/ð =ð/ð Kð/ð 
ó/ð,
*Ø
%ð
*àZó
*ó_ðDØðØðØ%2ðà!óð'Øð'àð'ð ð'ð ð	'ð
 
ó'ó.+ðB0ØðB0Ø4ðB0Ø=AðB0àôB0r5   