+
    :h@                       ^ RI HtHtHtHtHtHtHt ^ RIH	t	H
t
Ht ^ RIHt ^ RIHt ^ RIHt ^ RIHt ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt]! R	R
7      t]P8                  ! ]4      P=                  4       P>                  t ] R,          t!]PE                  ]RR7       ]! R.RR7      t#]PI                  R]! RR7      RR7       ]! RR7      t%R t&R t'R R lt(R R lt)]PU                  RRR7      ]! R4      ]! R4      3R  R! ll4       t+R" R# lt,R$ R% lt-RR& R' llt.^ RI/t/^ RI0t0^ RI1t1^ RI2t3^ RIt4R( t5RR) R* llt6R+ R, lt7R- t8R. R/ lt9R0 R1 lt:R2 R3 lt;^ R4I Ht ]PU                  R5R6R7      ]! R4      ]! R4      ]! R4      3R7 R8 ll4       t<]P{                  R9]	R:7      R; R< l4       t>]P{                  R=]	R:7      R> R? l4       t?]P{                  R@]	R:7      RA RB l4       t@]P{                  RC]	R:7      RD RE l4       tA]P{                  RFRG]	RH7      RI RJ l4       tB]PU                  RFRK]	RH7      ]! R4      ]! R4      3RL RM ll4       tC]P{                  RNRO]	RH7      RP RQ l4       tD]P{                  RR]RSRT7      RU RV l4       tE]P{                  RWRX]	RH7      RY RZ l4       tF]PU                  RWR[]	RH7      ]! R4      ]! R4      ]! R4      3R\ R] ll4       tG^ R^I Ht ^ R_IH	t	 ]P{                  R`Ra]	RH7      Rb Rc l4       tH] R,          Rd,          Re,          tI]PU                  R`RfR7      Rg Rh l4       tJ]P{                  Ri]	R:7      Rj Rk l4       tK]P{                  RlRm]	RH7      Rn Ro l4       tL]P{                  Rp]	R:7      Rq Rr l4       tM]P{                  Rs4      Rt Ru l4       tN^ RI HtHtHtHtHtHtHt ^ RIH	t	H
t
Ht ]P{                  RvRw]	RH7      RRx Ry ll4       tO^ RzI2HPtP ]PU                  RvR{R7      ]! R4      ]! R4      ]! R4      ]! R4      ]! R4      3R| R} ll4       tQ]P{                  R~]RRT7      R R l4       tR0 RmtS ! R R]4      tTR R ltU^ RIVHWtW ]P{                  R]RRT7      RR R ll4       tX]PU                  RRR7      R R l4       tY^ RIVHWtWHZtZH[t[H\t\ ^ RIHt ^ RIHt ^ RIHtH]t]H^t^ ^ RIt4^ RI H_t_ ]\]`]^! RR7      3,          ta]\]`]^! RR7      3,          tb ! R R]4      tc ! R R]4      td^ RI H_t_ ^ RIVHWtWHZtZH[t[Hete ^ RIHftg ^ RIt4]P{                  R4      ]_! RRRR7      ]_! R^^R7      RRRR^x3R R ll4       th^ RIHtHiti R R ltjR R ltkR R ltlRR ltm^ R^I Ht ^ RItR R ltnR R lto]PU                  R]pR7      R R l4       tq]P                  R]pR7      R R l4       ts]P                  R]pR7      R R l4       tu^ RIVHWtWHete ^ RIHt ^ R^I Ht 0 Rmtv]P{                  R]e]p,          R7      RR R ll4       tw]P{                  R]RRT7      R R l4       tx]P{                  R]	R:7      R R l4       ty]P{                  R]	R:7      R R l4       tz]PU                  R]	R:7      ]! R4      ]! R4      ]! R4      ]! R4      ]! R4      ]! R4      ]! R4      ]! R4      3R R ll4       t{]P{                  R]	R:7      R R l4       t|^ RI}t}^ RI~t~ ^ RIHt RtR R ltR R lt^ R4I Ht ]PU                  R]	R:7      ]! R4      ]! R4      ]! R4      3R R ll4       t]P{                  R4      R R l4       t]P{                  R4      R 4       t]EP                  R4      R 4       tR#   ] d    Rt Li ; i)    )FastAPIRequestForm
UploadFileFileBodyHTTPException)HTMLResponseRedirectResponseJSONResponse)StaticFiles)Jinja2Templates)SessionMiddleware)CryptContext)	BaseModelN	TheL4FPRO)titlez
db.sqlite3none)
secret_keybcryptauto)schemes
deprecatedz/staticz
app/static)	directorystatic)namezapp/templatesc                     \         P                  ! \        4      ;_uu_ 4       p V P                  R 4       V P                  R4       V P                  R4      pVP	                  4        Uu0 uF  q"^,          kK  	  ppRV9  d   V P                  R4       V P                  R4       V P                  R4        V P                  R4        V P                  R4       V P                  R	4      pVP	                  4        Uu0 uF  q"^,          kK  	  ppR
V9  d#   V P                  R4       V P                  R4       V P                  R	4      pVP	                  4        Uu0 uF  q"^,          kK  	  ppRV9  d   V P                  R4       RV9  d   V P                  R4       V P                  R	4      pVP	                  4        Uu0 uF  q"^,          kK  	  ppRV9  d   V P                  R4       RV9  d   V P                  R4       RV9  d   V P                  R4       RV9  d   V P                  R4       R pV! V RR4       V! V RR4       V! V RR4       V! V RR4       V! V RR4       V! V R R4       V! V R!R4       V! V R"R4       V! V R#R4       V! V R$R4       V! V R%R4       V! V R&R4       V! V R'R4       V! V R(R4       V! V R)R4       V! V R*R4       V! V R+R4       V! V R,R4        V P                  R-4       V P                  R.4       V P                  R/4       V P                  R04       V P                  R14       V P                  R24       V P                  4        R3R3R34       R3# u upi   \         P
                   d     ELi ; i  \         P
                   d     ELi ; iu upi u upi u upi   \         P
                   d     Li ; i  + '       g   i     R3# ; i)4a"  
            CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL,
                email TEXT NOT NULL UNIQUE,
                password_hash TEXT NOT NULL,
                created_at TEXT NOT NULL
            )
        a   
            CREATE TABLE IF NOT EXISTS reservations (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                created_at TEXT NOT NULL,
                date TEXT NOT NULL,
                time TEXT NOT NULL,
                duration_minutes INTEGER NOT NULL,
                price_cents INTEGER NOT NULL,
                name TEXT,
                email TEXT,
                phone TEXT,
                notes TEXT,
                user_id INTEGER,
                status TEXT NOT NULL DEFAULT 'confirmada'
            )
        zPRAGMA table_info(reservations)
docente_idz6ALTER TABLE reservations ADD COLUMN docente_id INTEGERzRCREATE INDEX IF NOT EXISTS idx_reservations_docente_id ON reservations(docente_id)zLCREATE INDEX IF NOT EXISTS idx_reservations_user_id ON reservations(user_id)zQALTER TABLE notifications ADD COLUMN deleted_by_sender INTEGER NOT NULL DEFAULT 0zTALTER TABLE notifications ADD COLUMN deleted_by_recipient INTEGER NOT NULL DEFAULT 0PRAGMA table_info(users)rolez@ALTER TABLE users ADD COLUMN role TEXT NOT NULL DEFAULT 'alumno'z@UPDATE users SET role = 'alumno' WHERE role IS NULL OR role = ''phonez'ALTER TABLE users ADD COLUMN phone TEXTavatarz(ALTER TABLE users ADD COLUMN avatar TEXTteamz&ALTER TABLE users ADD COLUMN team TEXTcategoryz*ALTER TABLE users ADD COLUMN category TEXTpositionz*ALTER TABLE users ADD COLUMN position TEXTinjury_historyz0ALTER TABLE users ADD COLUMN injury_history TEXTc                     V P                  R 4      pVP                  4        Uu0 uF  qD^,          kK  	  ppW9  d   V P                  RV RV 24       R# R# u upi )r   zALTER TABLE users ADD COLUMN  N)executefetchall)connr   ddlcurrowexistings   &&&   ./home/mario/Escritorio/furbo/furbo/app/main.pyadd_user_column init_db.<locals>.add_user_columnl   sY    ,,9:C*-,,.9.3A.H9#<TF!C5IJ $ :s   AdniTEXT
birth_datecitydominant_foot	strengths
weaknessestraining_typephysical_workphysical_work_detailssmokingalcoholrecovery
chest_pain
discomfortwhatsapp_contentvideo_permissionprivacy_acceptancedata_confirmationz@ALTER TABLE notifications ADD COLUMN reservation_id INTEGER NULLzYCREATE INDEX IF NOT EXISTS idx_notifications_reservation ON notifications(reservation_id)a  
            CREATE TABLE IF NOT EXISTS "formulario-registro" (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                created_at TEXT NOT NULL,
                expires_at TEXT NOT NULL,
                email TEXT NOT NULL,
                pin TEXT NOT NULL,
                data_json TEXT NOT NULL,
                used INTEGER NOT NULL DEFAULT 0,
                used_at TEXT
            )
        zMCREATE INDEX IF NOT EXISTS idx_form_reg_email ON "formulario-registro"(email)zICREATE INDEX IF NOT EXISTS idx_form_reg_pin ON "formulario-registro"(pin)zTCREATE INDEX IF NOT EXISTS idx_form_reg_expires ON "formulario-registro"(expires_at)N)sqlite3connectDB_PATHr)   r*   OperationalErrorcommit)r+   r-   r.   res_colscolsr1   s         r0   init_dbrM      s   		!	!T  	 	  	$ ll<=&)lln5nsFFn5x'LLQRij 	cd	LLlm	LLop
 ll56"%,,.1.3A.1LL[\LL[\ ll56"%,,.1.3A.1$LLBC4LLCD ll56"%,,.1.3A.1LLABT!LLEFT!LLEF4'LLKL	K 	eV,lF3ff- 	ov6k62lF3ov6 	ov65v>i0i0j&1lF3lF3 	0&90&92F;16:	LL[\ 	pq 	  	 	de`aklO 
"	!@ 6 '' 		 '' 		
 2 2 2\ '' 		e 
"	!	!s   AO)M-:<O7M2	N#O=N*AON/-AON4DO-N9>A%O-O2NO
NON'#O&N''O9OOOOO%	c                      \         P                  ! \        4      p \         P                  V n        V P                  R 4       V # )zPRAGMA foreign_keys = ON;)rF   rG   rH   Rowrow_factoryr)   r+   s    r0   _connrR      s.    ??7#D{{DLL,-K    c                $    V ^8  d   QhR\         /#    returnint)formats   "r0   __annotate__r[      s     " "c "rS   c                      \        4       ;_uu_ 4       p V P                  R 4      P                  4       p\        VR,          ;'       g    ^ 4      uuRRR4       #   + '       g   i     R# ; i)z2SELECT COUNT(1) AS c FROM users WHERE role='admin'cN)rR   r)   fetchonerY   )r+   r.   s     r0   count_adminsr_      sA    	DllOPYY[3s8==q! 
s   ;AA*	c                $    V ^8  d   QhR\         /# rU   )bool)rZ   s   "r0   r[   r[      s     & &D &rS   c                 ,    \        V R ,          4      R8H  # )r    adminstr)mes   &r0   is_adminrg      s    r&z?g%%rS   z/admin/users/deleteadmin_delete_user.c                J    V ^8  d   QhR\         R\        R\        R,          /# )rV   requestuser_idnext_urlNr   rY   re   )rZ   s   "r0   r[   r[      s*     .; .;.;.; Dj.;rS   c                   "   \        V 4      pV'       g   \        R RR7      # \        V4      '       g   \        RRR7      h\	        V4      pV'       g   \        RRR7      h\        VR,          4      \        VR,          4      8X  d   \        R	R
R7      h\        VR,          4      R8X  d   \        4       ^8:  d   \        R	RR7      h\        4       ;_uu_ 4       p VP                  R4       VP                  RW34       VP                  RV34       VP                  RV34       VP                  RV34       VP                  4         RRR4       T'       d>   ^ RIHp T! T4      pTP                  R8X  d   TP                   R8X  d   \        TRR7      # \        RRR7      #   \         d    TP                  4        h i ; i  + '       g   i     L; i5i)/login/  urlstatus_code  z&Solo un admin puede eliminar usuarios.rs   detail  zUsuario no encontrado.id  z$No puedes eliminar tu propia cuenta.r    rc   u$   No puedes eliminar al último admin.BEGINzADELETE FROM notifications WHERE sender_id = ? OR recipient_id = ?z&DELETE FROM reservations  WHERE id = ?zDELETE FROM users WHERE id = ?Nurlparse /admin)current_userr   rg   r	   get_user_by_idrY   re   r_   rR   r)   rJ   	Exceptionrollbackurllib.parser|   schemenetloc)rj   rk   rl   rf   targetr+   r|   ps   &&&     r0   rh   rh      s{     
g	BH#>>B<<4\]]G$F4LMM 2d8}F4L))4Z[[ 6&>g%,.A*=4Z[[ 
D<< <<[^e]op<<@7*M<<87*E<<87*E;;= 
  )X88r>ahh"n#cBBc::  ==? 
s8   CGGA-F$
GA
G$GGG	Gc                $    V ^8  d   QhR\         /# )rV   emailrd   )rZ   s   "r0   r[   r[      s      S rS   c                     \         P                  ! \        4      ;_uu_ 4       p\         P                  Vn        VP                  R V 34      pVP                  4       uuRRR4       #   + '       g   i     R# ; i)z#SELECT * FROM users WHERE email = ?NrF   rG   rH   rO   rP   r)   r^   )r   r+   r-   s   &  r0   get_user_by_emailr      sJ    		!	!T";;ll@5(K||~ 
"	!	!	!   8A&&A7	c                $    V ^8  d   QhR\         /# rV   rk   rX   )rZ   s   "r0   r[   r[      s      C rS   c                     \         P                  ! \        4      ;_uu_ 4       p\         P                  Vn        VP                  R V 34      pVP                  4       uuRRR4       #   + '       g   i     R# ; i)z SELECT * FROM users WHERE id = ?Nr   rk   r+   r-   s   &  r0   r   r      sJ    		!	!T";;ll=zJ||~ 
"	!	!	!r   c                H    V ^8  d   QhR\         R\         R\         R\         /# )rV   r   r   passwordr    rd   )rZ   s   "r0   r[   r[      s(      c #  C rS   c           
      N   \         P                  V4      p\        P                  ! \        4      ;_uu_ 4       pVP                  R WV\        P                  P                  4       P                  4       V34       VP                  4        RRR4       R#   + '       g   i     R# ; i)zSINSERT INTO users (name, email, password_hash, created_at, role) VALUES (?,?,?,?,?)N)pwd_contexthashrF   rG   rH   r)   dtdatetimeutcnow	isoformatrJ   )r   r   r   r    password_hashr+   s   &&&&  r0   create_userr      sn    $$X.M		!	!Ta-););)=)G)G)I4P	
 	 
"	!	!	!s   ABB$	c                      \        4       ;_uu_ 4       p V P                  R \        P                  P	                  4       P                  4       34       V P                  4        RRR4       R#   + '       g   i     R# ; i)zADELETE FROM "formulario-registro" WHERE used=0 AND expires_at < ?N)rR   r)   r   r   r   r   rJ   rQ   s    r0   purge_expired_temp_regsr     sK    	DX[][f[f[m[m[o[y[y[{Z}~ 
s   AA++A<	c                0    V ^8  d   QhR\         R\        /# )rV   lengthrW   rY   re   )rZ   s   "r0   r[   r[     s     
 
 
C 
rS   c                   a \         P                  o RP                  V3R l\        V 4       4       4      p\	        4       ;_uu_ 4       pVP                  RV\        P                  P                  4       P                  4       34      P                  4       pV'       g   VuuRRR4       #  RRR4       K    + '       g   i     K  ; i)Tr}   c              3   P   <"   T F  p\         P                  ! S4      x  K  	  R # 5iN)secretschoice).0_digitss   & r0   	<genexpr>&generate_unique_pin.<locals>.<genexpr>
  s     DmgnnV,,ms   #&zQSELECT 1 FROM "formulario-registro" WHERE pin = ? AND used = 0 AND expires_at > ?N)stringr   joinrangerR   r)   r   r   r   r   r^   )r   pinr+   r.   r   s   &   @r0   generate_unique_pinr     s    ]]F
ggDeFmDDWW,,cbkk((*4467 hj   W
  WWWs   	AB55C	c                $    V ^8  d   QhR\         /# rV   rj   r   )rZ   s   "r0   r[   r[     s     ( (' (rS   c                 t    V P                   P                  R 4      pV'       g   R# \        \        V4      4      # )rk   N)sessiongetr   rY   )rj   rk   s   & r0   r   r     s+    oo!!),G#g,''rS   c                      \         P                  ! \        4      ;_uu_ 4       p \         P                  V n        V P                  R 4      pVP                  4       uuRRR4       #   + '       g   i     R# ; i)zCSELECT id, name, email FROM users WHERE role='alumno' ORDER BY nameNrF   rG   rH   rO   rP   r)   r*   )r+   r-   s     r0   get_studentsr     sF    		!	!T";;ll`a||~ 
"	!	!	!s   6A$$A5	c                $    V ^8  d   QhR\         /# r   rX   )rZ   s   "r0   r[   r[   !  s       rS   c                     \         P                  ! \        4      ;_uu_ 4       p\         P                  Vn        VP                  R V 34      pVP                  4       uuRRR4       #   + '       g   i     R# ; i)a  
            SELECT n.id, n.created_at, n.title, n.body,
                   s.name AS sender_name, n.sender_id, n.recipient_id,
                   n.reservation_id
            FROM notifications n
            LEFT JOIN users s ON s.id = n.sender_id
            WHERE n.recipient_id = ?
              AND COALESCE(n.deleted_by_recipient, 0) = 0
            ORDER BY n.created_at DESC
        Nr   r   s   &  r0   get_notifications_for_userr   !  sS    		!	!T";;ll 	 Z	 ||~ 
"	!	!	!r   c                $    V ^8  d   QhR\         /# )rV   	sender_idrX   )rZ   s   "r0   r[   r[   1  s      c rS   c                     \         P                  ! \        4      ;_uu_ 4       p\         P                  Vn        VP                  R V 34      pVP                  4       uuRRR4       #   + '       g   i     R# ; i)a  
            SELECT n.id, n.created_at, n.title, n.body,
                   r.name AS recipient_name, n.sender_id, n.recipient_id,
                   n.reservation_id
            FROM notifications n
            LEFT JOIN users r ON r.id = n.recipient_id
            WHERE n.sender_id = ?
              AND COALESCE(n.deleted_by_sender, 0) = 0
            ORDER BY n.created_at DESC
        Nr   )r   r+   r-   s   &  r0   get_notifications_sent_by_userr   1  sS    		!	!T";;ll 	 \	 ||~ 
"	!	!	!r   c                0    V ^8  d   QhR\         R\         /# )rV   r   recipient_idrX   )rZ   s   "r0   r[   r[   B  s      c  rS   c                    \         P                  ! \        4      ;_uu_ 4       p\         P                  Vn        VP                  RW34      pVP                  4       uuRRR4       #   + '       g   i     R# ; i)u   Enviadas del docente hacia un alumno concreto, ocultando las que ya están borradas
por cualquiera de las partes cuando se gestiona la bandeja del alumno.a  
            SELECT n.id, n.created_at, n.title, n.body,
                   r.name AS recipient_name, n.sender_id, n.recipient_id,
                   n.reservation_id
            FROM notifications n
            LEFT JOIN users r ON r.id = n.recipient_id
            WHERE n.sender_id = ?
              AND n.recipient_id = ?
              AND COALESCE(n.deleted_by_sender, 0) = 0
              AND COALESCE(n.deleted_by_recipient, 0) = 0
            ORDER BY n.created_at DESC
        Nr   )r   r   r+   r-   s   &&  r0   &get_notifications_sent_by_user_to_userr   B  sV     
	!	!T";;ll  &( ||~ 
"	!	!	!r   )r   z/notificaciones/eliminardelete_notificationc          	      d    V ^8  d   QhR\         R\        R\        R,          R\        R,          /# )rV   rj   notification_idrl   Ntarget_recipient_idrm   )rZ   s   "r0   r[   r[   Z  sD     FD FDFDFD DjFD
 tFDrS   c                 ,  "   \        V 4      pV'       g   \        R RR7      # \        P                  ! \        4      ;_uu_ 4       p\        P
                  Vn        VP                  RV34      P                  4       pV'       g   \        RRR7      h\        VR,          4      pVR,          e   \        VR,          4      MR	p\        VR
,          4      p	Wy8X  d%   VP                  RV34       VP                  4        MVeS   Wx8X  dM   Ve%   \        V4      V	8X  d   VP                  RV34       MVP                  RV34       VP                  4        MSVR,          R9   d9   Ve5   \        V4      V	8X  d%   VP                  RV34       VP                  4        M\        RRR7      hR	R	R	4       V'       d>   ^ RIHp
 V
! V4      pVP                  R8X  d   VP                  R8X  d   \        VRR7      # \        RRR7      #   + '       g   i     Lb; i5i)ro   rp   rq   zBSELECT id, sender_id, recipient_id FROM notifications WHERE id = ?rw   u   Notificación no encontrada.ru   rx   r   Nr   z>UPDATE notifications SET deleted_by_recipient = 1 WHERE id = ?zUUPDATE notifications SET deleted_by_sender = 1, deleted_by_recipient = 1 WHERE id = ?z;UPDATE notifications SET deleted_by_sender = 1 WHERE id = ?r    rt   u&   No puedes eliminar esta notificación.r{   r}   /notificacionesdocenterc   )r   r   rF   rG   rH   rO   rP   r)   r^   r	   rY   rJ   r   r|   r   r   )rj   r   rl   r   rf   r+   r.   me_idr   r   r|   r   s   &&&&        r0   r   r   Y  s     
g	BH#>>		!	!T";;llP
 (* 	
 C8VWWBtH-0-=-ICK()t	3~./  LLP " KKM "u'9 #.37J3K|3[# %&	 Q$& KKM Z//4G4S()\9LLP " KKM  C8`aae 
"j )X88r>ahh"n#cBB 1sCCw 
"	!s&   AHE"H'H7A
HH	H/)response_classc                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s     V V VrS   c                 T   "   \        V 4      p\        P                  R RV RV/4      # 5i)z
index.htmlrj   userr   	templatesTemplateResponserj   rf   s   & r0   homer     ,     	g	B%%lYQS4TUU   &(z/aboutc                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s     V V VrS   c                 T   "   \        V 4      p\        P                  R RV RV/4      # 5i)z
about.htmlrj   r   r   r   s   & r0   aboutr     r   r   z
/membresiac                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s      W rS   c           	      P   "   \         P                  R RV R\        V 4      /4      # 5i)zmembresia.htmlrj   r   r   r   r   rj   s   &r0   	membresiar     s/     %%&67W%9     $&z
/ticketingc                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s     m mW mrS   c           	      P   "   \         P                  R RV R\        V 4      /4      # 5i)zticketing.htmlrj   r   r   r   s   &r0   	ticketingr     s)     %%&6GVUabiUj8kllr   ro   login)r   r   c                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s     Y YW YrS   c                 >   "   \         P                  R RV RR/4      # 5i)
login.htmlrj   errorN)r   r   r   s   &r0   	login_getr     s"     %%lYRV4WXXs   
login_postc                <    V ^8  d   QhR\         R\        R\        /# )rV   rj   r   r   r   re   )rZ   s   "r0   r[   r[     s&     S Sg Sc S SrS   c                 <  "   VP                  4       P                  4       p\        V4      pV'       d#   \        P	                  W$R ,          4      '       g   \
        P                  RRV RR/4      # \        VR,          4      V P                  R&   VR,          V P                  R&   VR,          R8X  g   VR	8X  d   \        V P                  R4      R
R7      # VR,          R8X  d   \        V P                  R4      R
R7      # \        V P                  R4      R
R7      # 5i)r   r   rj   r   u   Credenciales inválidasrx   rk   r    rc   admin@admin.esrp   rq   r   	dashboard)striplowerr   r   verifyr   r   rY   r   r   url_for)rj   r   r   
email_normr   s   &&&  r0   r   r     s     $$&JZ(D {))(4IJJ))*CD
 	
 "%T$ZGOOI"6lGOOF F|w*0@"@GOOG$<#NN	f	"GOOI$>CPPGOOK$@cRRs   DDz/docenter   c                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s      W rS   c           	         "   \        V 4      pV'       g   \        V P                  R 4      RR7      # . p VR,          R9   d   \        4       p\
        P                  RRT RTRT/4      #   \         d    . p L+i ; i5i)	r   rp   rq   r    zdocente.htmlrj   r   studentsr   )r   r   r   r   r   r   r   )rj   rf   r   s   &  r0   docente_dashboardr     s     	g	BGOOG$<#NN Hf:--#~H
 %%wB	
 	  s(   2A<A) A<)A96A<8A99A<z/api/users/{user_id}api_user_detail)r   r   c                0    V ^8  d   QhR\         R\        /# )rV   rk   rj   )rY   r   )rZ   s   "r0   r[   r[     s      3  rS   c                   "   \        V4      pV'       g   \        R RR7      # VR,          R9  d   \        RRR7      h\        P                  ! \
        4      ;_uu_ 4       p\        P                  Vn        VP                  RV 34      P                  4       pRRR4       X'       g   \        R	R
R7      h\        V4      #   + '       g   i     L0; i5i)ro   rp   rq   r    rt   zSolo docentes o adminru   a  
            SELECT
                id, name, email, created_at, role, phone, avatar, dni, birth_date, city, dominant_foot, team, category, position, injury_history, strengths, weaknesses, training_type, physical_work, physical_work_details, smoking, alcohol, recovery, chest_pain, discomfort, whatsapp_content, video_permission, privacy_acceptance, data_confirmation
            FROM users
            WHERE id = ?
        Nrw   Usuario no encontrador   )r   r   r	   rF   rG   rH   rO   rP   r)   r^   dict)rk   rj   rf   r+   r.   s   &&   r0   r   r     s     	g	BH#>> 
&z--4KLL		!	!T";;ll 
 Z
 " 	 
" 4KLL9 
"	!s$   AC 7B?C'C?C	
Cz	/registerregisterc                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s     n n nrS   c           	      |   "   \        V 4      pT;'       g	    R RRRRR/p\        P                  RRV RRRV/4      # 5i)	r   r}   r   r!   register.htmlrj   r   Nr   r   )rj   rf   ctx_users   &  r0   register_getr  
  sL     	g	B;;fb'2w;H%%o	7GUY[ack7lmms   :<register_postc                H    V ^8  d   QhR\         R\        R\        R\        /# )rV   rj   r   r   r   r   )rZ   s   "r0   r[   r[     s/     S S S S Scf SrS   c                   "   VP                  4       P                  4       p\        V4      '       d1   \        P	                  R RV RRRRVP                  4       RVRR//4      # \        V4      ^8  d1   \        P	                  R RV RR	RRVP                  4       RVRR//4      # \        VP                  4       WCR
R7       \        V4      p\        VR,          4      V P                  R&   VR,          V P                  R&   VR,          R8X  g   VR8X  d   \        V P                  R4      RR7      # \        V P                  R4      RR7      # 5i)r  rj   r   zEse email ya exister   r   r   r!   r}   u'   La contraseña debe tener 6+ caracteresalumnor    rx   rk   r    rc   r   rp   rq   r   )r   r   r   r   r   lenr   rY   r   r   r   )rj   r   r   r   r   r   s   &&&&  r0   r  r    s`    $$&J$$))*?&RVR\R\R^`gisu|  A  JB  C
 	
 8}q))*SU[^dfjfpfpfrt{  ~H  JQ  SU  ^V  W
 	
 

jB Z(D!$T$ZGOOI"6lGOOF F|w*0@"@GOOG$<#NNGOOK$@cRRs   E	E)r	   )r
   z/academy-registeracademy_register_getc                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[   3  s       rS   c                 T   "   \        V 4      p\        P                  R RV RV/4      # 5i)zacademy-register.htmlrj   r   r   r   s   & r0   r  r  2  s1     	g	B%%	GVR( r   uploadsacademyacademy_register_postc                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[   >  s     p< p< p<rS   c                 .
  a "   V P                  4       G R j  xL
 pVP                  R4      ;'       g    RP                  4       P                  4       pVP                  R4      ;'       g    RP                  4       pVP                  R4      ;'       g    RpV'       g   \	        RRR7      hV'       d   \        V4      ^8  d   \	        RRR7      hV'       d   \        V4      ^8  d   \	        RR	R7      h\        V4      pV'       d   \	        R
RR7      h^ R Ip^ R Ip^ R I	p^ R I
p	^ R Ip
VP                  P                  4       pR pVP                  R4      p\        V\        4      '       Ed   VP                  '       Ed   VP!                  4       G R j  xL
 pV'       d   V
P"                  P%                  VP                  4      ^,          P                  4       ;'       g    Rp\&        R,          R,          R,          pV
P(                  ! VRR7       VP*                  ! RRV4      ;'       g    RpV RVP,                  ! ^4       V 2pVV,          p\/        VR4      ;_uu_ 4       pVP1                  V4       R R R 4       RV 2p\3        VP                  4       W$RR7       \        V4      p\5        VR,          4      p/ o VP7                  4        F5  w  pp\        V\        4      '       d   K  VRN9  g   K'  \9        V4      S V&   K7  	  V'       d+   VS R&   \        V\        4      '       d   VP                  S R&   V 3R lp/ RV! RR4      bR V! R 4      bR!V! R"R!4      bR#V! R#4      bR$V! RR$4      bR%V! R&R%R'4      bR(V! R(4      bR)V! R*R+R)4      bR,V! R-4      bR.V! R.4      bR/V! R/4      bR0V! R14      bR2V! R34      bR4V! R54      bR6V! R64      bR7V! R74      bR8V! R84      bR9V! R:4      R;V! R;4      R<V! R=4      R>V! R?4      R@V! RA4      RBV! RC4      RDV! RERD4      /Cp. . ppVP7                  4        F.  w  ppVP;                  V RFV RG24       VP;                  V4       K0  	  VP;                  V4        \=        4       ;_uu_ 4       pVP?                  RHRIPA                  V4       RJ2V4       VPC                  4        R R R 4       \G        RKRRLRM/4      #  EL ELF  + '       g   i     ELl; i  + '       g   i     L9; i  \D         d     LIi ; i5i)ONr   r}   r   r   ry   zEl email es obligatorio.ru   u(   Indica tu nombre (mínimo 2 caracteres).u0   La contraseña debe tener al menos 6 caracteres.i  u3   Ya existe un usuario con ese email. Inicia sesión.playerPhoto.jpgr   r  r  Texist_okz
[^a-z0-9]+-r   r   wbz/static/uploads/academy/r	  r
  rx   playerPhoto_originalc                  R   < V  F  pSP                  V4      pVR9  g   K  Vu # 	  R # )NNr}   null)r   )keyskvaldatas   *  r0   pick#academy_register_post.<locals>.pickx  s-    A((1+C,,
  rS   r!   whatsappr3   r5   	birthDater6   r"   r#   currentTeamclubr$   r%   currentPositionpreferredPositionr7   dominantFootr8   r9   r:   trainingTyper;   physicalWorkr<   physicalWorkDetailsr=   r>   r?   r@   	chestPainrA   rB   whatsappContentrC   videoPermissionrD   privacyAcceptancerE   dataConfirmationr&   injuryHistoryz = COALESCE(?, )zUPDATE users SET , z WHERE id = ?okredirectro   r  )$formr   r   r   r	   r  r   r   r   rejsonosr   
isinstancer   filenamereadpathsplitextBASE_DIRmakedirssub	token_hexopenwriter   rY   itemsre   appendrR   r)   r   rJ   r   r   )!rj   r8  r   r   r   r/   r   r   r9  r:  r;  nowsaved_photo_publicplayer_photocontentextuploads_dir
email_slugr=  	file_pathfr   rk   r  vr"  update_valscols_sqlparamscolr   r+   r!  s!   &                               @r0   r  r  =  s    D XXg$$"++-335EXXf$$"++-D$**H4NOO3t9q=4^__s8}q(4fgg !'H4ijj000
++


C 88M*L,
++0E0E0E$))++''""<#8#89!<BBDNNC"X-	9IEKKKd3sE:DDfJ$Qw'8'8';&<SEBH#h.Ii&&!  '#;H:!F 

eH=U#D$t*oG D

1a$$&&!fDG	 
 0]lJ//+7+@+@D'(gz!: 	e 	k<!@	
 	f 	mX!> 	mVV!D 	j!1 	&79Lj!Y 	n!5 	k!2 	l!3 	n!5" 	n!5#$ 	 &;!<%& 	i'( 	i)* 	j!1+, 	k!2l!3&7!8&7!8&9!:&8!9o7G!H=KB 2fH%%'S3%se156c ( MM'WWLL,TYYx-@,AOQWXKKM  tZ:;;_  4 , '&&J W  s   TST6T+(T
TT4$TB'TTST!A T"AT/9T(S:A:T9TE$T8T 
6S1 T TTS.	(	T1T	<T  TT TTTTz/info-usuariosc                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s       rS   c                    "   \        V 4      pV'       g   \        V P                  R 4      RR7      # \        P	                  RRV RV/4      # 5i)r   rp   rq   zinfo-usuarios.htmlrj   r   r   r   r   r   r   r   s   & r0   info_usuariorZ    sM     	g	BGOOG$<#NN%%&:7=     A
Az
/dashboardr   c                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s     Z ZW ZrS   c                    "   \        V 4      pV'       g   \        V P                  R 4      RR7      # \        P	                  RRV RV/4      # 5i)r   rp   rq   zdashboard.htmlrj   r   rY  r   s   & r0   r   r     sF     	g	BGOOG$<#NN%%&6GVUW8XYYr[  r~   c                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s     X X XrS   c                 ~   "   \        V 4      pV'       g   \        R RR7      # \        P                  RRV RV/4      # 5i)ro   rp   rq   z
admin.htmlrj   r   r   r   r   r   rj   r   s   & r0   rc   rc     s<      DH#>>%%lYQU4VWW   ;=z/make-me-adminc                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s     	M 	M 	MrS   c           	      `  "   \        V 4      pV'       g   \        R R/RR7      # \        P                  ! \        4      ;_uu_ 4       pVP                  R\        VR,          4      34       VP                  4        RRR4       \        RRVR	,           R
2/4      #   + '       g   i     L(; i5i)r   No autenticado  )rs   z*UPDATE users SET role='admin' WHERE id = ?rx   NmessagezUsuario r   z ahora es admin)r   r   rF   rG   rH   r)   rY   rJ   )rj   rf   r+   s   &  r0   make_me_adminrh    s     	g	BW&67SII		!	!TAC4MCST 
" hr&zl/$JKLL	 
"	!s   AB.4B; B.B+	&B.r   notificacionesc                >    V ^8  d   QhR\         R\        R,          /# )rV   rj   rk   Nr   rY   )rZ   s   "r0   r[   r[     s"     R R' RC$J RrS   c                  "   \        V 4      pV'       g   \        RRR7      # \        VR,          4      pRpVeH    \        V4      pV'       d4   VR,          R9   d&   \	        V4      pV'       d   \        VR,          4      p\        V4      p. pVR,          R9   dA   V'       d   \        \        VR,          4      V4      pM\        \        VR,          4      4      p. pVR,          R9   d   \        4       pR pT;'       g    .  U	u. uF
  q! V	4      NK  	  p
p	. p/ p. pV'       d   \        P                  ! \        4      ;_uu_ 4       p\        P                  Vn        VP                  RV34      P                  4       pRRR4       T;'       g    .  Uu. uF
  q! V4      NK  	  ppT;'       g    .  Uu/ uF  p\        VR,          4      V! V4      bK  	  pp\         P#                  R	R
T RTRV'       d   \%        V4      MRRVRVRVRV
RVRVRV/
4      #   \         d    Rp ELi ; iu up	i   + '       g   i     L; iu upi u upi 5i)z
Por defecto muestra TU bandeja.
Si `user_id` viene en la query y eres docente/admin, muestra la bandeja de ese alumno
y las enviadas del docente filtradas a ese alumno.
ro   rp   rq   rx   Nr    c                      V P                  4        Uu/ uF  qW,          bK  	  up# u upi   \         d    \        T 4      u # i ; ir   )r  r   r   )rr  s   & r0   _row_to_dict$notificaciones.<locals>._row_to_dict  sA    	%&VVX.XqtGX... 	7N	s   - (- - AAz
                SELECT id, user_id, date, time, duration_minutes, status, created_at, name, email, phone, notes, price_cents
                FROM reservations
                WHERE user_id = ?
                ORDER BY date ASC, time ASC
            znotificaciones.htmlrj   r   	view_usernotificationssent_notificationsr   notifications_jsonappointmentsappointments_jsonappointments_mapr   )r   r   rY   r   r   r   r   r   r   rF   rG   rH   rO   rP   r)   r*   r   r   r   )rj   rk   rf   target_user_idrq  inboxsentr   ro  nrt  ru  rw  rv  r+   as   &&              r0   ri  ri    s@     
g	BH#>>D]NI	'lG r&z%99&w/I!$Yt_!5 '~6E D	&z))9#bh-XD1#bh-@DH	&z))> 5:KKRKAKa,q/KA L__W%%&{{D<< )
 !"$
 %-HJ  & 8D7I7Ir7IK7I\!_7IKDPDVDVTVDVXDVaC$L,q/9DVX %%wBIi4U $ "4L!2 0	
 e  	G	< B &% LXs   9IH IAI%AIIH,2I
7H1III'
I2I7"I	I8 IH)%I(H))I1I	<Ir{   create_notificationc                |    V ^8  d   QhR\         R\        R\        R\        R\        R,          R\        R,          /# )rV   rj   r   r   bodyrl   Nreservation_idrm   )rZ   s   "r0   r[   r[   7  sT     =D =D=D=D =D 	=D
 Dj=D $J=DrS   c                 V  "   \        V 4      pV'       g   \        R RR7      # VR,          R9  d   \        RRR7      hT;'       g    RP                  4       pT;'       g    RP                  4       pV'       d	   V'       g   \        RR	R7      h \	        V4      pRpTe   \        T4      P                  4       R8w  d    \	        T4      p\        P                  ! \        4      ;_uu_ 4       p\        P                  Tn        TP                  RT34      P                  4       p	T	'       g   \        RRR7      h\	        T	R,          ;'       g    ^ 4      T8w  d   \        RRR7      h RRR4       \        P                  ! \        4      ;_uu_ 4       pTP                  R\        P                  P!                  4       P#                  4       \	        TR,          4      YY734       TP%                  4        RRR4       T'       d;   \'        T4      p
T
P(                  R8X  d   T
P*                  R8X  d   \        TRR7      # \        RRR7      #   \
         d    \        RR
R7      hi ; i  \
         d    \        RRR7      hi ; i  + '       g   i     EL#; i  + '       g   i     L; i5i)ro   rp   rq   r    rt   z3Solo docentes o admin pueden enviar notificaciones.ru   r}   ry   u#   Título y mensaje son obligatorios.u   Destinatario inválido.Nu   Reserva inválida.z1SELECT id, user_id FROM reservations WHERE id = ?rw   zReserva no encontrada.rk   z/La reserva no pertenece al alumno seleccionado.z
            INSERT INTO notifications (created_at, sender_id, recipient_id, title, body, is_read, reservation_id)
            VALUES (?, ?, ?, ?, ?, 0, ?)
            rx   r   r   )r   r   r	   r   rY   r   re   rF   rG   rH   rO   rP   r)   r^   r   r   r   r   rJ   r|   r   r   )rj   r   r   r  rl   r  rf   res_id_to_saver+   resparseds   &&&&&&     r0   r}  r}  6  s7     
g	BH#>>	&z--4ijj[[b!EJJBD4YZZO<(
 N!c.&9&?&?&AR&G	N 0N __W%%&{{D,,C! hj  #<TUU3y>&&Q'<7#<mnn 8 & 
	!	!T [[!++-s2d8}lSWh	
 	 
" (#==B6==B#6#cBB  1sCCM  O4MNNO  	NC8LMM	N%%% 
"	!s   AJ)J)!J):J)J)I
 $J) I& "J)-A JJ(*J)A!J3J)AJ)
I##J)&I??J)J		J)J&	!J)z/api/teachersapi_teachersc                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[   {  s       rS   c                 r  "   \        V 4      pV'       g   \        R RR7      # \        P                  ! \        4      ;_uu_ 4       p\        P
                  Vn        VP                  R4      pVP                  4        Uu. uF  p\        V4      NK  	  ppRRR4       V# u upi   + '       g   i     X# ; i5i)ro   rp   rq   z\SELECT id, name, email, created_at, role FROM users WHERE role = 'docente' ORDER BY name ASCN)
r   r   rF   rG   rH   rO   rP   r)   r*   r   )rj   r   r+   r-   rn  r!  s   &     r0   r  r  z  s       DH#>>		!	!T";;llj
 "%0AQ0 
" K 1 
"	! Ks0   AB79B#>BB#
B7B##B4	.	B7c                   ,   a  ] tR tRt o V 3R ltRtV tR# )
RoleUpdatei  c                &   < V ^8  d   Qh/ S[ ;R&   # )rV   r    rd   )rZ   __classdict__s   "r0   r[   RoleUpdate.__annotate__  s     
I rS    N)__name__
__module____qualname____firstlineno____annotate_func____static_attributes____classdictcell__r  s   @r0   r  r    s      rS   r  c                0    V ^8  d   QhR\         R\        /# )rV   rk   r    r   )rZ   s   "r0   r[   r[     s      3 c rS   c                     \         P                  ! \        4      ;_uu_ 4       pVP                  R W34       VP	                  4        RRR4       R#   + '       g   i     R# ; i)z&UPDATE users SET role = ? WHERE id = ?N)rF   rG   rH   r)   rJ   )rk   r    r+   s   && r0   set_user_roler    s<    		!	!T=O 
"	!	!	!s   $AA"	)Optionalz
/api/users	api_usersc                F    V ^8  d   QhR\         R\        \        ,          /# )rV   rj   r    )r   r  re   )rZ   s   "r0   r[   r[     s     . .W .HSM .rS   c                   "   \        V 4      pV'       g   \        R RR7      # Rp. pV'       d0   RpVP                  VP                  4       P	                  4       4       \
        P                  ! \        4      ;_uu_ 4       p\
        P                  Vn	        VP                  RV R2V4      pVP                  4        Uu. uF  p\        V4      NK  	  ppRRR4       V# u upi   + '       g   i     X# ; i5i)ro   rp   rq   r}   zWHERE lower(role) = ?u  
            SELECT
                id,
                name,
                email,
                created_at,
                role,          -- ¡IMPORTANTE!
                phone,
                avatar,
                dni,
                birth_date,
                city,
                dominant_foot,
                strengths,
                weaknesses,
                training_type,
                physical_work,
                physical_work_details,
                smoking,
                alcohol,
                recovery,
                chest_pain,
                discomfort,
                whatsapp_content,
                video_permission,
                privacy_acceptance,
                data_confirmation
            FROM users
            z&
            ORDER BY id DESC
        N)r   r   rH  r   r   rF   rG   rH   rO   rP   r)   r*   r   )	rj   r    r   whererU  r+   r-   rn  r!  s	   &&       r0   r  r    s       DH#>>EF'djjl((*+		!	!T";;ll  8 G 	9< => "%0AQ0C 
"D K 1C 
"	!D Ks5   ,C7AC7 >C#>CC#
C7C##C4	.	C7z/api/users/{user_id}/roleapi_users_set_rolec                <    V ^8  d   QhR\         R\        R\        /# )rV   rk   payloadrj   )rY   r  r   )rZ   s   "r0   r[   r[     s&     %O %Oc %OJ %O %OrS   c                   "   \        V4      pV'       g   \        R RR7      # \        \        VR,          4      4      pV'       d&   \	        VR,          4      P                  4       R8w  d   \        RRR7      h\        V 4      pV'       g   \        R	R
R7      hVP                  ;'       g    RP                  4       P                  4       pV\        9  d   \        RRR7      h\	        VR,          4      P                  4       pVR8H  pT;'       d    VR8g  p	Wv8X  d   RRRV RVRR/# V	'       d   \        4       p
V
^8:  d   \        RRR7      h\        W4       RRRV RVRR/# 5i)ro   rp   rq   rx   r    rc   rt   z%No tienes permisos para cambiar rolesru   rw   r   r}   ry   u   Rol inválidor6  Trk   changedFuT   Debe existir al menos un usuario con rol admin. No puedes degradar al último admin.)r   r   r   rY   re   r   r	   r    r   ALLOWED_ROLESr_   r  )rk   r  rj   rf   me_rowr   new_rolecurrent_role	was_adminis_demoting_adminadmins_counts   &&&        r0   r  r    sI    	g	BH#>>C4M*FS(..0G;4[\\G$F4KLL""))+113H}$ODDvf~&,,.L'I!99h'&9 dIw)USS #~1m  '$$	7FHiNNs   B(E!+A$E!E!.3E!)r  DictAny	Annotated)r   )r   )r   FieldStringConstraints)Queryz^\d{4}-\d{2}-\d{2}$)patternz^\d{2}:\d{2}$c                   r   a  ] tR tRt o ]! ^<^RR7      t]! ^ ^ R7      tRtRtRt	Rt
RtRtRtV 3R ltRtV tR# )	ReservationIni  geler  N
confirmadac                  < V ^8  d   Qh/ S[ ;R&   S[;R&   S[;R&   S[;R&   S[S[,          ;R&   S[S[,          ;R&   S[S[,          ;R&   S[S[,          ;R&   S[S[,          ;R	&   S[S[,          ;R
&   S[S[,          ;R&   # rV   datetimeduration_minutesprice_centsrk   r   r   r!   statusnotesr   )DateStrTimeStrrY   r  re   )rZ   r  s   "r0   r[   ReservationIn.__annotate__  s     
M 
M  5  %	 
 c]!  3-  C=  C=  SM(  C=  $ rS   r    )r  r  r  r  r  r  r  rk   r   r   r!   r  r  r   r  r  r  r  s   @r0   r  r    sK      ""u5Q1~K!GDEE(FE $J  rS   r  c                   z   a  ] tR tRt o RtRt]! R^RR7      t]! R^ R7      tRt	Rt
RtRtRtRtRtV 3R ltRtV tR# )ReservationUpdatei  Nr  r  c                N  < V ^8  d   Qh/ S[ S[,          ;R&   S[ S[,          ;R&   S[ S[,          ;R&   S[ S[,          ;R&   S[ S[,          ;R&   S[ S[,          ;R&   S[ S[,          ;R&   S[ S[,          ;R&   S[ S[,          ;R	&   S[ S[,          ;R
&   S[ S[,          ;R&   # r  )r  r  r  rY   re   )rZ   r  s   "r0   r[   ReservationUpdate.__annotate__  s     
7
" 
7
"  smA  #2	 
 c]!  3-  C=  C=  SM   C=  $ rS   r  r  )r  r  r  r  r  r  r  r  r  rk   r   r   r!   r  r  r   r  r  r  r  s   @r0   r  r    sT     "D"D&+DQ5&A!&t!2K!GDEE FE $J  rS   r  )r  r  r  List)r  z/api/public/availabilityi  i  r  08:0022:00c                    V ^8  d   QhR\         \        ,          R\         \        ,          R\         \        ,          R\         \        ,          R\        R\        R\        /# )rV   yearmonth	date_fromdate_to	open_time
close_timeslot_minutes)r  rY   re   )rZ   s   "r0   r[   r[   '  sg     M M
3-MC=M }M c]	M M M MrS   c           
        aa"   V '       d   V'       dx   \        W^4      pV^8X  d   \        V ^,           ^^4      pM\        W^,           ^4      pVP                  4       pV\        P                  ! ^R7      ,
          P                  4       pV'       d	   V'       g   \	        RRR7      hRp	\
        P                  ! \        4      ;_uu_ 4       p
\
        P                  V
n	        V
P                  WV34      P                  4       pRRR4       / pX FQ  pVR,          pVP                  V. 4      P                  RVR,          R	\        VR	,          4      R
VR
,          /4       KS  	  \        WES4      p/ pVP!                  4        Fp  w  pp/ pV FY  p\#        V4      o\$        ;QJ d     VV3R lV 4       F  '       g   K   RM	  RM! VV3R lV 4       4      pV'       d   RMRVV&   K[  	  RVRV/VV&   Kr  	   \        P&                  P)                  V4      p\        P&                  P)                  V4      pVV,
          P*                  ^,           p\-        V4       FR  pV\        P                  ! VR7      ,           P                  4       pVV9  g   K8  RV Uu/ uF  pVRbK  	  upR. /VV&   KT  	  \1        VRR/R7      #   + '       g   i     EL; iu upi   \.         d     L5i ; i5i)   )daysry   z,Proporciona year+month o date_from y date_toru   z
      SELECT date, time, duration_minutes, status
      FROM reservations
      WHERE date >= ? AND date <= ?
        AND status != 'cancelada'
      ORDER BY date ASC, time ASC
    Nr  r  r  r  c           
   3      <"   T F3  p\        SS\        VR ,          4      \        VR,          4      4      x  K5  	  R# 5i)r  r  N)_overlap_to_minutesrY   )r   bs_startr  s   & r0   r   &public_availability.<locals>.<genexpr>\  s8     }v|qr'<QvY9OQTUVWiUjQkllv|s   ;>TFoccupied	availableslotsbusy_blockszCache-Controlzpublic, max-age=30)headers)date_clsr   r   	timedeltar	   rF   rG   rH   rO   rP   r)   r*   
setdefaultrH  rY   generate_daily_slotsrG  r  anyr  fromisoformatr  r   r   r   )r  r  r  r  r  r  r  startendsqlr+   rowsbusyrn  d	std_slotsoutdayblocksslot_statesss_busystart_dend_ddeltair  s   &&&&&&f                   @r0   public_availabilityr  &  s}     a(B;461a(C4q!,COO%	1--88:G4bccC 
	!	!T";;||CW!56??A 
"
 -/DfI2%%AfIA&8$9 :ak'
 	  %YLII &(Czz|VA!!nGS}v|}SSS}v|}}F+1Z{KN 
 [6
C $	''''	2''''07?((1,uA2<<Q//::<A|"i$Iiani$I=Z\^A  -&  [ 
"	!	!P %J sy   K*A>K*K*1K*7K B7K*> K*K*8BK K K$K 1K* K		K*K K'$K*&K''K*)r   r  c                R    V ^8  d   QhR\         R\        \        \        3,          /# )rV   r  rW   )re   tuplerY   )rZ   s   "r0   r[   r[     s"      3 5S> rS   c                 J    \        \        V P                  R 4      4      w  rW3# ):)maprY   split)r  hms   &  r0   _parse_hhmmr    s    sAGGCL!DA4KrS   c                0    V ^8  d   QhR\         R\        /# )rV   hhmmrW   )re   rY   )rZ   s   "r0   r[   r[     s      c c rS   c                 <    \        V 4      w  rV^<,          V,           # )<   )r  )r  r  r   s   &  r0   r  r    s    tDAR4!8OrS   c          
      T    V ^8  d   QhR\         R\         R\         R\         R\        /# )rV   a_starta_durb_startb_durrW   )rY   ra   )rZ   s   "r0   r[   r[     s6     J Jc J# J JC JD JrS   c                 H    W,           V8*  ;'       g    W#,           V 8*  '       * # r   r  )r  r  r	  r
  s   &&&&r0   r  r    s!    7*HHgo.HIIrS   c                     \        V 4      p\        V4      p. pTpWb,           V8:  d4   V^<,          qv^<,          pVP                  VR RVR 24       Wb,          pK@  V# )r  02dr  )r  rH  )		open_hhmm
close_hhmmr  r  r  r  tr  r   s	   &&&      r0   r  r    sb    	"E
#C
CA

c
!GRQ

aWAaW%&	JrS   c                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s      7 rS   c                 N   \        V 4      pV'       g   \        R RR7      h\        V\        P                  4      '       d6   RVP                  4       9   d   VR,          e   \        VR,          4      MRpM\        VP                  RR4      4      pVR8w  d   \        RRR7      hV# )rf  re  ru   r    r}   rc   rt   zSolo administradores)r   r	   r<  rF   rO   r  re   r   )rj   rf   r    s   &  r0   require_adminr    s    	g	B4DEE "gkk"""(BGGI"5"V*:Ps2f:VX266&"%&w4JKKIrS   c                f    V ^8  d   QhR\         P                  R\        \        \        3,          /# )rV   r.   rW   )rF   rO   r  re   r  )rZ   s   "r0   r[   r[     s&      '++ $sCx. rS   c                     R V R ,          RV R,          RV R,          RV R,          RV R,          RV R,          RV R,          RV R,          RV R,          R	V R	,          R
V R
,          RV R,          RRV P                  4       9   d   V R,          /# R/# )rx   
created_atr  r  r  r  r   r   r!   r  rk   r  r   N)r  )r.   s   &r0   _reservation_row_to_dictr    s    c$ic,'FFC 23s=)FWWW3y>#h-<388:+Ec,'  LP rS   z/api/reservations)response_modelc                0    V ^8  d   QhR\         R\        /# )rV   rj   r  )r   r  )rZ   s   "r0   r[   r[     s     j) j)7 j)] j)rS   c                 l	  "   \        V 4        \        P                  ! VP                  R 4       TP                  '       d3   \        TP                  4      ^8  g   TP                  ^,          R8w  d   \        RRR7      h \        TP                  R,          4      p\        TP                  R,          4      p^ Tu;8:  d   ^<8  d   M M^ Tu;8:  d   ^8  g   M \        RRR7      hT^ 8X  d   T^ 8X  d   \        RR	R7      h^Tu;8:  d   ^8  g   M \        RR
R7      hTP                  e   TP                  ^ 8:  d   \        RRR7      hTP                  R8  d   \        RRR7      hTP                  pTP                  pTP                  pTP                  '       d   \        P                  ! \         4      ;_uu_ 4       p\        P"                  Tn        TP'                  RTP                  34      P)                  4       pT'       g   \        RRR7      hT'       g
   TR,          pT'       g
   TR,          pT'       g
   TR,          pRRR4       MT'       d	   T'       g   \        RRR7      hTP*                  p	T	ex   \        P                  ! \         4      ;_uu_ 4       p\        P"                  Tn        TP'                  RT	34      P)                  4       p
T
'       g   \        RRR7      h RRR4       \        P,                  ! 4       P/                  RR7      p \        P                  ! \         4      ;_uu_ 4       p\        P"                  Tn        TP'                  RTTP                  TR RTR 2TP                  TP0                  TTTTP2                  TP                  TP4                  ;'       g    RT	34      pTP6                  pTP9                  4        TP'                  RT34      P)                  4       pRRR4       \=        X4      #   \         d    \        RRR7      hi ; i  \         d    \        RRR7      hi ; i  + '       g   i     EL; i  + '       g   i     ELv; i  + '       g   i     L{; i  \        P:                   d   p\        RRT 2R7      hRp?ii ; i5i)%Y-%m-%dry   (   Fecha inválida. Usa formato YYYY-MM-DD.ru   r  "   Hora inválida. Usa formato HH:MM.NrV   N      N   Hora inválida.,No se admiten reservas a medianoche (00:00).&   Hora fuera de horario (08:00–22:00).N   Duración inválida.r     Duración demasiado larga.3SELECT id, name, email, phone FROM users WHERE id=?rw   r   r   r   r!   z9Nombre y email son obligatorios si no seleccionas alumno.FSELECT id FROM users WHERE id=? AND LOWER(COALESCE(role,''))='docente'u   Docente inválidoseconds)timespeca  
                INSERT INTO reservations (
                    created_at, date, time, duration_minutes, price_cents,
                    name, email, phone, notes, user_id, status, docente_id
                )
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            r  r  %SELECT * FROM reservations WHERE id=?zError al crear: )r  r   strptimer  r   r	   r  r  rY   r  r   r   r!   rk   rF   rG   rH   rO   rP   r)   r^   r   r   r   r  r  r  	lastrowidrJ   IntegrityErrorr  )rj   r  hhmmr   r   r!   r+   ur   r  r  r-   ridr.   es   &&              r0   api_reservations_creater4    s    '`',,
3
 <<<3w||,q0GLLOs4J4XYYZb!"c"# LbLQ"\r\4EFF 
Qw274bccLbL4\]] '7+C+Cq+H4JKK$&4PQQ <<DMMEMME__W%%&{{DE" hj  #<STTy'
'
 &%" 5R  ##J__W%%&{{DX hj  #<OPP  & ",,i,@JL__W%%&{{D,,   c(!Bs8$((##//<C( --CKKM,,FOXXZC1 &8 $C((G  `4^__`  Z4XYYZ0 &%%4 &%% &%2 !! L6Fqc4JKKLs   R4!P R4?R48P0 :C(R4#"R4AQ#Q4Q	QR4R4'?R4&AQ 3-R4!"R B>Q4R 	R4P--R40Q		R4Q		R4 Q1	+	R44R	?R R4R R1R,,R11R4z/api/reservations/{res_id}c                <    V ^8  d   QhR\         R\        R\        /# )rV   rj   res_idr  )r   rY   r  )rZ   s   "r0   r[   r[   7  s'     G G7 GC GJ[ GrS   c                 L  "   \        V 4       VP                  R R7      P                  4        UUu/ uF  w  r4W4bK	  	  pppV'       g   \        RRR7      hRV9   d+   VR,          e     \        P
                  ! VR,          R4       R	V9   d   VR	,          e   VR	,          pV'       d   \        V4      ^8  g   V^,          R
8w  d   \        RRR7      h \        VR,          4      p\        VR,          4      p^ Tu;8:  d   ^<8  d   M M^ Tu;8:  d   ^8  g   M \        RRR7      hT^ 8X  d   T^ 8X  d   \        RRR7      h^Tu;8:  d   ^8  g   M \        RRR7      hTR R
TR 2TR	&   RV9   d=   VR,          e2   VR,          p	V	^ 8:  d   \        RRR7      hV	R8  d   \        RRR7      hRV9   Ed   VR,          '       d   \        P                  ! \        4      ;_uu_ 4       p
\        P                  V
n        V
P                  RVR,          34      P                  4       pV'       g   \        RRR7      hRV9  g   VP!                  R4      '       g   VR,          VR&   RV9  g   VP!                  R4      '       g   VR,          VR&   RV9  g   VP!                  R4      '       g   VR,          VR&   RRR4       RV9   ds   VR,          pVf   R# \        P                  ! \        4      ;_uu_ 4       p
\        P                  V
n        V
P                  RV34      P                  4       pRRR4       R# R# u uppi   \         d    \        RRR7      hi ; i  \         d    \        RRR7      hi ; i  + '       g   i     L; i  + '       g   i     R# ; i5i)T)exclude_unsetry   zNada que actualizarru   r  Nr  r  r  r  r  r  r  r"  r#  r$  r  r  r%  r  r&  rk   r'  rw   r   r   r   r!   r   r(  )r  r   rG  r	   r   r,  r   r  rY   rF   rG   rH   rO   rP   r)   r^   r   )rj   r6  r  r  rR  updatesr  r/  r0  dminr+   r1  r   r  s   &&&           r0   api_reservations_updater;  6  s4    ' '4 @ F F HI Hqt HGI4IJJ WV_8	dgfoz:
 WV_8FOCFQJ!A$#+C8\]]	^QrUB#af+R R"b2C8IJJ7rQwC8fggR"C8`aaHAbX. W$1C)D)P)*19C8NOO$;C8TUU G	 2 2__W%%&{{DE#% hj  #<STTW$GKK,?,?"#F)g%W[[-A-A#$W: g%W[[-A-A#$W:  &  wl#;))T#*;; LL\F (*  *) s J  	dC8bcc	d  	^C8\]]	^, &%, *))s   /N$L?*N$)M "N$*+N$$M! :CN$	"N$+A0M=)M=)M=0M=<A N$<7N3N$MN$!M::N$=N	N$N!		N$c                0    V ^8  d   QhR\         R\        /# )rV   rj   r6  rk  )rZ   s   "r0   r[   r[     s     	. 	.7 	.C 	.rS   c                   "   \        V 4       \        P                  ! \        4      ;_uu_ 4       p\        P                  Vn        VP                  R V34      P                  4       pV'       g   \        RRR7      hVP                  RV34       VP                  4        RRR4       RRRV/#   + '       g   i     L; i5i)	r+  rw   zReserva no encontradaru   z#DELETE FROM reservations WHERE id=?Nr6  T
deleted_id)
r  rF   rG   rH   rO   rP   r)   r^   r	   rJ   )rj   r6  r+   r.   s   &&  r0   api_reservations_deleter?    s     '		!	!T";;llBVINWWYC8OPP:VIF 
" $f-- 
"	!s   .C A/B-C -B=	8C )r  r  c                    V ^8  d   QhR\         R\        \        ,          R\        \        ,          R\        \        ,          R\        \        ,          R\        \        ,          /# )rV   rj   r  r  rk   r  r   )r   r  re   rY   )rZ   s   "r0   r[   r[     s`     Q7 Q7Q7}Q7 c]Q7 c]	Q7
 SMQ7 Q7rS   c           	      l  "   \        V 4       R  R lpV'       d	   V! V4       V'       d	   V! V4       V'       d   V'       d	   W8  d   Y!r!RpV'       dW   VP                  4       P                  4       pV\        9  d.   \	        RRRP                  \        \        4      4       R2R7      h. p. p	V'       d#   VP                  R4       V	P                  V4       V'       d#   VP                  R	4       V	P                  V4       Ve#   VP                  R
4       V	P                  V4       V'       d#   VP                  R4       V	P                  V4       Ve#   VP                  R4       V	P                  V4       V'       d   RRP                  V4      ,           MRp
RV
 R2p\        P                  ! \        4      ;_uu_ 4       p\        P                  Vn        VP                  W4      P                  4       pRRR4       X Uu. uF  p\        V4      NK  	  up#   + '       g   i     L+; iu upi 5i)c                (    V ^8  d   QhR\         RR/# )rV   r  rW   Nrd   )rZ   s   "r0   r[   +api_reservations_list.<locals>.__annotate__  s     j js jt jrS   c                 v     \         P                  ! V R 4       R#   \         d    \        RRT  R2R7      hi ; i)r  ry   u   Fecha inválida: z. Usa formato YYYY-MM-DD.ru   N)r   r,  r   r	   )r  s   &r0   _check_date*api_reservations_list.<locals>._check_date  sA    	ja, 	jC:KA3Ng8hii	js    8Nry   u   Estado inválido. Usa uno de: r5  .ru   z	date >= ?z	date <= ?zuser_id = ?zLOWER(status) = ?zdocente_id = ?z WHERE z AND r}   a@  
        SELECT
            id,
            created_at,
            date,
            time,
            duration_minutes,
            price_cents,
            name,
            email,
            phone,
            notes,
            user_id,
            status,
            docente_id
        FROM reservations
        z1
        ORDER BY date ASC, time ASC, id ASC
    )r  r   r   ALLOWED_STATUSESr	   r   sortedrH  rF   rG   rH   rO   rP   r)   r*   r  )rj   r  r  rk   r  r   rE  status_normr  rU  clauser  r+   r  rn  s   &&&&&&         r0   api_reservations_listrL    s     'j IG W!4$7!%Klln**,..7		&IYBZ8[7\\]^  EF[!i [!g]#g()k"%&j!27i',,u--RF	  
 !C( 
	!	!T";;||C(113 
" 266A$Q'66	 
"	! 7s[   )H4H4H4H4A!H48)H4"AH42AH4AH45H9H4H/H4H,	'H4z/api/meapi_mec                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s      ' rS   c                 N   "   \        V 4      pV'       g   \        R R/4      # R# 5i)authenticatedFN)r   r   rY   r   r   s   & r0   rM  rM    s'     	g	B_e455 s   #%/perfilc                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s     X X' XrS   c                 ~   "   \        V 4      pV'       g   \        R RR7      # \        P                  RRV RV/4      # 5i)ro   rp   rq   zprofile.htmlrj   r   r`  r   s   & r0   perfilrT    s<     	g	BH#>>%%ny'6SU6VWWrb  /ajustesc                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s     _ _w _rS   c                   "   \        V 4      pV'       g   \        R RR7      # \        P                  ! \        4      ;_uu_ 4       p\        P
                  Vn        VP                  RVR,          34      P                  4       pRRR4       X'       d   \        V4      MTp\        P                  RRV RV/4      #   + '       g   i     L?; i5i)	ro   rp   rq   z
            SELECT
                id, name, email, phone, avatar, created_at,
                team, category, position, injury_history
            FROM users
            WHERE id=?
            rx   Nsettings.htmlrj   r   )r   r   rF   rG   rH   rO   rP   r)   r^   r   r   r   )rj   rf   r+   	user_fullr  s   &    r0   ajustes_getrZ    s     	g	BH#>> 
	!	!T";;LL XK	
 (* 	 
" #,tIH%%o	7FT\7]^^ 
"	!s$   AC>B:C'C:C
	Cc                    V ^8  d   QhR\         R\        R\        R\        R\        R\        R\        R\        R	\        /	# )
rV   rj   r   r   r!   r"   r#   r$   r%   r&   )r   re   r   )rZ   s   "r0   r[   r[   &  sm     H< H<H<
H< H< 	H<
 H< H< H< H< H<rS   c	                 2  "   \        V 4      p	V	'       g   \        R RR7      # T;'       g    RP                  4       pT;'       g    RP                  4       pT;'       g    RP                  4       ;'       g    RpT;'       g    RP                  4       ;'       g    RpT;'       g    RP                  4       ;'       g    RpT;'       g    RP                  4       ;'       g    RpT;'       g    RP                  4       ;'       g    Rp\        P                  ! \
        4      ;_uu_ 4       p
\        P                  V
n        V
P                  RV	R,          34      P                  4       pV'       d
   VR,          MRpRRR4       XpV'       Ed-   \        VRR4      '       Ed   \        P                  P                  VP                  4      ^,          P                  4       pVR9  d   \         P#                  R	R
V RV	RR/4      # \        P                  P%                  RRR4      p\        P&                  ! VRR7       \        P                  P%                  VRV	R,           V 24      p\)        VR4      ;_uu_ 4       pTP+                  VP-                  4       G Rj  xL
 4       RRR4       RV	R,           V 2p \        P                  ! \
        4      ;_uu_ 4       p
V
P                  RWW=WVWxV	R,          3	4       V
P/                  4        RRR4       \        RRR7      #   + '       g   i     EL; i L  + '       g   i     L; i  + '       g   i     LF; i  \        P0                   d     \         P#                  R	R
T RT	RR/4      u # i ; i5i)ro   rp   rq   r}   Nz%SELECT avatar FROM users WHERE id = ?rx   r"   r=  rX  rj   r   r   z:Formato de imagen no permitido. Usa PNG, JPG, JPEG o WebP.appr   r  Tr  user_r  z/static/uploads/user_z
                UPDATE users
                SET name=?, email=?, phone=?, avatar=?, team=?, category=?, position=?, injury_history=?
                WHERE id=?
                u*   El correo ya está en uso por otra cuenta.rQ  )z.pngr  z.jpegz.webp)r   r   r   rF   rG   rH   rO   rP   r)   r^   getattrr;  r?  r@  r=  r   r   r   r   rB  rE  rF  r>  rJ   r.  )rj   r   r   r!   r"   r#   r$   r%   r&   rf   r+   r.   current_avataravatar_pathrM  rN  rP  rQ  s   &&&&&&&&&         r0   ajustes_postrb  %  s     
g	BH#>> JJBD[[b!Ekkr  "**dEZZR ((DDR&&(00DHR&&(00DH%++224<<N 
	!	!T";;llBRXKPYY[*-X4 
" !Kv'&*d33ggv/288:88--o7U@  
 ggll5(I>
K$/GGLLbhZu.EF	)T""aGG&++-'( # .bhZu=__W%%LL
 e$(\^_c\de KKM && 	s;;[ 
"	!	!( ( #" &% !! ))/wBA<
  	s   )NNN N8NNN(N NN$N0N%N-AL$>NC.N?L:L8L:'N>"M   /MM  N$L5	/	N8L::M
	NM	M  NM   1NNNNz/notesc                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[   s  s     	 	 	rS   c                 ~   "   \        V 4      pV'       g   \        R RR7      # \        P                  RRV RV/4      # 5i)ro   rp   rq   z
notes.htmlrj   r   r`  ra  s   & r0   r  r  r  sC      DH#>>%%l75  rb  )r   TFc                0    V ^8  d   QhR\         R\         /# )rV   plainrW   rd   )rZ   s   "r0   r[   r[     s     I I I IrS   c                     T ;'       g    R p \         '       d   \        P                  ! V 4      # R\        P                  ! V P                  R4      4      P                  4       ,           # )r}   sha256$utf-8)_HAS_BCRYPTr   r   hashlibsha256encode	hexdigest)rf  s   &r0   hash_passwordro    sG    KKRE{{{5!!w~~ell7&;<FFHHHrS   c                <    V ^8  d   QhR\         R\         R\        /# )rV   rf  stored_hashrW   )re   ra   )rZ   s   "r0   r[   r[     s!      3 S T rS   c                     T ;'       g    R p T;'       g    R pVP                  R4      '       g/   VP                  R4      '       g   VP                  R4      '       d&   \        '       d    \        P                  ! W4      # R# VP                  R4      '       dc   VP                  R^4      ^,          p\        P                  ! V P                  R4      4      P                  4       p\        P                  ! W24      # R#   \         d     R# i ; i)r}   z$2a$z$2b$z$2y$Frh  ri  )
startswithrj  r   r   r   r  rk  rl  rm  rn  hmaccompare_digest)rf  rq  expecteddigests   &&  r0   verify_passwordrx    s    KKRE##Kf%%)?)?)G)G;KaKabhKiKi;}}U88 i(($$Y215W 56@@B""644  s   +C> >DDz/ajustes/passwordc                H    V ^8  d   QhR\         R\        R\        R\        /# )rV   rj   current_passwordnew_passwordconfirm_passwordr   )rZ   s   "r0   r[   r[     s0     -= -=-=-= -= 	-=rS   c           	        "   \        V 4      pV'       g   \        R RR7      # T;'       g    RP                  4       pT;'       g    RP                  4       pW#8w  d   \        P	                  RRV RVRR/4      # \        V4      ^8  d   \        P	                  RRV RVRR	/4      # \        V\        4      '       d   VP                  R
4      MVR
,          p\        W4      '       g   \        P	                  RRV RVRR/4      # \        V4      p\        P                  ! \        4      ;_uu_ 4       pVP                  RWdR,          34       VP                  4        RRR4       \        RRR7      #   + '       g   i     L; i5i)ro   rp   rq   r}   rX  rj   r   r   u   Las contraseñas no coinciden.u6   La nueva contraseña debe tener al menos 8 caracteres.r   u%   La contraseña actual no es correcta.z+UPDATE users SET password_hash=? WHERE id=?rx   NrU  )r   r   r   r   r   r  r<  r   r   rx  ro  rF   rG   rH   r)   rJ   )rj   rz  r{  r|  rf   rq  new_hashr+   s   &&&&    r0   ajustes_passwordr    sk     
g	BH#>> !&&B--/L(..B557'))/wB5<
  	 <1))/wBM<
  	 .8D-A-A"&&)r/GZK+99))/wB<<
  	 \*H		!	!TBXRVxDXY 
" 
<< 
"	!s)   )FFC)F/+E/F/E?	:Fz/logoutc                $    V ^8  d   QhR\         /# r   r   )rZ   s   "r0   r[   r[     s     6 6' 6rS   c                 X   "   V P                   P                  4        \        R RR7      # 5i)r   rp   rq   )r   clearr   r   s   &r0   logoutr    s"     OO55s   (*z/api/healthc                     "   R R/# 5i)r  r6  r  r  rS   r0   healthr    s     ds   startupc                      \         P                  ! \        4      ;_uu_ 4       p V P                  R 4       V P	                  4        RRR4       \        4        \        4        R#   + '       g   i     L&; i  \
         d     L6i ; i)z
                UPDATE reservations
                SET name = (SELECT name FROM users WHERE users.id = reservations.user_id)
                WHERE (name IS NULL OR name='') AND user_id IS NOT NULL
            N)rF   rG   rH   r)   rJ   r   rM   r   rQ   s    r0   
on_startupr    sb    	__W%%LL  
 KKM & I &%  s.   "A7 "A$A7 $A4	/A7 4A7 7BB)r	  )   r   >   rc   r	  r   )r  r  Z   >   	cancelada	pendienter  )NNNNN)fastapir   r   r   r   r   r   r	   fastapi.responsesr
   r   r   fastapi.staticfilesr   fastapi.templatingr   starlette.middleware.sessionsr   passlib.contextr   pydanticr   rF   pathlibr   r;  r9  r]  Path__file__resolveparentrA  rH   add_middlewarer   mountr   rM   rR   r_   rg   postrh   r   r   r   r:  r   r   r   urllibr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  UPLOADS_DIRr  rZ  r   rc   rh  ri  r|   r}  r  r  r  r  typingr  r  r  r  r  r  r  r  r  re   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r4  patchr;  deleter?  rH  rL  rM  rT  rZ  rb  r  rk  rt  passlib.hashr   rj  r   ro  rx  r  r  r  on_eventr  r  rS   r0   <module>r     sB   Q Q Q J J + . ; (  % % 	K <<!))+22
\
!   $  8H:&A 		)[<8x	 Ho6	
HV"
&
 
&9: 9:.; ;.;b + * 

( "* 
$+@A  9:&*4jFD BFDZ \*V +V ,/V 0V l3 4 l3m 4m =Y >Y (lC48ItTWy S DS. )LA B0 	CTU V0 :lCn Dn
 +OLI6:3idSViimnqir S JS: " *	#9,W X !I-	9 
$;<p< =p<f 	,7 8 KEZ FZ ,/X 0X 		M 	M R Q Q J J 	!1,OR PRn "
"78 S	cS	:!%d=D 9=DF NK L / 
 lE. F.d 
%,@A%O B%OT 2 1  * 8 8   C*3IJJ
K
C*3CDD
E%I %%	 %&  , , %  	#$$7 !3#!M %Mt )J
	 " $& 
d3j) 4j)\ '=G >GV (>	. ?	. "  !; 	T$Z8Q7 9Q7r <h? @( <0X 1X L1_ 2_2 *\2 S	cddT
JJt*H< 3H<X ,/	 0	  #KI( 
l; !IS	 I	-= <-=f 6 6   i I  Ks   $]< <	^^