+
    7<i                    x   ^ 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Ht ^ R
I Ht ^ RIHtHt ^ RIHtHtH t H!t! ^ RIHt ^ RIHtH"t"H#t# ^ RIt$^ R
I Ht ^ RIHtH%t% ^ RI Ht ^ RI&t&^ RI't'^ RIH%t% ^ RI(t(^ RI)t)^ RI*t*^ RI+t+^ RI(t,^ RI-t-^ RI.t/^ RIt0^ RI.H1t1 ]! RR7      t2]Pf                  ! ]44      Pk                  4       Pl                  t7]7R,          t8]Pr                  ! RR4      Pu                  4       ER&9   t;]Pr                  ! R4      ;'       g    ](Px                  ! ^@4      t=]2P}                  ]]=RRER'RR7       ]! R.RR7      t?R  R! lt@]2P                  R"]! R#R$7      R%R&7       ]! R'R$7      tBR( R) ltC]2P                  R*]	R+7      R, R- l4       tE0 ER(mtFR. R/ ltGR0 R1 ltHR2 R3 ltIR4 tJR5 tKR6 tLR7 tMR8 R9 ltNR: R; ltOR< R= ltP]2P                  R>R?R&7      ]! R@4      ]! R4      3RA RB ll4       tRRC RD ltSRE RF ltTER)RG RH lltU]2P                  RI]R+7      RJ RK l4       tV]2P                  RL]R+7      RM RN l4       tW]2P                  RO]R+7      RP RQ l4       tX]2P                  RR]YRS7      RT RU l4       tZ]2P                  RV4      ]! ^^RWRX7      ]! ^
^^dRYRZ7      ]! R4      ]! R4      ]! R4      3R[ R\ ll4       t[R] t\ER*R^ R_ llt]R` Ra lt^Rb t_Rc Rd lt`Re Rf ltaRg Rh ltb]2P                  RiRjR&7      ]! R@4      ]! R4      ]! R4      ]! R4      3Rk Rl ll4       tc]2P                  Rm]	R+7      Rn Ro l4       td]2P                  Rp]	R+7      Rq Rr l4       te]2P                  Rs]	R+7      Rt Ru l4       tf]2P                  RvRw]	Rx7      Ry Rz l4       tg]2P                  RvR{]	Rx7      ]! R@4      ]! R@4      3R| R} ll4       th]2P                  R~R]	Rx7      R R l4       ti]2P                  RR]	Rx7      R R l4       tj]2P                  R]RR7      R R l4       tk]2P                  RR]	Rx7      R R l4       tl]2P                  RR]	Rx7      ]! R@4      ]! R@4      ]! R@4      3R R ll4       tm]2P                  RR]	Rx7      R R l4       tn]7R%,          R,          R,          to]2P                  RRR&7      R R l4       tp]2P                  R]	R+7      R R l4       tq]2P                  R]	RR7      R R l4       tr]2P                  RR]	Rx7      R R l4       ts]2P                  R]	R+7      R R l4       tt]2P                  RR]	Rx7      ER+R R ll4       tu^ RIH%t% ]2P                  R]%]Y,          RS7      ER,R R ll4       tv ! R R]4      tw]2P                  R]YRS7      R R l4       tx]2P                  R]YRS7      R R l4       tz]2P                  RRR&7      ]! R@4      ]! R@4      ]! R@4      ]! R4      ]! R4      ]! R4      3R R ll4       t{]2P                  R]RR7      R R l4       t|0 ER-mt}0 ER.mt~ ! R R]4      t ! R R]4      tR R lt0 ER.mt~ ! R R]4      t]2P                  RRR&7      R R l4       t]2P                  R]RR7      ]! R4      ]! R4      3R R ll4       t]2P                  RRR&7      R R l4       t]!]]#! RR7      3,          t]!]]#! RR7      3,          t ! R R]4      t ! R R]4      t ! R R]4      tR t]2EP                  RO]YRS7      R R l4       t]2P                  R]YRS7      R R l4       t0 ER/mt]2P                  R]YRS7      R R l4       t]2P                  R]%]Y,          RS7      ER0R R ll4       t]2P                  R]	R+7      R R l4       t]2P                  R]	R+7      R R l4       t]2P                  R]	R+7      ]! R@4      ]! R@4      ]! R4      ]! R4      ]! R4      ]! R4      ]! R4      ]! R4      ]! R@4      3	R R ll4       t]2P                  R]	R+7      R R l4       t ^ RIHt RtR R ltR R lt]2P                  R]	R+7      ]! R@4      ]! R@4      ]! R@4      ]! R@4      3R R ll4       t ! R R]4      t]2EP                  R]YRS7      ]! R@4      3R R ll4       t^ RI H3t3 0 ER-mt]2EP                  R]YRS7      ]3! R@4      ]! R@4      3R ER  ll4       t]2P                  ER]ERR7      ER ER l4       t]2P                  ER]ERR7      ]! R4      3ER ER ll4       t]2P                  ER4      ER	 ER
 l4       t]2P                  ER4      ER 4       t^ ERIHtH"t" ^ ERIH%t%Ht ^ RI(t( ! ER ER]4      t ! ER ER]4      t]2P                  ER]]Y,          RS7      ]! R@4      3ER ER ll4       t]2P                  R]YRS7      ER ER l4       t^ ERI HtHt ^ ERI HtHt ^ RItER ER ltER ER lt]2P                  ER]YRS7      ER ER l4       t^ RIHt ^ ERIHtHt ]2EPe                  ]4      ER  ER! l4       tER" ER# lt]2EPk                  ER$4      ER% 4       tR#   ] d    Rt ELOi ; i(1      )FastAPIRequestForm
UploadFileFileBodyHTTPException)HTMLResponseRedirectResponseJSONResponse)StaticFiles)Jinja2Templates)SessionMiddleware)CryptContext)	BaseModelN)Optional)Query)datetime	timedelta)r   DictAny	Annotated)r   )r   FieldStringConstraints)r   List)r	   )r   )urlparse	TheL4FPRO)titlez
db.sqlite3APP_ENVdevAPP_SECRET_KEYlaxTthelfpro_session)
secret_key	same_site
https_onlymax_agesession_cookiebcryptauto)schemes
deprecatedc                (    V ^8  d   QhR\         RR/# )   requestreturnNr   )formats   "(C:\Users\mario\Desktop\furbo\app\main.py__annotate__r4   0   s     5 5G 5 5    c                    V P                   P                  4        \        P                  ! ^ 4      V P                   R&   \        P                  ! ^ 4      V P                   R&   \	        \
        P
                  ! 4       4      V P                   R&   R# )    sidcsrf
created_atN)sessionclearsecretstoken_urlsafeinttimer/   s   &r3   rotate_sessionrB   0   s]    OO$2226GOOE%33B7GOOF$'		$4GOOL!r5   z/staticz
app/static)	directorystatic)namezapp/templatesc                >    V ^8  d   QhR\         R\        R,          /# )r.   r/   tokenNr   str)r2   s   "r3   r4   r4   9   s"     L L' L#* Lr5   c                     V P                   P                  R 4      pV'       dB   V'       d:   \        P                  ! \	        V4      \	        T;'       g    R4      4      '       g   \        RRR7      hR# )r9      u   CSRF token inválidostatus_codedetailN)r;   gethmaccompare_digestrI   r	   )r/   rG   sesss   && r3   require_csrfrT   9   sQ    ??v&DuD$7$7D	3u{{PRCS$T$T4JKK %Ur5   z/contabilidad)response_classc                $    V ^8  d   QhR\         /# r.   r/   r1   )r2   s   "r3   r4   r4   @   s     _ _ _r5   c                 j   "   \        V 4       \        V 4      p\        P                  R RV RV/4      # 5i)zcontabilidad.htmlr/   user)require_admincurrent_user	templatesTemplateResponser/   rY   s   & r3   contabilidadr_   ?   s6     ' D%%&9IwPVX\;]^^s   13c                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   H   s     % %W %r5   c                     V P                   \        9   d)   V P                  P                  R 4      p\	        W4       R# R# )X-CSRF-TokenN)methodUNSAFE_METHODSheadersrP   rT   r/   rG   s   & r3   _enforce_csrf_if_unsaferg   H   s/    ~~'##N3W$ (r5   c                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   M   s      7 r5   c                 N   \        V 4      pV'       g   \        R RR7      h\        V 4       \        V\        P
                  4      '       d
   VR,          M\        VP                  RR4      4      ;'       g    Rp\        V4      P                  4       R8w  d   \        RRR7      hV# )  No autenticadorM   rolerK   adminrL   zSolo administradores	r[   r	   rg   
isinstancesqlite3RowrI   rP   lowerr/   merl   s   &  r3   rZ   rZ   M   s    	g	B4DEEG$$R55BvJ3rvvfb?Q;RYYWYD
4yG#4JKKIr5   c                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   W   s      g r5   c                 N   \        V 4      pV'       g   \        R RR7      h\        V 4       \        V\        P
                  4      '       d
   VR,          M\        VP                  RR4      4      ;'       g    Rp\        V4      P                  4       R9  d   \        RRR7      hV# )rj   rk   rM   rl   rK   rL   Solo docentes o admindocenterm   rn   rs   s   &  r3   require_docente_or_adminrz   W   s    	g	B4DEEG$$R55BvJ3rvvfb?Q;RYYWYD
4y 444KLLIr5   c                  ~   \         P                  ! \        R RR7      p \         P                  V n        V P                  R4       V P                  R4       V P                  R4       V P                  R4       V P                  R4       V P                  R4        V P                  R	4       V #   \         d     T # i ; i)
NF)isolation_levelcheck_same_threadzPRAGMA foreign_keys = ON;zPRAGMA journal_mode = WAL;zPRAGMA synchronous = NORMAL;zPRAGMA busy_timeout = 5000;zPRAGMA cache_size = -20000;zPRAGMA temp_store = MEMORY;zPRAGMA mmap_size = 268435456;)rp   connectDB_PATHrq   row_factoryexecute	Exceptionconns    r3   get_connr   a   s    ??7DERD{{DLL,-LL-.LL/0LL./LL./LL./45 K  Ks   B- -B<;B<c                      \        4       # N)r    r5   r3   _connr   p   s
    :r5   c                      V P                  R V R24      P                  4        Uu0 uF  q"^,          kK  	  up# u upi   \         d    \        4       u # i ; i)zPRAGMA table_info())r   fetchallr   set)r   tablers   && r3   _table_columnsr   s   sW    "ll-?wa+HIRRTUT!TUUU us   %A  ;A  A   AAc                  v   \        4       ;_uu_ 4       p V P                  4       pVP                  R 4       VP                  R4       VP                  R4      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       VP                  R	4       VP                  R
4       VP                  R4       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                  4        Uu0 uF  q"^,          kK  	  ppRV9  d#   VP                  R4       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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"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       VP                  R*4       VP                  R+4       VP                  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                  R34       VP                  R44       VP                  R54       VP                  R64       VP                  R74       VP                  R84       VP                  R94       VP                  R:4       VP                  R;4       VP                  R<4       VP                  R=4       V P	                  4        R>R>R>4       R># u upi u upi   + '       g   i     R># ; i)?zPRAGMA foreign_keys=ONa  
        CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            email TEXT NOT NULL UNIQUE,
            name TEXT NOT NULL,
            first_name TEXT,
            last_name TEXT,
            phone TEXT,
            password_hash TEXT NOT NULL,
            role TEXT NOT NULL DEFAULT 'alumno',
            created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S','now','localtime'))
        )
        zPRAGMA table_info(users)
first_namez,ALTER TABLE users ADD COLUMN first_name TEXT	last_namez+ALTER TABLE users ADD COLUMN last_name TEXTphonez'ALTER TABLE users ADD COLUMN phone TEXTa1  
        CREATE TABLE IF NOT EXISTS user_profile (
            user_id INTEGER PRIMARY KEY,
            phone TEXT,
            avatar TEXT,
            city TEXT,
            dni TEXT,
            birth_date TEXT,
            FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
        )
        a  
        CREATE TABLE IF NOT EXISTS user_sports (
            user_id INTEGER PRIMARY KEY,
            team TEXT,
            category TEXT,
            position TEXT,
            dominant_foot TEXT,
            strengths TEXT,
            weaknesses TEXT,
            injury_history TEXT,
            training_type TEXT,
            FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
        )
        a  
        CREATE TABLE IF NOT EXISTS user_health (
            user_id INTEGER PRIMARY KEY,
            physical_work INTEGER,
            physical_work_details TEXT,
            smoking INTEGER,
            alcohol INTEGER,
            recovery TEXT,
            chest_pain INTEGER,
            discomfort INTEGER,
            FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
        )
        ap  
        CREATE TABLE IF NOT EXISTS user_consent (
            user_id INTEGER PRIMARY KEY,
            whatsapp_content INTEGER,
            video_permission INTEGER,
            privacy_acceptance INTEGER,
            data_confirmation INTEGER,
            agreement INTEGER,
            FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
        )
        a0  
        CREATE TABLE IF NOT EXISTS user_guardians (
            user_id INTEGER PRIMARY KEY,
            occupation TEXT,
            study_place TEXT,
            parent_name TEXT,
            parent_email TEXT,
            FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
        )
        a9  
        CREATE TABLE IF NOT EXISTS user_marketing (
            user_id INTEGER PRIMARY KEY,
            found_us TEXT,
            enjoyment TEXT,
            nerves_confidence TEXT,
            additional_comments TEXT,
            FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
        )
        z
        CREATE TABLE IF NOT EXISTS user_finance (
            user_id INTEGER PRIMARY KEY,
            matricula_eur REAL NOT NULL DEFAULT 0,
            FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
        )
        a  
        CREATE TABLE IF NOT EXISTS reservations (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S','now','localtime')),
            date TEXT NOT NULL,
            time TEXT,
            duration_minutes INTEGER,
            price_cents INTEGER NOT NULL DEFAULT 0,
            name TEXT,
            email TEXT,
            phone TEXT,
            notes TEXT,
            user_id INTEGER,
            status TEXT NOT NULL DEFAULT 'confirmada',
            docente_id INTEGER NOT NULL,
            paid INTEGER NOT NULL DEFAULT 0,
            FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE SET NULL,
            FOREIGN KEY(docente_id) REFERENCES users(id) ON DELETE CASCADE
        )
        zPRAGMA table_info(reservations)r:   z3ALTER TABLE reservations ADD COLUMN created_at TEXTzmUPDATE reservations SET created_at = strftime('%Y-%m-%dT%H:%M:%S','now','localtime') WHERE created_at IS NULLr@   z-ALTER TABLE reservations ADD COLUMN time TEXTduration_minutesz<ALTER TABLE reservations ADD COLUMN duration_minutes INTEGERprice_centszJALTER TABLE reservations ADD COLUMN price_cents INTEGER NOT NULL DEFAULT 0rE   z-ALTER TABLE reservations ADD COLUMN name TEXTemailz.ALTER TABLE reservations ADD COLUMN email TEXTz.ALTER TABLE reservations ADD COLUMN phone TEXTnotesz.ALTER TABLE reservations ADD COLUMN notes TEXTuser_idz3ALTER TABLE reservations ADD COLUMN user_id INTEGERstatuszMALTER TABLE reservations ADD COLUMN status TEXT NOT NULL DEFAULT 'confirmada'
docente_idzIALTER TABLE reservations ADD COLUMN docente_id INTEGER NOT NULL DEFAULT 1paidzCALTER TABLE reservations ADD COLUMN paid INTEGER NOT NULL DEFAULT 0ar  
        CREATE TABLE IF NOT EXISTS reservation_students (
            reservation_id INTEGER NOT NULL,
            user_id INTEGER NOT NULL,
            PRIMARY KEY (reservation_id, user_id),
            FOREIGN KEY(reservation_id) REFERENCES reservations(id) ON DELETE CASCADE,
            FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE
        )
        aS  
        CREATE TABLE IF NOT EXISTS jugadores_gastos (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S','now','localtime')),
            date TEXT NOT NULL,
            user_id INTEGER,
            reservation_id INTEGER,
            amount_cents INTEGER NOT NULL,
            category TEXT,
            concept TEXT,
            notes TEXT,
            FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
            FOREIGN KEY(reservation_id) REFERENCES reservations(id) ON DELETE CASCADE
        )
        z@CREATE INDEX IF NOT EXISTS idx_jg_date ON jugadores_gastos(date)zCCREATE INDEX IF NOT EXISTS idx_jg_user ON jugadores_gastos(user_id)zQCREATE INDEX IF NOT EXISTS idx_jg_reservation ON jugadores_gastos(reservation_id)a  
        CREATE TABLE IF NOT EXISTS notifications (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S','now','localtime')),
            title TEXT,
            body TEXT,
            sender_id INTEGER,
            recipient_id INTEGER NOT NULL,
            reservation_id INTEGER,
            is_read INTEGER NOT NULL DEFAULT 0,
            deleted_by_sender INTEGER NOT NULL DEFAULT 0,
            deleted_by_recipient INTEGER NOT NULL DEFAULT 0,
            FOREIGN KEY(sender_id) REFERENCES users(id) ON DELETE SET NULL,
            FOREIGN KEY(recipient_id) REFERENCES users(id) ON DELETE CASCADE,
            FOREIGN KEY(reservation_id) REFERENCES reservations(id) ON DELETE CASCADE
        )
        zPCREATE INDEX IF NOT EXISTS idx_notif_rec ON notifications(recipient_id, is_read)zECREATE INDEX IF NOT EXISTS idx_notif_send ON notifications(sender_id)zICREATE INDEX IF NOT EXISTS idx_notif_created ON notifications(created_at)a  
        CREATE TABLE IF NOT EXISTS player_ratings (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            player_id INTEGER NOT NULL,
            docente_id INTEGER NOT NULL,
            rating INTEGER NOT NULL,
            notes TEXT,
            created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S','now','localtime')),
            FOREIGN KEY(player_id) REFERENCES users(id) ON DELETE CASCADE,
            FOREIGN KEY(docente_id) REFERENCES users(id) ON DELETE CASCADE
        )
        a  
        CREATE TABLE IF NOT EXISTS valoraciones_jugador (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            eval_id TEXT NOT NULL,
            player_id INTEGER NOT NULL,
            docente_id INTEGER NOT NULL,
            area TEXT NOT NULL,
            subescala TEXT NOT NULL,
            indicador TEXT NOT NULL,
            score INTEGER NOT NULL,
            observaciones TEXT,
            created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S','now','localtime')),
            FOREIGN KEY(player_id) REFERENCES users(id) ON DELETE CASCADE,
            FOREIGN KEY(docente_id) REFERENCES users(id) ON DELETE CASCADE
        )
        a  
        CREATE TABLE IF NOT EXISTS "formulario-registro" (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            pin TEXT NOT NULL UNIQUE,
            email TEXT,
            name TEXT,
            used INTEGER NOT NULL DEFAULT 0,
            expires_at TEXT NOT NULL,
            created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S','now','localtime'))
        )
        zZCREATE INDEX IF NOT EXISTS idx_formreg_used_exp ON "formulario-registro"(used, expires_at)zAINSERT OR IGNORE INTO user_profile(user_id)  SELECT id FROM userszAINSERT OR IGNORE INTO user_sports(user_id)   SELECT id FROM userszAINSERT OR IGNORE INTO user_health(user_id)   SELECT id FROM userszAINSERT OR IGNORE INTO user_consent(user_id)  SELECT id FROM userszAINSERT OR IGNORE INTO user_guardians(user_id)SELECT id FROM userszAINSERT OR IGNORE INTO user_marketing(user_id)SELECT id FROM userszTINSERT OR IGNORE INTO user_finance(user_id, matricula_eur) SELECT id, 0.0 FROM usersN)r   cursorr   r   commit)r   cr   
cols_userscols_ress        r3   init_dbr   y   s   	DKKM			*+			  	 %&II.H$I$R$R$TU$Tqdd$T
Uz)IIDEj(IICD*$II?@			 
 
	 	
		  	 	
		  	 	
		 
 
	 	
		 	 		 	
		 	 		 	
		  	 	
		  	( #$)),M"N"W"W"YZ"YQaDD"YZx'IIKLII  F  G!IIEFX-IITU(IIbc!IIEF("IIFG("IIFG("IIFGH$IIKL8#IIefx'IIab!II[\			  	 	
		  	 	
		TU			WX			ef			  	" 	
		de			YZ			]^			  	 	
		  	" 	
		 
 
	 	
		no			UV			UV			UV			UV			UV			UV			hiA 
" V^ [A 
s,   AP''P8C3P'+P"<JP'
P''P8	c                $    V ^8  d   QhR\         /# r.   r0   r?   )r2   s   "r3   r4   r4   ~  s     " "c "r5   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'r   N)r   r   fetchoner?   )r   rows     r3   count_adminsr   ~  sA    	DllOPYY[3s8==q! 
s   ;AA*	c                $    V ^8  d   QhR\         /# r   )bool)r2   s   "r3   r4   r4     s     & &D &r5   c                 ,    \        V R ,          4      R8H  # )rl   rm   rI   )rt   s   &r3   is_adminr     s    r&z?g%%r5   c                $    V ^8  d   QhR\         /# r.   r   r   )r2   s   "r3   r4   r4     s     k kC kr5   c                    V P                  R V34       V P                  RV34       V P                  RV34       V P                  RV34       V P                  RV34       V P                  RV34       V P                  RV34       R# )6INSERT OR IGNORE INTO user_profile(user_id) VALUES (?)5INSERT OR IGNORE INTO user_sports(user_id) VALUES (?)z5INSERT OR IGNORE INTO user_health(user_id) VALUES (?)z6INSERT OR IGNORE INTO user_consent(user_id) VALUES (?)z8INSERT OR IGNORE INTO user_guardians(user_id) VALUES (?)z8INSERT OR IGNORE INTO user_marketing(user_id) VALUES (?)JINSERT OR IGNORE INTO user_finance(user_id, matricula_eur) VALUES (?, 0.0)N)r   )r   r   s   &&r3   _upsert_satellites_emptyr     s{    LLIG:VLLH7*ULLH7*ULLIG:VLLKgZXLLKgZXLL]`g_ijr5   z/admin/users/deleteadmin_delete_user.c                J    V ^8  d   QhR\         R\        R\        R,          /# )r.   r/   r   next_urlNr   r?   rI   )r2   s   "r3   r4   r4     s*     ; ;;; Dj;r5   c                 F  "   \        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\        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;   \        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/  urlrN   rL   z&Solo un admin puede eliminar usuarios.rM     Usuario no encontrado.id  z$No puedes eliminar tu propia cuenta.BEGINADELETE FROM notifications WHERE sender_id = ? OR recipient_id = ?2DELETE FROM reservation_students WHERE user_id = ?z*DELETE FROM reservations WHERE user_id = ?DELETE FROM users WHERE id = ?NrK   /admin)r[   r   r   r	   get_user_by_idr?   r   r   r   r   rollbackr   schemenetloc)r/   r   r   rt   targetr   ps   &&&    r3   r   r     sJ     
g	BH#>>B<<4\]]G$F4LMM
2d8}F4L))4Z[[	D	<< <<[^e]op<<LwjY<<DwjQ<<87*E;;= 
 X88r>ahh"n#cBBc::  ==? 
s8   B%F!'F)A-E.F!'AF!.FFF	F!c                $    V ^8  d   QhR\         /# )r.   r   r   )r2   s   "r3   r4   r4     s      S r5   c                     \        4       ;_uu_ 4       pVP                  R V 34      pVP                  4       uuRRR4       #   + '       g   i     R# ; i)a"  
            SELECT u.id,u.name,u.email,u.password_hash,u.created_at,u.role,u.first_name,u.last_name,
                   p.phone,p.avatar,p.city,p.dni,p.birth_date,
                   s.team,s.category,s.position,s.dominant_foot,s.strengths,s.weaknesses,s.injury_history,s.training_type,
                   h.physical_work,h.physical_work_details,h.smoking,h.alcohol,h.recovery,h.chest_pain,h.discomfort,
                   c.whatsapp_content,c.video_permission,c.privacy_acceptance,c.data_confirmation,c.agreement,
                   g.occupation,g.study_place,g.parent_name,g.parent_email,
                   m.found_us,m.enjoyment,m.nerves_confidence,m.additional_comments,
                   COALESCE(f.matricula_eur,0.0) AS matricula_eur,
                   CAST(ROUND(COALESCE(f.matricula_eur,0.0)*100) AS INTEGER) AS matricula_cents
            FROM users u
            LEFT JOIN user_profile p   ON p.user_id=u.id
            LEFT JOIN user_sports s    ON s.user_id=u.id
            LEFT JOIN user_health h    ON h.user_id=u.id
            LEFT JOIN user_consent c   ON c.user_id=u.id
            LEFT JOIN user_guardians g ON g.user_id=u.id
            LEFT JOIN user_marketing m ON m.user_id=u.id
            LEFT JOIN user_finance f   ON f.user_id=u.id
            WHERE LOWER(u.email)=LOWER(?)
        Nr   r   r   )r   r   curs   &  r3   get_user_by_emailr     s<    	Dll & X'( ||~+ 
   #AA	c                $    V ^8  d   QhR\         /# r   r   )r2   s   "r3   r4   r4     s      C r5   c                     \        4       ;_uu_ 4       pVP                  R V 34      pVP                  4       uuRRR4       #   + '       g   i     R# ; i)a  
            SELECT u.id,u.name,u.email,u.password_hash,u.created_at,u.role,u.first_name,u.last_name,
                   p.phone,p.avatar,p.city,p.dni,p.birth_date,
                   s.team,s.category,s.position,s.dominant_foot,s.strengths,s.weaknesses,s.injury_history,s.training_type,
                   h.physical_work,h.physical_work_details,h.smoking,h.alcohol,h.recovery,h.chest_pain,h.discomfort,
                   c.whatsapp_content,c.video_permission,c.privacy_acceptance,c.data_confirmation,c.agreement,
                   g.occupation,g.study_place,g.parent_name,g.parent_email,
                   m.found_us,m.enjoyment,m.nerves_confidence,m.additional_comments,
                   COALESCE(f.matricula_eur,0.0) AS matricula_eur,
                   CAST(ROUND(COALESCE(f.matricula_eur,0.0)*100) AS INTEGER) AS matricula_cents
            FROM users u
            LEFT JOIN user_profile p   ON p.user_id=u.id
            LEFT JOIN user_sports s    ON s.user_id=u.id
            LEFT JOIN user_health h    ON h.user_id=u.id
            LEFT JOIN user_consent c   ON c.user_id=u.id
            LEFT JOIN user_guardians g ON g.user_id=u.id
            LEFT JOIN user_marketing m ON m.user_id=u.id
            LEFT JOIN user_finance f   ON f.user_id=u.id
            WHERE u.id=?
        Nr   r   r   r   s   &  r3   r   r     s<    	Dll & Z'( ||~+ 
r   c                |    V ^8  d   QhR\         R\         R\         R\         R\         R,          R\         R,          /# )r.   rE   r   passwordrl   r   Nr   r   )r2   s   "r3   r4   r4     s@      c #  C $J:=*r5   c                    \         P                  V4      p\        4       ;_uu_ 4       p\        VR 4      p\        P
                  P                  4       P                  4       p	RV9   d   RV9   d   VP                  RWWiW4V34      p
MVP                  RWWiV34      p
V
P                  p\        W{4       VP                  4        RRR4       R#   + '       g   i     R# ; i)usersr   r   znINSERT INTO users (name, email, password_hash, created_at, role, first_name, last_name) VALUES (?,?,?,?,?,?,?)zSINSERT INTO users (name, email, password_hash, created_at, role) VALUES (?,?,?,?,?)N)pwd_contexthashr   r   dtr   utcnow	isoformatr   	lastrowidr   r   )rE   r   r   rl   r   r   password_hashr   colsr:   r   uids   &&&&&&      r3   create_userr     s    $$X.M	DdG,[['')335
4K4$7,,)m9UC ,,em>C mm +! 
s   BCC	z/api/notifications/unreadc                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4     s     & &G &r5   c                    "   \        V 4      pV'       g   \        R RR7      h\        \        VR,          4      4      pR pV Uu. uF
  qC! V4      NK  	  up# u upi 5i)rj   rk   rM   r   c                 X    V P                  4        Uu/ uF  qW,          bK  	  up# u upi r   )keysr   ks   & r3   to_dict)api_notifications_unread.<locals>.to_dict  s#    QVVX6XqtGX666s   ')r[   r	   !get_unread_notifications_for_userr?   )r/   rt   rowsr   r   s   &    r3   api_notifications_unreadr     sQ     	g	B4DEE,SD];D6 $%1GAJ%%%s   AAAAz./api/notifications/{notification_id}/mark-readc                0    V ^8  d   QhR\         R\        /# )r.   r/   notification_idr   r?   )r2   s   "r3   r4   r4     s      w  r5   c           
      h  "   \        V 4      pV'       g   \        R RR7      hV P                  P                  R4      p\	        W4       \        4       ;_uu_ 4       pVP                  RV\        VR,          4      34       VP                  4        RRR4       RR/#   + '       g   i     RR/# ; i5i)	rj   rk   rM   rb   zx
            UPDATE notifications
            SET is_read = 1
            WHERE id = ? AND recipient_id = ?
            r   NokT)	r[   r	   re   rP   rT   r   r   r?   r   )r/   r   rt   rG   r   s   &&   r3   api_notifications_mark_readr      s     	g	B4DEEOO/E 	D
 c"T(m,	
 	 
 $< 
 $<s   AB25BB2B/	'B2z/api/reservations/{res_id}c                0    V ^8  d   QhR\         R\        /# r.   r/   res_idr   )r2   s   "r3   r4   r4     s     !& !&w !& !&r5   c                 @  "   \        V 4      pV'       g   \        R RR7      h\        4       ;_uu_ 4       pVP                  RV34      P	                  4       pRRR4       X'       g   \        RRR7      h\        V4      p\        VR7      #   + '       g   i     L<; i5i)rj   rk   rM   a  
            SELECT
                id,
                created_at,
                date,
                time,
                duration_minutes,
                price_cents,
                name,
                email,
                phone,
                notes,
                user_id,
                status,
                docente_id,
                paid
            FROM reservations
            WHERE id = ?
            Nr   zNo encontrada)content)r[   r	   r   r   r   _reservation_row_to_dictr   )r/   r   rt   r   r   datas   &&    r3   api_reservation_getr     s     	g	B4DEE	Dll& I)
* (*+ 	 
0 ODD#C(D%%9 
s"   3B"BB'$BB	Bz#/api/reservations/{res_id}/students)response_modelc                0    V ^8  d   QhR\         R\        /# r   r   )r2   s   "r3   r4   r4   :  s     T TG TS Tr5   c           
        "   \        V 4      pV'       g   \        R RR7      h\        4       ;_uu_ 4       p\        P                  Vn        VP                  RV34      P                  4       pV'       gl   VP                  RV34      P                  4       pV'       dC   VR,          '       d4   VP                  RVR,          34      P                  4       pV'       d   V.pRRR4       X Uu. uF)  pR\        VR,          4      R	VR	,          R
VR
,          /NK+  	  ppRVR\        V4      RV/#   + '       g   i     LV; iu upi 5i)rj   rk   rM   z
            SELECT u.id, u.name, u.email
            FROM reservation_students rs
            JOIN users u ON u.id = rs.user_id
            WHERE rs.reservation_id = ?
            ORDER BY COALESCE(u.name, u.email)
        z-SELECT user_id FROM reservations WHERE id = ?r   .SELECT id, name, email FROM users WHERE id = ?Nr   rE   r   reservation_idcountstudents)r[   r	   r   rp   rq   r   r   r   r   r?   len)r/   r   rt   r   r   r   ur  s   &&      r3   api_reservation_studentsr  9  s    	g	B4DEE	D";;||  Y !
 	 LviXaacAQy\\LL!QTUV_T`Sbclln3D 
 W[[VZQRs1T7|VQvY7LVZH[fgs8}j(SS! 
 \s;   3EA'D-D-,/D-D-E+/E E-D=	8Ez /api/reservations/list/paginatedu   P�gina (1-based))gedescriptionu   Tama�o de p�gina)r  ler	  c                    V ^8  d   QhR\         R\         R\        \         ,          R\        \         ,          R\        \        ,          /# )r.   pagesizer   r   r   r?   r   rI   )r2   s   "r3   r4   r4   Q  sT     @W @W
@W
@W c]@W 	@W
 SM@Wr5   c                     V ^,
          V,          pR.p. pVe#   VP                  R4       VP                  V4       Ve#   VP                  R4       VP                  V4       Ve#   VP                  R4       VP                  V4       RRP                  V4      ,           p\        4       ;_uu_ 4       p	V	P                  RV 2\	        V4      4      P                  4       p
\        V
R	,          ;'       g    ^ 4      pV	P                  R
V R2\	        V4      W3,           4      P                  4       pRRR4       X Uu. uF  p\        V4      NK  	  ppX'       d'   \        ^\        P                  ! W,          4      4      M^pRVRRV RVRVRV//#   + '       g   i     Lh; iu upi   \         d    h \         d    \        RRR7      hi ; i)   z1=1Nuser_id = ?docente_id = ?z
status = ?zWHERE  AND z'SELECT COUNT(*) AS c FROM reservations r   a  
                SELECT
                    id,
                    created_at,
                    date,
                    time,
                    duration_minutes,
                    price_cents,
                    name,
                    email,
                    phone,
                    notes,
                    user_id,
                    status,
                    docente_id
                FROM reservations
                zn
                ORDER BY datetime(created_at) DESC, id DESC
                LIMIT ? OFFSET ?
                itemsmetar  r  totalpagesi  zError interno listando reservasrM   )appendjoinr   r   tupler   r?   r   r   maxmathceilr	   r   )r  r  r   r   r   offsetwhere_clausesparams	where_sqlr   	total_rowr  r   r   r  r  s   &&&&&           r3   reservations_paginatedr#  P  s   9W(d"  /MM'"!  !12MM*%  .MM&!w||M::	WW9)Ef hj  	#++!,E<<   !( f.+, hj-  : 7;;d)!,d;38Atyy./aU	
 	
? W: <   W4UVVWs7   B1F) 3A>F1F) =F$?F) F!	F) )G>G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)r   r   _dtr   r   r   r   r   s    r3   purge_expired_temp_regsr&    sK    	DX[^[g[g[n[n[p[z[z[|Z~ 
s   AA++A<	c                0    V ^8  d   QhR\         R\        /# )r.   lengthr0   r?   rI   )r2   s   "r3   r4   r4     s     
 
 
C 
r5   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)TrK   c              3   P   <"   T F  p\         P                  ! S4      x  K  	  R # 5ir   )_secretschoice).0_digitss   & r3   	<genexpr>&generate_unique_pin.<locals>.<genexpr>  s     E}!hoof--}s   #&zQSELECT 1 FROM "formulario-registro" WHERE pin = ? AND used = 0 AND expires_at > ?N)stringr0  r  ranger   r   r%  r   r   r   r   )r(  pinr   r   r0  s   &   @r3   generate_unique_pinr6    s    ]]F
ggEuV}EEWW,,ccll))+5578 hj   W
  WWWs   	AB55C	c                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4     s     ( (' (r5   c                 t    V P                   P                  R 4      pV'       g   R# \        \        V4      4      # )r   N)r;   rP   r   r?   )r/   r   s   & r3   r[   r[     s+    oo!!),G#g,''r5   c                      \        4       ;_uu_ 4       p 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r   r   r   )r   r   s     r3   get_studentsr;    s/    	Dll`a||~ 
s	   !?A	c                $    V ^8  d   QhR\         /# r   r   )r2   s   "r3   r4   r4     s       r5   c                     \        4       ;_uu_ 4       p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   &  r3   get_notifications_for_userr>    s<    	Dll 	 Z	 ||~ 
r   c                $    V ^8  d   QhR\         /# )r.   	sender_idr   )r2   s   "r3   r4   r4     s      c r5   c                     \        4       ;_uu_ 4       p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   &  r3   get_notifications_sent_by_userrB    s<    	Dll 	 \	 ||~ 
r   c                0    V ^8  d   QhR\         R\         /# )r.   r@  recipient_idr   )r2   s   "r3   r4   r4     s      c  r5   c                     \        4       ;_uu_ 4       pVP                  R W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 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@  rD  r   r   s   &&  r3   &get_notifications_sent_by_user_to_userrF    s=    	Dll  &( ||~ 
r   z/notificaciones/eliminardelete_notificationc                ~    V ^8  d   QhR\         R\        R\        R,          R\        R,          R\        R,          /# )r.   r/   r   r   Ntarget_recipient_idr9   r   )r2   s   "r3   r4   r4     sM     'D 'D'D'D Dj'D t	'D
 *'Dr5   c                   "   \        V 4      pV'       g   \        R RR7      # \        W4       \        4       ;_uu_ 4       p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
W8X  d%   VP	                  RV34       VP                  4        MV	eS   W8X  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;   \        V4      pVP                  R8X  d   VP                  R8X  d   \        VRR7      # \        RRR7      #   + '       g   i     L_; i5i)r   r   r   zBSELECT id, sender_id, recipient_id FROM notifications WHERE id = ?r   u   Notificaci�n no encontrada.rM   r   r@  NrD  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 = ?rl   rL   u'   No puedes eliminar esta notificaci�n.rK   /notificacionesrx   )r[   r   rT   r   r   r   r	   r?   r   r   r   r   )r/   r   r   rI  r9   rt   r   r   me_idr@  rD  parseds   &&&&&       r3   rG  rG    s     
g	BH#>>	DllP
 (* 	 C8WXXBtH-0-=-ICK()t	3~./ LLY\k[mnKKM"u'9".37J3K|3[t  xG  wI  JZ]l\noKKMZ//4G4SX[\oXp  uA  YALLY\k[mnKKMC8abb/ 
0 (#==B6==B#6#cBB 1sCC9 
s%   >G7 EG$G7AG7$G4	/G7/c                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4     s     V V Vr5   c                 T   "   \        V 4      p\        P                  R RV RV/4      # 5i)z
index.htmlr/   rY   r[   r\   r]   r/   rt   s   & r3   homerS    ,     	g	B%%lYQS4TUU   &(z/aboutc                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4     s     V V Vr5   c                 T   "   \        V 4      p\        P                  R RV RV/4      # 5i)z
about.htmlr/   rY   rQ  rR  s   & r3   aboutrX  
  rT  rU  z
/ticketingc                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4     s     m mW mr5   c           	      P   "   \         P                  R RV R\        V 4      /4      # 5i)zticketing.htmlr/   rY   )r\   r]   r[   rA   s   &r3   	ticketingr[    s)     %%&6GVUabiUj8klls   $&r   login)rE   rU   c                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4     s     Y YW Yr5   c                 >   "   \         P                  R RV RR/4      # 5i)
login.htmlr/   errorN)r\   r]   rA   s   &r3   	login_getra    s"     %%lYRV4WXXs   
login_postc                <    V ^8  d   QhR\         R\        R\        /# )r.   r/   r   r   rH   )r2   s   "r3   r4   r4     s&     S Sg Sc S Sr5   c                 R  "   VP                  4       P                  4       p\        V4      pV'       d#   \        P	                  W$R ,          4      '       g   \
        P                  RRV RR/4      # \        V 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_  r/   r`  u   Credenciales inv�lidasr   r   rl   rm   admin@admin.esr   r   ry   	dashboard)striprr   r   r   verifyr\   r]   rB   r?   r;   r   url_for)r/   r   r   
email_normrY   s   &&&  r3   rb  rb    s     $$&JZ(D{))(4IJJ)),GWVp8qrr7!$T$ZGOOI"6lGOOFF|w*0@"@GOOG$<#NN	f	"GOOI$>CPPGOOK$@cRRs   D%D'z/docentery   c                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   (  s      W r5   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\  r   r   rl   zdocente.htmlr/   rY   r  rx   )r[   r   ri  r;  r   r\   r]   )r/   rt   r  s   &  r3   docente_dashboardrm  '  s     	g	BGOOG$<#NNHf:--#~H %%wB	
   s(   2A<A) A<)A96A<8A99A<z/valoracionesvaloracionesc                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   <  s     ] ]W ]r5   c                 P  "   \        V 4      pV'       g   \        V P                  R 4      RR7      # RVP                  4       9   d!   \	        VR,          4      P                  4       MRpVR	9  d   \        V P                  R4      RR7      # \        P                  RRV RV/4      # 5i)
r\  r   r   rl   rK   rf  zvaloraciones.htmlr/   rY   rx   )r[   r   ri  r   rI   rr   r\   r]   rs   s   &  r3   valoraciones_pagerq  ;  s     	g	BGOOG$<#NN&,	&93r&z?  "rD''GOOK$@cRR%%&9IwPVXZ;[\\s   B$B&z/api/users/{user_id}api_user_detail)rU   rE   c                0    V ^8  d   QhR\         R\        /# )r.   r   r/   )r?   r   )r2   s   "r3   r4   r4   F  s      3  r5   c                 ^  "   \        V4      pV'       g   \        R RR7      # VR,          R9  d   \        RRR7      h\        4       ;_uu_ 4       p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)r   r   r   rl   rL   rw   rM   a  
            SELECT
                u.id,u.name,u.email,u.created_at,u.role,
                p.phone,p.avatar,p.dni,p.birth_date,p.city,
                s.dominant_foot,s.team,s.category,s.position,s.injury_history,s.strengths,s.weaknesses,s.training_type,
                h.physical_work,h.physical_work_details,h.smoking,h.alcohol,h.recovery,h.chest_pain,h.discomfort,
                c.whatsapp_content,c.video_permission,c.privacy_acceptance,c.data_confirmation,
                COALESCE(f.matricula_eur,0.0) AS matricula_eur,
                CAST(ROUND(COALESCE(f.matricula_eur,0.0)*100) AS INTEGER) AS matricula_cents,
                c.agreement,
                g.occupation,g.study_place,g.parent_name,g.parent_email,
                m.found_us,m.enjoyment,m.nerves_confidence,m.additional_comments
            FROM users u
            LEFT JOIN user_profile p   ON p.user_id=u.id
            LEFT JOIN user_sports s    ON s.user_id=u.id
            LEFT JOIN user_health h    ON h.user_id=u.id
            LEFT JOIN user_consent c   ON c.user_id=u.id
            LEFT JOIN user_guardians g ON g.user_id=u.id
            LEFT JOIN user_marketing m ON m.user_id=u.id
            LEFT JOIN user_finance f   ON f.user_id=u.id
            WHERE u.id = ?
        Nr   Usuario no encontradorx   )r[   r   r	   r   r   r   dict)r   r/   rt   r   r   s   &&   r3   rr  rr  E  s     	g	BH#>>	&z--4KLL	Dll * Z+* "+ 	 
. 4KLL93 
s$   AB-"B2B-B-B*	%B-z	/registerregisterc                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   h  s     n n nr5   c           	      |   "   \        V 4      pT;'       g	    R RRRRR/p\        P                  RRV RRRV/4      # 5i)	rE   rK   r   r   register.htmlr/   r`  NrY   rQ  )r/   rt   ctx_users   &  r3   register_getr|  g  sL     	g	B;;fb'2w;H%%o	7GUY[ack7lmms   :<register_postc                H    V ^8  d   QhR\         R\        R\        R\        /# )r.   r/   rE   r   r   rH   )r2   s   "r3   r4   r4   n  s/     S S S S Scf Sr5   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)rz  r/   r`  zEse email ya existerY   rE   r   r   rK   u(   La contrase�a debe tener 6+ caracteresalumno)rl   r   r   rl   rm   re  r   r   rf  )rg  rr   r   r\   r]   r  r   r?   r;   r   ri  )r/   rE   r   r   rj  rY   s   &&&&  r3   r}  r}  m  s\    $$&J$$))*?&RVR\R\R^`gisu|  A  JB  C
 	
 8}q))*TV\_egkgqgqgsu|  I  KR  TV  _W  X
 	
 

jBZ(D!$T$ZGOOI"6lGOOFF|w*0@"@GOOG$<#NNGOOK$@cRRs   E	Ez/academy-registeracademy_register_getc                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4     s       r5   c                 T   "   \        V 4      p\        P                  R RV RV/4      # 5i)zacademy-register.htmlr/   rY   rQ  rR  s   & r3   r  r    s1     	g	B%%	GVR( rU  uploadsacademyacademy_register_postc                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4     s     X< X< X<r5   c                   a "   \        R~4       \        R4       \        R~4       V P                  4       G Rj  xL
 p\        R\        VP                  4       4       24       \        RRV9    24       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P	                  R
4      ;'       g    RP                  4       pVP	                  R4      ;'       g    RP                  4       p\        RV RV RV RV 24       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'       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pRp	VP	                  R4      p
\        R\        V
4       24       \        V
R4      ;'       d    \        V
R4      p\        RV 24       V'       d   \        RV
P                   24       V'       d   V
P                  '       d    V
P                  4       G Rj  xL
 p\        RV'       d   \        V4      M^  24       V'       dT   \        P                  P!                  V
P                  4      ^,          P                  4       ;'       g    Rp	\        R 4       \)        VP                  4       W$R"WVR#7       \        V4      p\+        VR$,          4      pRpV'       d   V	'       d    \,        R%,          R&,          pVP/                  R'R'R(7       R)V V	 2pVV,          p\        R*V 24       \1        VR+4      ;_uu_ 4       pVP3                  V4       RRR4       \        R,V 24       R-V 2p\        R.V 24       / o VP5                  4        F5  w  pp\7        V\8        4      '       d   K  VR9  g   K'  \;        V4      S V&   K7  	  V 3R0 lpR1V! R1R24      R3V! R34      R4V! R5R44      R6V! R64      R7T;'       g
    V! RR74      /pR8V! R9R8R:4      R;V! R;4      R<V! R=R>R<4      R?V! R@4      RAV! RA4      RBV! RB4      RCV! RD4      REV! RFRGRE4      /pRHV! RI4      RJV! RK4      RLV! RL4      RMV! RM4      RNV! RN4      ROV! RP4      RQV! RQ4      /pRRV! RS4      RTV! RU4      RVV! RW4      RXV! RY4      RZV! RZ4      /pR[V! R[4      R\V! R]R\4      R^V! R_R^4      R`V! RaR`4      /pRbV! RcRb4      RdV! Rd4      ReV! RfRe4      RgV! RhRg4      /p\=        4       ;_uu_ 4       p\?        VV4       \@        ;QJ d*    Ri VPC                  4        4       F  '       g   K   R'M	  RjM! Ri VPC                  4        4       4      '       d_   RkPE                  VP                  4        Uu. uF  pV RlV Rm2NK  	  up4      pVPG                  RnV Ro2. VPC                  4       OVN54       \@        ;QJ d*    Rp VPC                  4        4       F  '       g   K   R'M	  RjM! Rp VPC                  4        4       4      '       d_   RkPE                  VP                  4        Uu. uF  pV RlV Rm2NK  	  up4      pVPG                  RqV Ro2. VPC                  4       OVN54       \@        ;QJ d*    Rr VPC                  4        4       F  '       g   K   R'M	  RjM! Rr VPC                  4        4       4      '       d_   RkPE                  VP                  4        Uu. uF  pV RlV Rm2NK  	  up4      pVPG                  RsV Ro2. VPC                  4       OVN54       \@        ;QJ d*    Rt VPC                  4        4       F  '       g   K   R'M	  RjM! Rt VPC                  4        4       4      '       d_   RkPE                  VP                  4        Uu. uF  pV RlV Rm2NK  	  up4      pVPG                  RuV Ro2. VPC                  4       OVN54       \@        ;QJ d*    Rv VPC                  4        4       F  '       g   K   R'M	  RjM! Rv VPC                  4        4       4      '       d_   RkPE                  VP                  4        Uu. uF  pV RlV Rm2NK  	  up4      pVPG                  RwV Ro2. VPC                  4       OVN54       \@        ;QJ d*    Rx VPC                  4        4       F  '       g   K   R'M	  RjM! Rx VPC                  4        4       4      '       d_   RkPE                  VP                  4        Uu. uF  pV RlV Rm2NK  	  up4      pVPG                  RyV Ro2. VPC                  4       OVN54       VPI                  4        RRR4       \        R~4       \        Rz4       \        R~4       \K        R{R'R|R}/4      #  E
L EL  \"         d.   p\        R!T 24       ^ RIpTP'                  4         Rp?EL7Rp?ii ; i  + '       g   i     EL; i  \"         d.   p\        R/T 24       ^ RIpTP'                  4         Rp?ELRp?ii ; iu upi u upi u upi u upi u upi u upi   + '       g   i     L; i5i)=z,DEBUG: academy_register_post function calledNzDEBUG: Form keys: zDEBUG: Form has playerPhoto: playerPhotor   rK   rE   r   	firstNamelastNamezDEBUG: email=z, name=z, first_name=z, last_name=r   zEl email es obligatorio.rM   zIndica tu nombre.zIndica tus apellidos.u(   Indica tu nombre (mínimo 2 caracteres).u0   La contraseña debe tener al menos 6 caracteres.  u3   Ya existe un usuario con ese email. Inicia sesión.zDEBUG: player_photo type: filenamereadz"DEBUG: is_upload (hasattr check): zDEBUG: player_photo.filename: zDEBUG: content length: .jpgz<DEBUG: Photo stored in memory, will save after user creationzERROR: Failed to read photo: r  )rl   r   r   r   rD   r  Tparentsexist_okuser_zDEBUG: Saving photo to: wbz#DEBUG: Photo saved successfully to z/static/uploads/zDEBUG: avatar_path: z%ERROR: Failed to save photo to disk: c                  R   < V  F  pSP                  V4      pVR9  g   K  Vu # 	  R # )NNrK   null)rP   )r   r   valr   s   *  r3   pick#academy_register_post.<locals>.pick  s-    A((1+C,,
  r5   r   whatsappdni
birth_date	birthDatecityavatarteamcurrentTeamclubcategorypositioncurrentPositionpreferredPositiondominant_footdominantFoot	strengths
weaknessestraining_typetrainingTypeinjury_historyinjuriesinjuryHistoryphysical_workphysicalWorkphysical_work_detailsphysicalWorkDetailssmokingalcoholrecovery
chest_pain	chestPain
discomfortwhatsapp_contentwhatsappContentvideo_permissionvideoPermissionprivacy_acceptanceprivacyAcceptancedata_confirmationdataConfirmation	agreement
occupationstudy_place
studyPlaceparent_name
parentNameparent_emailparentEmailfound_usfoundUs	enjoymentnerves_confidencenervesConfidenceadditional_commentsadditionalCommentsc              3   (   "   T F  qR Jx  K
  	  R # 5ir   r   r.  vs   & r3   r1  (academy_register_post.<locals>.<genexpr>       <&;}&;   F, z=COALESCE(?, r   zUPDATE user_profile SET z WHERE user_id=?c              3   (   "   T F  qR Jx  K
  	  R # 5ir   r   r  s   & r3   r1  r         ;&:}&:r  zUPDATE user_sports SET c              3   (   "   T F  qR Jx  K
  	  R # 5ir   r   r  s   & r3   r1  r    r  r  zUPDATE user_health SET c              3   (   "   T F  qR Jx  K
  	  R # 5ir   r   r  s   & r3   r1  r    r  r  zUPDATE user_consent SET c              3   (   "   T F  qR Jx  K
  	  R # 5ir   r   r  s   & r3   r1  r         >&=}&=r  zUPDATE user_guardians SET c              3   (   "   T F  qR Jx  K
  	  R # 5ir   r   r  s   & r3   r1  r    r  r  zUPDATE user_marketing SET zHDEBUG: About to return JSON response: {'ok': True, 'redirect': '/login'}r   redirectr   zP================================================================================r  )&printformlistr   rP   rg  rr   r	   r  r   typehasattrr  r  ospathsplitextr   	traceback	print_excr   r?   BASE_DIRmkdiropenwriter  ro   r   rI   r   r   anyvaluesr  r   r   r   )!r/   r  r   rE   r   r   r   existingphoto_content	photo_extplayer_photo	is_uploader  rY   r   avatar_pathuploads_dirr  	file_pathfr   r  r  profile_valssports_valshealth_valsconsent_valsguardians_valsmarketing_valsr   setsr   s!   &                               @r3   r  r    s	    	&M	
89	&MD	tDIIK01
23	)-4*?)@
ABXXg$$"++-335EXXf$$"++-D$**H((;'--2446J*%++224I	M%v]:,lS\R]
^_4NOOZ1,4GHHI*4KLL3t9q=4^__s8}q(4fgg 'H4ijjMI88M*L	&tL'9&:
;<j1SSglF6SI	.yk
:;.|/D/D.EFG\***		""."3"3"55M+-C,>UV+WXYGG,,\-B-BCAFLLNXXRX	TV 

eHiU#D$t*oG K	""X-	9KdT:wi	{3H#h.I,YK89i&&!& '7	{CD,XJ7K(67 D

1a$$&&!fDG	 
 	gz*tE{d;5V+>>mX!>L 	]FF3D$D*,?Ln-T+&d<(n-$z?<LM	K 	n-&;!<4	?4	?D$d;'d<(K 	D!23D!23d#67T"45T+&L 	d<(tL-8tL-8]N;	N 	DJ/T+&T"46IJt$8:OP	N 
D w/3<l&9&9&;<333<l&9&9&;<<<99|?P?P?RS?R!=15?RSTDLL3D69IJLmlNaNaNcLmelLmn3;k&8&8&:;333;k&8&8&:;;;99{?O?O?QR?Q!=15?QRSDLL24&8HIKk[M_M_MaKkcjKkl3;k&8&8&:;333;k&8&8&:;;;99{?O?O?QR?Q!=15?QRSDLL24&8HIKk[M_M_MaKkcjKkl3<l&9&9&;<333<l&9&9&;<<<99|?P?P?RS?R!=15?RSTDLL3D69IJLmlNaNaNcLmelLmn3>n&;&;&=>333>n&;&;&=>>>99~?R?R?TU?T!=15?TUVDLL5dV;KLNqP^PePePgNqipNqr3>n&;&;&=>333>n&;&;&=>>>99~?R?R?TU?T!=15?TUVDLL5dV;KLNqP^PePePgNqipNqr) 
* 
&M	
TU	&MtZ:;;i  B 6
  	"1!56!!	"& '&&
  	"9!=>!!	"B T S S T V V% 
s  5liBl(l+l(l/Al4$l$l>$l#B>l"l5i i
	,i 6Ai ;i 	AlAj /j)j *4l#Al'Dl:7k54(k5k5:k:k5k5((k5k5.k?:k5:k5(k5k5"k!3:k5.k5(k59k5k&':k5"k5(k5-k5
k+:k5k58(k5!k5>k0A k59l
i j"j :l jlj		j k'"k	lklk55l	 lz/info-usuariosc                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   +  s       r5   c                    "   \        V 4      pV'       g   \        V P                  R 4      RR7      # \        P	                  RRV RV/4      # 5i)r\  r   r   zinfo-usuarios.htmlr/   rY   )r[   r   ri  r\   r]   rR  s   & r3   info_usuarior  *  sM     	g	BGOOG$<#NN%%&:7=  s   A
Az/gestion-usuariosgestion_usuariosc                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   5  s        G  r5   c           	        "   \        V 4      pV'       g   \        V P                  R 4      RR7      # \        V\        P
                  4      '       d   \        V4      p\        \        V\        4      '       d   VP                  R4      MVR,          ;'       g    R4      P                  4       pVR8w  d   \        V P                  R4      RR7      # \        4       ;_uu_ 4       pVP                  R4      pVP                  4        Uu. uF  p\        V4      NK  	  ppRRR4       \        P                  R	R
V RVRX/4      # u upi   + '       g   i     L1; i5i)r\  r   r   rl   rK   rm   rf  aX  
            SELECT
                u.id,
                u.name,
                u.email,
                u.role,
                u.created_at,
                LOWER(COALESCE(s.category, '')) AS category
            FROM users u
            LEFT JOIN user_sports s ON s.user_id = u.id
            ORDER BY u.created_at DESC, u.id DESC
        Nzgestion-usuarios.htmlr/   rY   r   )r[   r   ri  ro   rp   rq   rv  rI   rP   rr   r   r   r   r\   r]   )r/   rt   rl   r   r   r   r   s   &      r3   r  r  4  s    	g	BGOOG$<#NN"gkk"""X*R"6"6vBvJMM2NTTVDwGOOK$@cRR	Dll   #&,,.1.Qa.1 
 %%wBU	
  2 
s7   BEA
E#$EEE$EEE	Ez
/dashboardrf  c                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   Z  s      W r5   c           	        "   \        V 4      pV'       g   \        V P                  R 4      RR7      # \        V\        P
                  4      '       d   \        VR,          4      M\        VP                  R4      4      p\        V\        P
                  4      '       d
   VR,          MVP                  R4      ;'       g    RP                  4       p\        4       ;_uu_ 4       pVP                  RW"V34      P                  4       p\        V'       d   VR,          e
   VR,          M^ 4      pRRR4       \        P                  R	R
V RVRX/4      #   + '       g   i     L,; i5i)r\  r   r   r   r   rK   a  
            SELECT COUNT(DISTINCT r.id) AS c
            FROM reservations r
            LEFT JOIN reservation_students rs ON rs.reservation_id = r.id
            WHERE rs.user_id = ?
               OR r.user_id = ?
               OR LOWER(COALESCE(r.email,'')) = LOWER(?)
        r   Nzdashboard.htmlr/   rY   reservation_count)r[   r   ri  ro   rp   rq   r?   rP   rg  r   r   r   r\   r]   r/   rt   rL  me_emailr   r   r  s   &      r3   rf  rf  Y  s    	g	BGOOG$<#NN'GKK88C4Mc"&&,>OE)"gkk::7w@U@USU\\^H	Dll  H%' (0xz 	  CCH4HCaP 
 %%wB!2	
  
s%   B<E#?#E#"A
E,$E#E 	E#r   c                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   t  s     X X Xr5   c                 ~   "   \        V 4      pV'       g   \        R RR7      # \        P                  RRV RV/4      # 5i)r   r   r   z
admin.htmlr/   rY   )r[   r   r\   r]   r^   s   & r3   rm   rm   s  s<      DH#>>%%lYQU4VWWs   ;=rK  notificacionesc                >    V ^8  d   QhR\         R\        R,          /# )r.   r/   r   Nr   )r2   s   "r3   r4   r4     s     : :' :C$J :r5   c                 V  "   \        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   \        4       ;_uu_ 4       p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)r   r   r   r   Nrl   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   rv  r   s   & r3   _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.htmlr/   rY   	view_usernotificationssent_notificationsr  notifications_jsonappointmentsappointments_jsonappointments_maprx   )r[   r   r?   r   r   r>  rF  rB  r;  r   r   r   r\   r]   rv  )r/   r   rt   target_user_idr  inboxsentr  r  nr  r  r  r  r   as   &&              r3   r  r    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WW<< )
 !"$
 %-HJ   8D7I7Ir7IK7I\!_7IKDPDVDVTVDVXDVaC$L,q/9DVX%%wBIi4U $ "4L!2 0	
 G  	G	* B
 W LXs   9H)G3 H)AH)%AH)H)H"H):"HH)-H)2H
H)H)"H$4H) H)3H H)HH)H	H)z/api/expensesc          	          V ^8  d   QhR\         R\        \        ,          R\        \        ,          R\        \        ,          /# )r.   r/   	date_fromdate_tor   r   r   rI   r?   )r2   s   "r3   r4   r4     s<     < <<}< c]< c]	<r5   c                   "   \        V 4       R  R lp. p. pV'       d+   V! V4       VP                  R4       VP                  V4       V'       d+   V! V4       VP                  R4       VP                  V4       Ve,   VP                  R4       VP                  \        V4      4       RpV'       d    VRRP                  V4      ,           ,          pVR	,          p\	        4       ;_uu_ 4       p\
        P                  Vn        VP                  V\        V4      4      P                  4       p	. p
V	 F  pT
P                  R
VR
,          RVR,          RVR,          RVR,          RVR,          RVR,          RVR,          R\        VR,          ;'       g    ^ 4      RVR,          RVR,          RVR,          /4       K  	  V
uuRRR4       #   + '       g   i     R# ; i5i)c                $    V ^8  d   QhR\         /# )r.   sr   )r2   s   "r3   r4   'api_expenses_list.<locals>.__annotate__  s     _ _C _r5   c                 v     \         P                  ! V R 4       R#   \         d    \        RRT  R2R7      hi ; i)%Y-%m-%dr   u   Fecha inv�lida: z (YYYY-MM-DD)rM   Nr   strptimer   r	   r(  s   &r3   _ok_date#api_expenses_list.<locals>._ok_date  s@    	_a, 	_C:LQC}8]^^	_    8zjg.date >= ?zjg.date <= ?Nzjg.user_id = ?a  
        SELECT
            jg.id,
            jg.created_at,
            jg.date,
            jg.user_id,
            jg.reservation_id,
            jg.amount_cents,
            jg.category,
            jg.concept,
            jg.notes,
            u.name  AS user_name,
            u.email AS user_email
        FROM jugadores_gastos jg
        LEFT JOIN users u ON u.id = jg.user_id
     WHERE r  z  ORDER BY jg.date ASC, jg.id ASCr   r:   dater   	user_name
user_emailr  amount_centsr  conceptr   )rZ   r  r?   r  r   rp   rq   r   r   r  r   )r/   r#  r$  r   r/  wherer   sqlr   r   outr   s   &&&&        r3   api_expenses_listr;    s     '_ EFU\\.96==;S5<<7w9O%&c'l(CC  y7<<...--C	D";;||Cv/88:AJJagao&	1Y<Q{^ao !$4"5An$5$:$: ;AjM1Y<7   % 
s2   AG A"G 5:G /B%G,GG G		G c                   R   a  ] tR tRt o ]! ^ R7      tRtRtRtRt	Rt
V 3R ltRtV tR# )	ExpenseIni  r  Nc                   < V ^8  d   Qh/ S[ ;R&   S[;R&   S[S[ ,          ;R&   S[S[ ,          ;R&   S[S[ ,          ;R&   S[S[,          ;R&   S[S[,          ;R&   # )r.   r3  r6  r  r7  r   r   r  rI   r?   r   )r2   __classdict__s   "r3   r4   ExpenseIn.__annotate__  so     
I #  sm"  c]!	 
 C=  c]!  SM( r5   r   )__name__
__module____qualname____firstlineno__r   r6  r  r7  r   r   r  __annotate_func____static_attributes____classdictcell__rA  s   @r3   r=  r=    s.     L"H!GE!G$(N  r5   r=  c                0    V ^8  d   QhR\         R\        /# r.   r/   payload)r   r=  )r2   s   "r3   r4   r4   !  s     # #w # #r5   c                   "   \        V 4        \        P                  ! VP                  R 4       \        P                  ! 4       P                  R4      p\        4       ;_uu_ 4       pTP                  RTTP                  P                  4       TP                  e   \        TP                  4      MRTP                  '       d   \        TP                  4      MR\        TP                  ;'       g    ^ 4      TP                  ;'       g    RP                  4       ;'       g    RTP                   ;'       g    RP                  4       ;'       g    RTP"                  ;'       g    RP                  4       ;'       g    R34      pTP$                  pRRR4       RR	R
X/#   \         d    \        RRR7      hi ; i  + '       g   i     L2; i5i)r+  r   u   Fecha inválida (YYYY-MM-DD).rM   %Y-%m-%d %H:%M:%Sz
            INSERT INTO jugadores_gastos (created_at, date, user_id, reservation_id, amount_cents, category, concept, notes)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        NrK   r   Tr   )rZ   r   r-  r3  r   r	   nowstrftimer   r   rg  r   r?   r  r6  r  r7  r   r   )r/   rM  r:   r   r   gids   &&    r3   api_expenses_createrS     si    'U',,
3 (()<=J	Dll  LL $+OO$?C T+2+A+A+AC&&'t$$))*##**,44__""))+33t]]  b'')11T	
 mm 
 $c""%  U4STTU 
sd   G!F 6G&AF:-F:1F:
F:"F:7F:F:$F:<F:GF77G:G
	Gz/api/expenses/{gid}c                0    V ^8  d   QhR\         R\        /# )r.   r/   rR  r   )r2   s   "r3   r4   r4   :  s      w S r5   c                    "   \        V 4       \        4       ;_uu_ 4       pVP                  R V34       RRR4       RR/#   + '       g   i     RR/# ; i5i)z)DELETE FROM jugadores_gastos WHERE id = ?Nr   T)rZ   r   r   )r/   rR  r   s   && r3   api_expenses_deleterV  9  sG     '	D@3&I 
$< 
$<s   AA A A	Acreate_notificationc                    V ^8  d   QhR\         R\        R\        R\        R\        R,          R\        R,          R\        R,          /# )	r.   r/   rD  r   bodyr   Nr  r9   r   )r2   s   "r3   r4   r4   B  sc     3D 3D3D3D 3D 	3D
 Dj3D $J3D *3Dr5   c                   "   \        V 4      pV'       g   \        R RR7      # VR,          R9  d   \        RRR7      h\        W4       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\        4       ;_uu_ 4       p	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       \        4       ;_uu_ 4       p	T	P                  R\        P                  P                  4       P                  4       \        TR,          4      YY83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)r   r   r   rl   rL   z3Solo docentes o admin pueden enviar notificaciones.rM   rK   r   u$   T�tulo y mensaje son obligatorios.u   Destinatario inv�lido.Nu   Reserva inv�lida.z1SELECT id, user_id FROM reservations WHERE id = ?r   Reserva no encontrada.r   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, ?)
            r   rK  rx   )r[   r   r	   rT   rg  r?   r   rI   r   r   r   r   r   r   r   r   r   r   r   )r/   rD  r   rY  r   r  r9   rt   res_id_to_saver   resrM  s   &&&&&&&     r3   rW  rW  A  s     
g	BH#>>	&z--4ijj[[b!EJJBD4Z[[P<( N!c.&9&?&?&AR&G	O 0N WW,,C! hj  #<TUU3y>&&Q'<7#<mnn 8  
D [[!++-s2d8}lSWh	
 	 
 (#==B6==B#6#cBB 1sCC=  P4NOOP  	OC8MNN	OWW 
s   AI?I?,I?I?I?H  &$I?H< I?(AI4II?(A!I,	I?AI? H99I?<II?I)	#	I?,I<	7I?z/api/teachersapi_teachersc                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   x  s     	 	 	r5   c                 (  "   \        V 4      pV'       g   \        R RR7      # \        4       ;_uu_ 4       p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)r   r   r   z\SELECT id, name, email, created_at, role FROM users WHERE role = 'docente' ORDER BY name ASCN)r[   r   r   r   r   rv  )r/   rY   r   r   r   r   s   &     r3   r^  r^  w  sx      DH#>>	Dllj
 "%0AQ0	 

 K 1	 

 Ks.   3B$A>A9-A>/
B9A>>B			Bc                   0   a  ] tR tRt o RtV 3R ltRtV tR# )CategoryUpdatei  Nc                6   < V ^8  d   Qh/ S[ S[,          ;R&   # r.   r  r   rI   )r2   rA  s   "r3   r4   CategoryUpdate.__annotate__       sm" r5   r   rC  rD  rE  rF  r  rG  rH  rI  rJ  s   @r3   rb  rb         "H  r5   rb  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&   # )r.   rl   r   )r2   rA  s   "r3   r4   RoleUpdate.__annotate__  s     
I r5   r   NrC  rD  rE  rF  rG  rH  rI  rJ  s   @r3   rk  rk          r5   rk  c                0    V ^8  d   QhR\         R\        /# )r.   r   rl   r)  )r2   s   "r3   r4   r4     s      3 c r5   c                     \        4       ;_uu_ 4       pVP                  R W34       VP                  4        RRR4       R#   + '       g   i     R# ; i)&UPDATE users SET role = ? WHERE id = ?N)r   r   r   )r   rl   r   s   && r3   set_user_rolers    s1    	D=O 
s   $AA	c                   0   a  ] tR tRt o RtV 3R ltRtV tR# )rb  i  Nc                6   < V ^8  d   Qh/ S[ S[,          ;R&   # rd  re  )r2   rA  s   "r3   r4   rf    rg  r5   r   rh  rJ  s   @r3   rb  rb    ri  r5   z/api/users/{user_id}/categoryapi_users_set_categoryc                <    V ^8  d   QhR\         R\        R\        /# r.   r   rM  r/   )r?   rb  r   )r2   s   "r3   r4   r4     s"     = =# = =QX =r5   c                   "   \        V4       \        V 4      pV'       g   \        R RR7      hVP                  ;'       g    RP	                  4       P                  4       pV'       d   V\        9  d   \        RRR7      h\        4       ;_uu_ 4       pVP                  RV 34       TP                  RV'       d   TMRV 34       VP                  4        RRR4       R	R
RV RV/#   + '       g   i     L; i5i)r   ru  rM   rK   r   u   Categoría no válidar   z5UPDATE user_sports SET category = ? WHERE user_id = ?Nr   Tr   r  )
rZ   r   r	   r  rg  rr   ALLOWED_CATEGORIESr   r   r   )r   rM  r/   r   catr   s   &&&   r3   rv  rv    s     'G$F4KLL!!r
(
(
*
0
0
2C
s,,4KLL	DLwjYLVYs_celNmn 
 $	7J<<	 
s*   >C7&C7(*C7AC$C7$C4	/C7z
/api/users	api_usersc                h    V ^8  d   QhR\         R\        \        ,          R\        \        ,          /# )r.   r/   rolesrl   )r   r   rI   )r2   s   "r3   r4   r4     s.     . ..C=. 3-.r5   c                   "   \        V 4      pV'       g   \        R RR7      # . pV'       dU   VP                  R4       Uu. uF8  qUP                  4       '       g   K  VP                  4       P	                  4       NK:  	  ppM'V'       d    VP                  4       P	                  4       .pRp. pV'       d9   RP                  R\        V4      ,          4      pRV R2pVP                  V4       \        4       ;_uu_ 4       p	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 u upi   + '       g   i     X# ; i5i)r   r   r   ,rK   ?zWHERE lower(u.role) IN (r   a  
            SELECT
                u.id,u.name,u.email,u.created_at,u.role,u.first_name,u.last_name,
                p.phone,p.avatar,
                s.team,s.category,s.position,s.injury_history,
                p.dni,p.birth_date,p.city,
                s.dominant_foot,s.strengths,s.weaknesses,s.training_type,
                h.physical_work,h.physical_work_details,h.smoking,h.alcohol,h.recovery,h.chest_pain,h.discomfort,
                c.whatsapp_content,c.video_permission,c.privacy_acceptance,c.data_confirmation,
                COALESCE(f.matricula_eur,0.0) AS matricula_eur,
                CAST(ROUND(COALESCE(f.matricula_eur,0.0)*100) AS INTEGER) AS matricula_cents,
                c.agreement,
                g.occupation,g.study_place,g.parent_name,g.parent_email,
                m.found_us,m.enjoyment,m.nerves_confidence,m.additional_comments
            FROM users u
            LEFT JOIN user_profile p   ON p.user_id=u.id
            LEFT JOIN user_sports s    ON s.user_id=u.id
            LEFT JOIN user_health h    ON h.user_id=u.id
            LEFT JOIN user_consent c   ON c.user_id=u.id
            LEFT JOIN user_guardians g ON g.user_id=u.id
            LEFT JOIN user_marketing m ON m.user_id=u.id
            LEFT JOIN user_finance f   ON f.user_id=u.id
            z(
            ORDER BY u.id DESC
        N)r[   r   splitrg  rr   r  r  extendr   r   r   rv  )r/   r~  rl   rY   
roles_listr   r8  r   placeholdersr   r   r   s   &&&         r3   r|  r|    s1      DH#>>J16S1AO1AAWWY'aggioo'1A
O
	jjl((*+
EFxxc*o 56*<.:j!	Dll  , G 	-0 12 "%0AQ05 
6 KI PF 15 
6 KsS   *E%E% E"E>
E%	*E%4A
E%>)E'E;E=E%EE"		E%z/api/users/{user_id}/roleapi_users_set_rolec                <    V ^8  d   QhR\         R\        R\        /# rx  )r?   rk  r   )r2   s   "r3   r4   r4     s&     O Oc OJ O Or5   c                   "   \        V4       \        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WT8X  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)r   ru  rM   rK   r   u   Rol inv�lidorl   rm   r   Tr   changedFuU   Debe existir al menos un usuario con rol admin. No puedes degradar al �ltimo admin.)
rZ   r   r	   rl   rg  rr   ALLOWED_ROLESrI   r   rs  )	r   rM  r/   r   new_rolecurrent_role	was_adminis_demoting_adminadmins_counts	   &&&      r3   r  r    s     'G$F4KLL""))+113H}$4DEEvf~&,,.L'I!99h'&9dIw)USS#~1n  '$$	7FHiNNs   >C7A$C7&C73C7z^\d{4}-\d{2}-\d{2}$)patternz^\d{2}:\d{2}$c                      a  ] tR tRt o ]! ^<^R
R7      t]! ^ ^ R7      t]! ]R7      tR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  r  r
  r>  )default_factoryN
confirmadaFc                6  < 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&   S[S[,          ;R&   S[;R&   # r.   r3  r@   r   r   user_idsr   rE   r   r   r   r   r   r   )DateStrTimeStrr?   r   r   rI   r   )r2   rA  s   "r3   r4   ReservationIn.__annotate__  s     
M 
M  5  %	 
 3i5  c]!  3-  C=  C=  SM(  C=  $   r5   r     )rC  rD  rE  rF  r   r   r   r  r  r   rE   r   r   r   r   r   r   rG  rH  rI  rJ  s   @r3   r  r    sZ      ""u5Q1~K5H!GDEE(FE $JD  r5   r  c                      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RtRtV 3R ltRtV tR# )ReservationUpdatei  Nr  r>  c                  < V ^8  d   Qh/ S[ S[,          ;R&   S[ S[,          ;R&   S[ S[,          ;R&   S[ S[,          ;R&   S[ 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  r?   r   rI   r   )r2   rA  s   "r3   r4   ReservationUpdate.__annotate__  s     
7
" 
7
"  smA  #2	 
 tCy!(  c]!  3-  C=  C=  SM   C=  $  4. r5   r   r  )rC  rD  rE  rF  r3  r@   r   r   r   r  r   rE   r   r   r   r   r   r   rG  rH  rI  rJ  s   @r3   r  r    s^     "D"D&+DQ5&A!&t!2K$(H!GDEE FE $JD  r5   r  c                   D   a  ] tR tRt o ]! ^^R7      tRtV 3R ltRtV t	R# )RatingIni  r  Nc                N   < V ^8  d   Qh/ S[ ;R&   S[ ;R&   S[S[,          ;R&   # )r.   	player_idscorecommentr  )r2   rA  s   "r3   r4   RatingIn.__annotate__  s+     N "  c]! r5   r   )
rC  rD  rE  rF  r   r  r  rG  rH  rI  rJ  s   @r3   r  r    s     !"E!G  r5   r  c           !      r   R V R ,          RV R,          RV R,          RV R,          RV R,          R\        V R,          ;'       g    ^ 4      R\        V R,          ;'       g    ^ 4      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,          MRRRV P                  4       9   d   V R,          e   \        V R,          4      MR/p\        4       ;_uu_ 4       pVP	                  RV R ,          34      P                  4       pRRR4       X Uu. uF  p\        VR ,          4      NK  	  upVR&   V Uu. uF)  pR \        VR ,          4      RVR,          R	VR	,          /NK+  	  upVR&   V#   + '       g   i     Lp; iu upi u upi )r   r:   r3  r@   r   r   	price_eur      Y@rE   r   r   r   r   r   r   Nr   Fz
            SELECT u.id, u.name, u.email
            FROM reservation_students rs
            JOIN users u ON u.id = rs.user_id
            WHERE rs.reservation_id = ?
            ORDER BY u.name
        student_idsr  )r?   r   r   r   r   r   )r   baser   srowsr   s   &    r3   r   r     s   c$ic,'FFC 23s3}-223c#m,112U:FWWW3y>#h-<388:+Ec,'4Vsxxz%9c&k>US[![`D" 
A		  $i\ $8: 	 
 277A3qw<7D^cd^cYZs1T7|VQvY7T^cdDK 
 8ds   )F F/%/F4F,	c                <    V ^8  d   QhR\         R\        R\        /# )r.   r/   r   rM  )r   r?   r  )r2   s   "r3   r4   r4   ;  s'     S& S&7 S&C S&J[ S&r5   c                   "   \        V 4       \        VR 4      '       d   VP                  RR7      MT;'       g    / p V P                  4       G Rj  xL
 pRV9   d0   RV9  d)    \        VP                  R4      ;'       g    ^ 4      VR&   RV9   d   RV9  d   VP                  R4      VR&   RV9   dP   R	V9  dI    \        \        \        \        VR,          4      P                  R
R4      4      ^d,          4      4      VR	&   RV9   dP   R	V9  dI    \        \        \        \        VR,          4      P                  R
R4      4      ^d,          4      4      VR	&   \        V4      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R,          4      pTp	RV9   d   VR,          e   \        VR,          4      p	MVP                  RVP                  R4      4      p
V
ep   \'        V
\        4      '       d   T
p	MV\'        V
\
        \        34      '       d;   \        V
4      P)                  4       P+                  4       pVR:9   d   Rp	M	VR;9   d   Rp	V'       g   W8X  d   \%        RRR7      hV	'       d   ^M^ VR&   RV9   d4   VR,          e)    \,        P.                  P1                  VR,          R4       RV9   d   VR,          e    \        VR,          4      P)                  4       R,          p\3        \
        VP5                  R4      4      w  r^ 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   d9   VR,          e.   \        VR,          4      pV^ 8:  g   VR<8  d   \%        RR!R7      hR"V9   dZ   VR",          eO   \        VR",          4      P)                  4       P+                  4       pV\6        9  d   \%        RR#V 2R7      hVVR"&   RV9   dg   VR,          e\   VR,          p\        4       ;_uu_ 4       pVP!                  R$V34      P#                  4       pV'       g   \%        RR%R7      h RRR4       RV9   dP   R	V9  dI    \        \        \        \        VR,          4      P                  R
R4      4      ^d,          4      4      VR	&   R	V9   d<    \        VR	,          ;'       g    ^ 4      VR	&   VR	,          ^ 8  d   \%        RR&R7      h0 R=mp. p. pVP9                  4        F4  w  ppVV9   g   K  VP;                  V R(24       VP;                  V4       K6  	  V'       g   \%        RR)R7      h \        R	V9   d   VP                  R	4      MVR	,          ;'       g    ^ 4      pV'       * ;'       d    T	pVP;                  V4       \        4       ;_uu_ 4       p\        P                  Vn        V'       Ed   V^ 8  Ed   VP!                  R*V34      P=                  4       pV Uu. uF"  pVR',          f   K  \        VR',          4      NK$  	  ppV'       g$   VR',          '       d    \        VR',          4      .p/ p VP                  R+4      ;'       g    / p\'        V\        4      '       dq   / pVP9                  4        FX  w  pp \'        V\        4      '       d   \        V4      M
\        V4      p  \        T;'       g    ^ 4      p!\?        ^ T!4      TT &   KZ  	  TpT'       Ed   TPA                  R,T U"u. uF  p"T"3NK  	  up"4       / p#T'       d=   T F5  p"\?        ^ \        TP                  T"T4      ;'       g    ^ 4      4      T#T"&   K7  	  M+T F%  p"\?        ^ \        T;'       g    ^ 4      4      T#T"&   K'  	  \,        P.                  PC                  4       PE                  R-4      p$TP                  R4      ;'       g
    TR,          p%TP                  R4      ;'       g    TR,          ;'       g    R.R,          p&R/T% R0T& 2p'. p(T#P9                  4        FX  w  p"p)\        T)R1,          ^4      p*TP!                  R2T*T"34       T)^ 8  g   K6  T(P;                  T$T%T"T\        T)4      R3T'R34       KZ  	  T('       d   TPA                  R4T(4       VP!                  R5R6PG                  V4       R72\I        V4      4       VPK                  4        RRR4       R8RR9V/#  E	L.  \         d    / p E	L<i ; i  \         d     E	Li ; i  \         d     ELi ; i  \         d     ELni ; i  + '       g   i     EL'; i  \         d    Rp ELi ; i  \         d    \%        RRR7      hi ; i  \         d    \%        RRR7      hi ; i  + '       g   i     ELd; i  \         d
    ^ TR	&    EL$i ; i  \         d
    ^ TR	&    ELi ; i  \         d    ^ p ELsi ; iu upi   \         d    . p ELi ; i  \         d     EK  i ; i  \         d    ^ p! ELOi ; i  \         d    / p ELNi ; iu up"i   + '       g   i     ELs; i5i)>rv  T)exclude_unsetNdurationr   
teacher_idr   r  r   r  .price'SELECT * FROM reservations WHERE id = ?r   zReserva no encontradarM   r   Fhas_paidr   zNada que actualizarr3  r+  u(   Fecha inválida. Usa formato YYYY-MM-DD.r@   N   N:u"   Hora inválida. Usa formato HH:MM.   Hora inválida.,No se admiten reservas a medianoche (00:00).u&   Hora fuera de horario (08:00–22:00).02d   Duración inválida.r   Estado no permitido: FSELECT id FROM users WHERE id=? AND LOWER(COALESCE(role,''))='docente'/   docente_id no corresponde a un docente válido.   Precio inválido.r   z = ?u'   Ningún campo permitido para actualizarzASELECT user_id FROM reservation_students WHERE reservation_id = ?per_student_centsr   z%Y-%m-%dT%H:%M:%Sz00:00Reserva  r  cUPDATE user_finance SET matricula_eur = ROUND(COALESCE(matricula_eur,0.0) - ?, 2) WHERE user_id = ?reservaz
                        INSERT INTO jugadores_gastos
                        (created_at, date, user_id, reservation_id, amount_cents, category, concept, notes)
                        VALUES (?, ?, ?, ?, ?, ?, ?, ?)
                    zUPDATE reservations SET r  z WHERE id = ?r   r   1trueu   sísion)0falsenooffr  >   r3  rE   r   r@   r   r   r   r   r   r   r   r   )&rz   r  rv  jsonr   r?   rP   roundfloatrI   replacer   r   rp   rq   r   r   r   r	   ro   rg  rr   r   r   r-  mapr  ALLOWED_STATUSESr  r  r   r  executemanyrP  rQ  r  r  r   )+r/   r   rM  updatesrawhas_other_updatesr   prev_row	prev_paidnew_paidr  r(  thhmmdminstatus_normr   dallowed	set_partsargsr   r  effective_price_centsdo_charge_nowr   r   r  r  psctmpkkvvr8   sharesnow_txtdate_txttime_txtconcept_baseto_insshare	share_eurs+   &&&                                        r3   api_reservations_updater  :  s
    W%29'62J2Jglll.QXQ^Q^\^GLLN" S/w>	*-cggj.A.F.FQ*GG&' s|7: # 5cm7:	%(uS[9I5J5R5RSVX[5\/]`c/c)d%eGM" #~-w6	%(uSW5F5N5NsTW5X/Y\_/_)`%aGM" W	D";;<< IF9U^^` 
 4KLL&)*	 HWV_8(ggfcggj12?#t$$C#s,,HNN$**,88#H55$H!64IJJ#aGFOWV_8	dKK  *= WV_8	^GFO$**,R0Aaggcl+FB R"b2C8IJJ7rQwC8fggR"C8`aaHAbX.W$1C)D)P7-./19uC8NOO7wx0<'(+,224::<..C:OP[}8]^^'w7<#8#D\*
WWX hj  #<mnn   g-w">	'%(uS9M5N5V5VWZ\_5`/adg/g)h%iGM" 	'%()?)D)D1%EGM" =!A%C8KLLG ID1<s$Z(KKN   4]^^" #-SZBZGKK$>aijwaxa}a}|}  #]00MKK	D";;=2Q6<<S	 hj  7;Wda	l,3q|,dKW8I#6#6%#&x	':#;"<K !#'gg1288bc4((C #		1%+5a+=+=Q3q6B#!$QVV!B #&a*B !, ),% {  `'23{cV{3
 $*&)!S1B1F1FsLa1b1g1gfg-h&is  +  +&)!S1F1K1K!-L&Ms  + ++//+445HI";;v.BB(62B#KK/NN8F3CNNwPRS!)(1XJ?"(,,.JC %eemQ 7ILL}"C( qy#$"J%( 	' 	 #1$ $$ &  	! 	/		)0D/E]SUZ[_U`ac 
f $f%%_ # 
  		  		
  		
 
  	6  	dC8bcc	d  	^C8\]]	^( WW  	'%&GM"	'
  	'%&GM"	'&  " !" X
 ! %"$K%  ) %$%  ) #!"B#  '$&!' 4M 
s  8k0k0f f f k0&f 
f 0k0>Af) k0Af; k087g/k0?k0g! Ck0"k0=k0'g5 >k0Ah Ek07h-k0)Ai 0k08i 
i =k00k0
k0,i/ i/ k0&k0 Akjj4kj!k$k<1k.,jj/)j/0kkkk*k;B+k'!k	kAk4-k"Ak2k0 f fk0fk0f&"k0%f&&k0)f84k07f88k0;g
k0	g

k0g		k0!g2.k01g22k05hk0h**k0-h>	8	k0ik0ik0i,(k0+i,,k0/j <k0?j  k0kjkjkj,	'k+j,	,k/k 	<k?k 	 kkkkkk-	'	k0z/api/reservations/{rid}c                0    V ^8  d   QhR\         R\        /# )r.   r/   ridr   )r2   s   "r3   r4   r4     s     g g7 g gr5   c                 $  a"   \        V 4       R  R loR V3R ll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Rp \        VR	,          4      pV'       Ed   \        VP                  4       4      pR
V9   d   \        VR
,          ;'       g    ^ 4      M^ p. pRV9   dQ   VR,          '       dB    \        P                  ! VR,          4      ;'       g    .  U	u. uF  p	\        V	4      NK  	  pp	M*RV9   d$   VR,          '       d    \        VR,          4      .pV'       g	   V! W14      p\        V U
u0 uF  p
\!        V
\        4      '       g   K  V
kK  	  up
4      p/ pRV9   d   VR,          '       du    \        P                  ! VR,          4      ;'       g    / pVP#                  4        F8  w  r \        V4      pV'       d   W9   d   \        T;'       g    ^ 4      W&   K8  K:  	  V'       g   Tp\%        V4      pV^ 8  d   \'        \)        V4      V4      w  ppV Uu/ uF  qVbK  	  ppVRV  F  pVV;;,          ^,          uu&   K  	  V^ 8  d.   \+        VP                  4       4       F  pVV,          ) VV&   K  	  TpVP#                  4        Fl  w  ppT;'       g    ^ R,          pVP                  RV34      P                  4       pV'       d   VP                  RVV34       KX  VP                  RVV34       Kn  	  VP                  RV34       VP                  RV34       VP-                  4        RRR4       RR/#   \         d    Rp ELi ; iu up	i   \         d    . p ELVi ; i  \         d    . p ELji ; iu up
i   \         d     EK  i ; i  \         d    / p ELi ; iu upi   + '       g   i     RR/# ; i5i)c                0    V ^8  d   QhR\         R\        /# )r.   rE   r0   rI   r   )r2   s   "r3   r4   -api_reservations_delete.<locals>.__annotate__  s      # $ r5   c                 Z    V P                  R V34      P                  4       p\        V4      # )z>SELECT name FROM sqlite_master WHERE type='table' AND name = ?)r   r   r   )r   rE   r   s   && r3   _table_exists.api_reservations_delete.<locals>._table_exists  s0    llLG
 (* 	 Cyr5   c                F    V ^8  d   QhR\         R\        \         ,          /# )r.   r  r0   )r?   r  )r2   s   "r3   r4   r    s       c r5   c                 $  < R Fq  pS! W4      '       g   K   V P                  RV R2V34      P                  4       pV'       d1   V Uu. uF!  qD^ ,          f   K  \        V^ ,          4      NK#  	  upu # Ks  	  . # u upi   \         d     K  i ; i)reservation_userszSELECT user_id FROM z WHERE reservation_id = ?)r   reservation_studentsreservation_alumnos)r   r   r?   r   )r   r  r  r   r   r  s   &&   r3   _get_uids_from_bridge6api_reservations_delete.<locals>._get_uids_from_bridge  s    UAT%%<<.qc1JK hj  37L4aQ4	AaD	4LL  V 	  M  s/   ,B B 	A;A;0B ;B  BBr  r   r[  rM   Fr   r   user_ids_jsonr   per_student_cents_jsonNr  z2SELECT user_id FROM user_finance WHERE user_id = ?zWUPDATE user_finance SET matricula_eur = COALESCE(matricula_eur,0) + ? WHERE user_id = ??INSERT INTO user_finance (user_id, matricula_eur) VALUES (?, ?)z5DELETE FROM jugadores_gastos WHERE reservation_id = ?z%DELETE FROM reservations WHERE id = ?r   T)rz   r   rp   rq   r   r   r   r	   r   r   r   r   r?   r  loadssortedro   r  r  divmodabsr  r   )r/   r  r  r   r   	paid_flagr   r   uidsxr  per_mapjr   r  r8   sidsr   r  remr  centseurr   r  s   &&                      @r3   api_reservations_deleter    s    W%  
D";;llDsfMVVXC8PQQ		S[)I 9sxxz?D:G4:O#c-055A6UVK D$&3+?+?,0JJs?7K,L,R,RPR,RS,RqCF,RDSD d"s9~~I/0D ,T7dAdjC.@11dABD&(G'4/C8P4Q4Q
!

3'?#@AGGRA !	%"%a&C#'3;/2166{ ,7 !* Iq5 &s;'7 ;ID#0459C5#DSzCA  *"Q!%chhj!1A&)!fWCF "2!G%mmo
UzzU*llHF (*  LLqc

 LLYc
 ." LLPSVRXY<sfE[ 
^ $<M  	I	 T  D
 ! D B  ) %$%  ! G! 6c 
^ $<s9  -PAO:?NO:4O: O:1#N!N!N.N!0O:N5O:#O:4O	O	O:7#O!O!4&O	O$O!*O:20O:"O5-A7O:%2O:A$O:<PNO:NO:N!!N2.O:1N22O:5OO:OO:O	O!O	O!!O2.O:1O22O::P	Pz/api/reservationsc                0    V ^8  d   QhR\         R\        /# rL  )r   r  )r2   s   "r3   r4   r4     s     ^6 ^67 ^6] ^6r5   c                   "   \        V 4        V P                  4       G R j  xL
 pRp\        VR4      '       d%   VP                  e   \        VP                  4      pMVP                  RVP                  R4      4      p\        V\
        4      '       d   TpML\        V\        \        34      '       d1   \        V4      P                  4       P                  4       pVRH9   d   RpVP                  P                  4       pVP                  P                  4       R,          p \        P                  P                  V4        \#        \        TP%                  R	4      4      w  r^ 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p\        TP&                  4      p
T
^ 8:  g   T
RI8  d   \!        RRR7      h\        TP(                  ;'       g    ^ 4      p\+        TRR 4      pTf"   TP                  RTP                  R4      4      pT'       gS   TeO   \        T4      R8w  d?    \        \-        \/        \        T4      P1                  RR4      4      ^d,          4      4      pT^ 8  d   \!        RRR7      hTP2                  ;'       g    RP                  4       P                  4       pT\4        9  d   \!        RRT 2R7      hTP6                  ;'       g    R pTP8                  ;'       g    R pTP:                  ;'       g    R p\=        TP>                  ;'       g    . 4      pTP@                  '       d   TPC                  TP@                  4        \E        \G        R T 4       4      4      pT'       Ed$   \I        4       ;_uu_ 4       pTPK                  RRPM                  R\O        T4      ,          4       R2\Q        T4      4      PS                  4       pR R R 4       X Uu/ uF  p\        TR,          4      TbK  	  ppT Uu. uF#  pTT9  g   TT,          R,          R8w  g   K!  TNK%  	  ppT'       d   \!        RR T 2R7      h\O        T4      ^8X  dD   TT^ ,          ,          pT'       g
   TR!,          pT'       g
   TR",          pT'       g
   TR#,          pTPT                  e   TPT                  MR pTf   R$T9   d   TP                  R$4      pTei    \        T4      pT^ 8  dT   \I        4       ;_uu_ 4       pTPK                  R&T34      PW                  4       pT'       g   \!        RR'R7      h R R R 4       MR p\O        T4      ^8X  d
   T^ ,          MR p\        PX                  P[                  4       P]                  R(4      p/ p TP                  R)4      ;'       g    / p\        T\^        4      '       dq   / pTPa                  4        FX  w  p p! \        T \        4      '       d   \        T 4      M
\        T 4      p" \        T!;'       g    ^ 4      p#\c        ^ T#4      TT"&   KZ  	  TpT'       d   / p$T'       d=   T F5  p\c        ^ \        TP                  TT4      ;'       g    ^ 4      4      T$T&   K7  	  M+T F%  p\c        ^ \        T;'       g    ^ 4      4      T$T&   K'  	  \e        T$Pg                  4       4      p%M/ p$\        T;'       g    ^ 4      p% \I        4       ;_uu_ 4       pTPK                  R*TYgT
T%YTTPh                  TTTT'       d   ^M^ 34      p&T&Pj                  p'T'       Ed   TPm                  R+T Uu. uF  pT'T3NK	  	  up4       TPm                  R,T Uu. uF  pT3NK  	  up4       T'       d   T$Pa                  4        F-  w  pp(\-        T(R-,          ^4      p)TPK                  R.T)T34       K/  	  . p*R/T R0T 2p+T$Pa                  4        F:  w  pp(\        T(4      ^ 8  g   K  T*PC                  TTTT'\        T(4      R1T+R 34       K<  	  T*'       d   TPm                  R2T*4       TPo                  4        R R R 4       X'p, \I        4       ;_uu_ 4       p3T3PK                  R8X,34      PW                  4       p-T3PK                  R9T,34      PS                  4       p4T4'       d   \=        T44      M. p5T5'       g   R p6T-R7,          '       d)   T3PK                  R:T-R7,          34      PW                  4       p6T6'       g8   T-R",          '       d)   T3PK                  R;T-R",          34      PW                  4       p6T6'       d   T6.p5R p7T-R<,          e<   T3PK                  R=T-R<,          34      PW                  4       pT'       d
   TR!,          MR p7T5'       d   R>p8R?T-R@,           RAT-RB,           2T7'       d   RCT7 2MR,           R,           p9 \        \u        T 4      R,          4      p:\        PX                  Pw                  4       Py                  RDRE7      p;T3Pm                  RFT5 Uu. uF  pT;T:\        TR,          4      T8T9T,3NK  	  up4       T3Po                  4        R R R 4       RGRRX,/#  E
L  \         d    / p E
Li ; i  \         d    \!        RRR7      hi ; i  \         d    \!        RR
R7      hi ; i  \         d    ^ p EL_i ; i  \         d    \!        RRR7      hi ; i  + '       g   i     EL; iu upi u upi   \         d    \!        RR%R7      hi ; i  + '       g   i     EL; i  \         d     EKs  i ; i  \         d    ^ p# EL>i ; i  \         d    / p EL=i ; iu upi u upi   + '       g   i     EL>; i  \p        Pr                   Ed%    \I        4       ;_uu_ 4       pTPK                  R3YgT34      PW                  4       p-T-'       g   \!        R4R5R7      h\        T-R,          4      p.TPK                  R6T.34      PS                  4       p/T/ Uu. uF  p\        TR7,          4      NK  	  Mu upi p0pT Uu. uF  pTT09  g   K  TNK  	  Mu upi p1pT1'       g   T.p,EM2TPm                  R+T1 Uu. uF  pT.T3NK	  	  Mu upi up4       TPm                  R,T1 Uu. uF  pT3NK  	  Mu upi up4       . p*R/T R0T 2p+T'       d   T1 F  pTP                  TT4      p2 \        T2;'       g    ^ 4      p2M  \         d    ^ p2 Mi ; i\-        \c        ^ T24      R-,          ^4      p)TPK                  R.T)T34       T2^ 8  g   Ky  T*PC                  TTTT.\        T24      R1T+R 34       K  	  T*'       d   TPm                  R2T*4       TPo                  4        T.p,R R R 4        EKc    + '       g   i      ELu; ii ; i  \         d    ^ p: ELi ; iu upi   + '       g   i     EL; i  \         d     ELi ; i5i)JNFr   r  Tr  r   u!   Fecha inválida (usa YYYY-MM-DD).rM   r  u   Hora inválida (usa HH:MM).r  r  z$Hora fuera de horario (08:00-22:00).r  r  r  r  rK   r  r  r  r  r  c              3   B   "   T F  qf   K  \        V4      x  K  	  R # 5ir   r   )r.  r  s   & r3   r1  *api_reservations_create.<locals>.<genexpr>  s      NAQs   u   IDs de alumnos inválidos.zXSELECT id, LOWER(COALESCE(role,'')) AS role, name, email, phone FROM users WHERE id IN (r  r   r   rl   r  u   IDs no v�lidos o no alumnos: rE   r   r   r  u   docente_id inválido.r  r  rO  r  z
              INSERT INTO reservations
              (created_at, date, time, duration_minutes, price_cents, name, email, phone, notes, user_id, status, docente_id, paid)
              VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            zQINSERT OR IGNORE INTO reservation_students(reservation_id, user_id) VALUES (?, ?)r   r  r  r  r  r  z
                            INSERT INTO jugadores_gastos
                            (created_at, date, user_id, reservation_id, amount_cents, category, concept, notes)
                            VALUES (?, ?, ?, ?, ?, ?, ?, ?)
                        z\SELECT id FROM reservations WHERE date=? AND time=? AND COALESCE(docente_id,0)=COALESCE(?,0)r  z%Ya existe una reserva en ese horario.z?SELECT user_id FROM reservation_students WHERE reservation_id=?r   r  z
              SELECT u.id, u.name, u.email
              FROM reservation_students rs
              JOIN users u ON u.id = rs.user_id
              WHERE rs.reservation_id = ?
              ORDER BY u.name
            r  z?SELECT id, name, email FROM users WHERE lower(email) = lower(?)r   z#SELECT name FROM users WHERE id = ?zReserva creadaz!Se ha creado una reserva para el r3  z a las r@   z con secondstimespecz
                  INSERT INTO notifications
                  (created_at, sender_id, recipient_id, title, body, is_read, reservation_id)
                  VALUES (?, ?, ?, ?, ?, 0, ?)
                r   r  r  )=rz   r  r   r  r   r   rP   ro   r?   rI   rg  rr   r3  r@   r   fromisoformatr	   r  r  r   r   getattrr  r  r  r   r  rE   r   r   r  r  r   r  r	  r   r   r   r  r  r  r   r   r   r   rP  rQ  rv  r  r  sumr  r   r   r  r   rp   IntegrityErrorr[   r   r   )<r/   rM  r  r  r  r(  r  r  r  r  r  r   price_eur_rawr  rE   r   r   r  r   r   r   foundr8   badu1r   r  legacy_user_idr  r  r  r  r   r  r  r  r  total_price_centsr   new_idr  r  r  r  created_reservation_idr   existing_idcurrentcurrent_idsto_addr  conn2r  
recipientsrecipdocente_nametitulocuerpor@  now_isos<   &&                                                          r3   api_reservations_creater4    sB    W%LLN" IwGLL$<&	ggfcggj12c4  Ic3Z((C &&(A44 	||!!#H||!!#B'HY
h'SS(..-. LbLQ"\r\4EFF	Qw274bccLbL4Z[[S2c(#Hw''(DqyD5L4JKKg))..Q/KG[$7MSWWW-=>m7C<NRT<T	eE#m*<*D*DS#*N$ORU$UVWK Q4GHH>>11\88:@@BK**6KK=4YZZLL  DD]]""dE]]""dEw''--2.K7??+RS N NNO {WW<<jknkskstwx{  }H  yI  uI  lJ  kK  KL  Mk" hj  
 +//$QQtWq$/)`ksS-=sFASW_A_ssk`C:\]`\a8bcc{q {1~&B&z77'.'9'9'E##4Jlc1WW\*
	QZJ >DLL\M (*  'C@qrr   J'*;'71'<[^$Nkkoo(()<=Ggg)*00bc4  C		1#-a#5#5Q3q6BQVV!B a*B $ !$ "!!S):)>)>sK)P)U)UTU%VWs # #!!S)9)9%:;s #0 0 0q1h5WW,,   8t5FUZ\c\i\iky  |G  IS  Zc  UV  ij  k	lC
 ]]F{  g.9:ksfc]k:   `'23{cV{3 &,lln
U$)%%-$;	 B&, '5  F%-hZq
#CL&,lln
Uu:>"MM ' ( # & #E
 ) , $	+ 	 '5 (( * $	%
 KKMW X "(x3WW-- ILbKdennpCMM # )*, -5HJ  ).e2Jy>>!MMF9~' hj  W!MMW7|o hj  "'JL< ,MM"G#lJ[I]^ggi,-qy4)5c&k]'#f+W/;u\N+E 
" #L$9$$? @I ++,,.88)8L!! # &%a Is1T7|VVE[\%	 a f $455w # "  Y4WXXY  S4QRRS&  	K	  R4PQQR WW
 0`"  	QC8OPP	Q & !  ! B  2 ; 4 WWZ !! :5WW,,l:. hj  #<cddc$i.KllOn hj  7>>g3q|,g>K>%0K[cC{4Jcc[KFK)4&  e178#K%8   ^%+,VcC6V, !)(1XJ?% 1 5 5c; G&$'

OE( &$%E&$)#a-%*?$C	$c* !19"MM ' ( # + #E
 ) , $	+ 	  &, (( * $	%
 )4&s WWW:5B ! " !I"Y WWb  s  yj2 j/j2 C9y!k !k" "B9yA yy2=k> /&yAy#y9yy*yyl :yyAl."y.m
ym3m9Ay;yyAy#m .y7m(?Ayn# -1n# ,m<nn!n# 6y>	yByy!o 3Ao:o
n7o.n<:o	A.o<-o*"o
o x? )Ax+	x+/x+
x+/x+	?x+	x+x+;x+x+>x+)!x&
x+!x? )y/j2 2k?ykyky"k;;y>lylyl++y.l?	9ym%%y(m9	3	y<nn# nn# n n# n  n# #n40y3n44y7
oo		o (x=A/w9,r
w9	r(
!r(
'$w9sw95tw9 w98uuw9uw9u8w9-w9	$w9-x5y9xxyxyx#x+"x##x++x<	6x? :y<x? ?y
yyyc                    V ^8  d   QhR\         R\        \        ,          R\        \        ,          R\        \        ,          R\        \        ,          R\        \        ,          /# )r.   r/   r#  r$  r   r   r   r%  )r2   s   "r3   r4   r4     s`     M7 M7M7}M7 c]M7 c]	M7
 SMM7 M7r5   c           	      "  "   \        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\        4       ;_uu_ 4       p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/# )r.   r(  r0   Nr   )r2   s   "r3   r4   +api_reservations_list.<locals>.__annotate__  s     j js jt jr5   c                 v     \         P                  ! V R 4       R#   \         d    \        RRT  R2R7      hi ; i)r+  r   u   Fecha inválida: z. Usa formato YYYY-MM-DD.rM   Nr,  r.  s   &r3   _check_date*api_reservations_list.<locals>._check_date  sA    	ja, 	jC:KA3Ng8hii	jr1  Nr   u   Estado inválido. Usa uno de: r  r  rM   z	date >= ?z	date <= ?r  zLOWER(status) = ?r  r2  r  rK   aR  
        SELECT
            id,
            created_at,
            date,
            time,
            duration_minutes,
            price_cents,
            name,
            email,
            phone,
            notes,
            user_id,
            status,
            docente_id,
            paid
        FROM reservations
        z1
        ORDER BY date ASC, time ASC, id ASC
    )rz   rg  rr   r  r	   r  r	  r  r   r   r   r   )r/   r#  r$  r   r   r   r:  r  r8  r   clauser9  r   r   r   s   &&&&&&         r3   api_reservations_listr=    s     W%j IGW!4$7!%Klln**,..7		&IYBZ8[7\\]^ 
 EF[!i [!g]#g()k"%&j!27i',,u--RF	" 
 #C* 
D||C(113 
 266A$Q'66 
 7sZ   )HHHHA!H8)H"AH2AH2H4 G7H H
4H7H	H/perfilc                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4     s      ' r5   c           	        "   \        V 4      pV'       g   \        R RR7      # \        V\        P                  4      '       d   \        VR,          4      M\        VP                  R4      4      p\        V\        P                  4      '       d
   VR,          MVP                  R4      ;'       g    RP                  4       p\        4       ;_uu_ 4       pVP                  RW#34      P                  4       pV'       d
   VR,          M^ pRRR4       \        P                  R	R
V RVRX/4      #   + '       g   i     L,; i5i)r   r   r   r   r   rK   z
            SELECT COUNT(*) AS c
            FROM reservations r
            WHERE r.user_id = ?
               OR LOWER(COALESCE(r.email,'')) = LOWER(?)
            r   Nzprofile.htmlr/   rY   r  )r[   r   ro   rp   rq   r?   rP   rg  r   r   r   r\   r]   r  s   &      r3   perfilrA    s     	g	BH#>>'GKK88C4Mc"&&,>OE)"gkk::7w@U@USU\\^H	Dll 
 (* 	 ),CH 
 %%wB!2	
  
s$   B-D?0#D?5D,$D?,D<	7D?/ajustesc                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   	  s      w r5   c                   "   \        V 4      pV'       g   \        R RR7      # \        4       ;_uu_ 4       pVP                  RVR,          34      P	                  4       pVP                  RVR,          34      P	                  4       pVP                  RVR,          34      P	                  4       pRRR4       X'       d   \        V4      M/ pX'       d   VP                  \        V4      4       X'       d   VP                  \        V4      4       \        P                  RR	V R
VRV P                  P                  R4      /4      #   + '       g   i     L; i5i)r   r   r   z8SELECT id, name, email, created_at FROM users WHERE id=?r   z6SELECT phone, avatar FROM user_profile WHERE user_id=?zPSELECT team, category, position, injury_history FROM user_sports WHERE user_id=?Nsettings.htmlr/   rY   r9   )r[   r   r   r   r   rv  updater\   r]   r;   rP   )r/   rt   r   row_corerow_profile
row_sportsctxs   &      r3   ajustes_getrK  	  s     	g	BH#>>	D<< Z]_`d]e\ghqqsll#[^`ae^f]hirrt\\"twyz~w  wB  C  L  L  N
 
 %$x."C

4$%

4
#$%%wCGOO''/	
  
s0   3EA9E.E>E!E5AEE	Ec                    V ^8  d   QhR\         R\        R\        R\        R\        R\        R\        R\        R	\        R
\        /
# )r.   r/   rE   r   r   r  r  r  r  r  r9   )r   rI   r   )r2   s   "r3   r4   r4   ,	  sl     9< 9<9<
9< 9< 	9<
 9< 9< 9< 9< 9< 9<r5   c
                   "   \        V 4      p
V
'       g   \        R RR7      # \        W	4       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\	        4       ;_uu_ 4       p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  d8   \        P                  R	R
V RV
RRRV P                  P!                  R4      /4      # \"        R,          R,          pVP%                  RRR7       VRV
R,           V 2,          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 \	        4       ;_uu_ 4       pVP                  RWV
R,          34       VP                  RV
R,          34       VP                  RW>V
R,          34       VP                  RV
R,          34       VP                  R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RT P                  P!                  R4      /4      u # i ; i5i)r   r   r   rK   Nz1SELECT avatar FROM user_profile WHERE user_id = ?r   r  r  rE  r/   rY   r`  z:Formato de imagen no permitido. Usa PNG, JPG, JPEG o WebP.r9   rD   r  Tr  r  r  z/static/uploads/user_z+UPDATE users SET name=?, email=? WHERE id=?r   z9UPDATE user_profile SET phone=?, avatar=? WHERE user_id=?r   zWUPDATE user_sports SET team=?, category=?, position=?, injury_history=? WHERE user_id=?u+   El correo ya est� en uso por otra cuenta.r>  )z.pngr  z.jpegz.webp)r[   r   rT   rg  r   r   r   r  r  r  r  r  rr   r\   r]   r;   rP   r  r  r  r  r  r   rp   r   )r/   rE   r   r   r  r  r  r  r  r9   rt   r   r   current_avatarr  extr  r  r  s   &&&&&&&&&&         r3   ajustes_postrP  +	  s^     
g	BH#>>JJBD[[b!Ekkr  "**dEZZR ((DDR&&(00DHR&&(00DH%++224<<N	DllNQSTXQYP[\eeg*-X4 
 !Kv'&*d33ggv/288:88--o7U++F3	@   )I5$6E"T(C5"99	)T""aGG&++-'( #-bhZu=WWLLFVXY]V^H_`LLQTVW[T\S^_LLTW\kmnrksVtuLLPSUVZS[R]^LLruy  FN  `b  cg  `h  ui  jKKM  	s;;E 
" ( #" W !! ))/wBBGOO''/	<
  	s   4O"O"O"+O"O"O"'O"3O"O"O"/O";O"O"(<M$O"7C O"M*6M(7M*?O"N (BM=?N O"M%		O"(M**M:	5O"=N	N O"N AOO"OO"z/notesc                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   i	  s     I I Ir5   c                 8  aa"   \        V 4      pV'       g   \        R RR7      # Rp. pRVP                  4       9   d   VR,          e   \        VR,          4      MRpVR8X  d   M\VR8X  d,   VR	,          pVP	                  \        VR
,          4      4       M*VR,          pVP	                  \        VR
,          4      4       VR,          p\        4       ;_uu_ 4       pVP                  W#4      P                  4       pRRR4       R oV3R loV3R lpV3R lp. p	X EFH  p
S! V
RR4      ;'       g    RpS! V
RRR4      ;'       g    RpV'       gq   S! V
R4      '       db   V
R,          '       dS   \        V
R,          4      P                  4       p\        V4      ^8  d
   V^ ,          p\        V4      ^8  d
   V^,          pV'       g	   V'       d   V RV 2P                  4       MS! V
R4      '       d
   V
R,          MRpT	P	                  R
S! V
R
4      '       d
   V
R
,          MRRTRTRTRS! V
R4      '       d
   V
R,          MRRV
R,          RV! V
4      RV! V
4      /4       EKK  	  \        P                  RRV RVRV	/4      #   + '       g   i     EL; i5i)r   r   r   aY  
      SELECT
        r.*,
        su.name  AS student_name,
        su.email AS student_email,
        du.name  AS docente_name,
        du.email AS docente_email
      FROM reservations r
      LEFT JOIN users su ON su.id = r.user_id
      LEFT JOIN users du ON du.id = r.docente_id
      WHERE r.notes IS NOT NULL AND TRIM(r.notes) <> ''
    rl   NrK   rm   ry   z AND r.docente_id = ?r   z AND r.user_id = ?z& ORDER BY r.created_at DESC, r.id DESCc                 L     WP                  4       9   #   \         d     R # i ; i)F)r   r   )r   keys   &&r3   hasnotes.<locals>.has	  s(    	((*$$ 		s    ##c                    < V FC  pS! W4      '       g   K  W,          pVf   K!  \        V4      P                  4       R8w  g   KA  Vu # 	  R # )NrK   )rI   rg  )r   namesr   r  rU  s   &*  r3   r  notes.<locals>.pick	  s>    A3{{f?s3x~~'72'=J	 
 r5   c                 n   < S! V R 4      ;'       g%    S! V R4      ;'       g    S! V R4      ;'       g    R# )student_namerE   r      —r   r   r  s   &r3   student_labelnotes.<locals>.student_label	  s7    C(__Df,=__c7AS__W__r5   c                 L   < S! V R 4      ;'       g    S! V R4      ;'       g    R# )r0  docente_emailr\  r   r]  s   &r3   docente_labelnotes.<locals>.docente_label	  s'    C(RRDo,FRR(Rr5   r3  fechar@   hourhorar:   r  
dt_displayr   studentz
notes.htmlr/   rY   r  )r[   r   r   rI   r  r?   r   r   r   r  r  rg  r\   r]   )r/   rt   r9  r   rl   r   r   r^  rb  r  r   r  r  partsrg  rU  r  s   &              @@r3   r   r   h	  sh    	g	BH#>>C F$	1bj6L3r&z?RTDw		&&c"T(m$##c"T(m$33C	D||C(113 

`SEVW-33VVV4::C\22s<7H7HL)*002E5zQ 85zQ 8;Cx
!H:.557knor  uA  lB  lBVYZfVg  HJ
s3~~#d)4HH*s3/E/E#l+4S\}S)}S)	
 		 ( %%wBU	
 O 
s\   CJ J<5J2J
JJ!J0AJ
J#J6%JJ<A
JJ		J)r)   Fc                0    V ^8  d   QhR\         R\         /# )r.   plainr0   r   )r2   s   "r3   r4   r4   	  s     I I I Ir5   c                     T ;'       g    R p \         '       d   \        P                  ! V 4      # R\        P                  ! V P                  R4      4      P                  4       ,           # )rK   sha256$utf-8)_HAS_BCRYPTr)   r   hashlibsha256encode	hexdigest)rk  s   &r3   hash_passwordrt  	  sG    KKRE{{{5!!w~~ell7&;<FFHHHr5   c                <    V ^8  d   QhR\         R\         R\        /# )r.   rk  stored_hashr0   r  )r2   s   "r3   r4   r4   	  s!      3 S T r5   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)rK   z$2a$z$2b$z$2y$Frm  rn  )
startswithro  r)   rh  r   r  rp  rq  rr  rs  rQ   rR   )rk  rv  expecteddigests   &&  r3   verify_passwordr{  	  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          
      T    V ^8  d   QhR\         R\        R\        R\        R\        /# )r.   r/   current_passwordnew_passwordconfirm_passwordr9   rH   )r2   s   "r3   r4   r4   	  s:     $= $=$=$= $= 	$=
 $=r5   c           	        "   \        V 4      pV'       g   \        R RR7      # \        W4       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\        4       ;_uu_ 4       pVP                  RWuR,          34       VP                  4        RRR4       \        RRR7      #   + '       g   i     L; i5i)r   r   r   rK   rE  r/   rY   r`  u   Las contrase�as no coinciden.u7   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=?r   NrB  )r[   r   rT   rg  r\   r]   r  ro   rv  rP   r{  rt  r   r   r   )	r/   r}  r~  r  r9   rt   rv  new_hashr   s	   &&&&&    r3   ajustes_passwordr  	  sh     
g	BH#>> &&B--/L(..B557'))/wB6<
  	
 <1))/wBN<
  	
 .8D-A-A"&&)r/GZK+99))/wB=<
  	
 \*H	DBXRVxDXY 
 
<< 
s)   4E=E=CE=*+E*E=*E:	5E=c                   B   a  ] tR tRt o ]! ^ R7      tRtV 3R ltRtV t	R# )MatriculaPayloadi	  r>  addc                B   < V ^8  d   Qh/ S[ ;R&   S[S[,          ;R&   # )r.   matricula_centsmoder  )r2   rA  s   "r3   r4   MatriculaPayload.__annotate__	  s     & 
3- r5   r   N)
rC  rD  rE  rF  r   r  r  rG  rH  rI  rJ  s   @r3   r  r  	  s      A;OD  r5   r  z/api/users/{user_id}/matriculac                <    V ^8  d   QhR\         R\        R\        /# r.   r/   r   rM  r   r?   rv  )r2   s   "r3   r4   r4   	  s!     ,
 ,
g ,
 ,
d ,
r5   c                   "   \        V 4       \        VP                  R R4      4      P                  4       pVR9  d   \	        RRR7      hRV9   pRV9   pV'       g   V'       g   \	        RRR7      hV'       d8    \        \        \        VR,          4      P                  RR	4      4      ^4      pM& \        VR,          4      p\        TR,          ^4      p\        4       ;_uu_ 4       pVP                  RV34      P                  4       p	V	'       g   VP                  RVR34       Rp
M\        V	^ ,          ;'       g    R4      p
VR8X  d   TpM\        W,           ^4      pVP                  RW34       RRRVR\        \        V^d,          4      4      /uuRRR4       #   \         d    \	        RR
R7      hi ; i  \         d    \	        RRR7      hi ; i  + '       g   i     R# ; i5i)r  r   r   zmode debe ser 'set' o 'add'.rM   matricula_eurr  zFalta matricula_eur.r  r  u   matricula_eur inv�lido.u   matricula_cents inv�lido.r  z8SELECT matricula_eur FROM user_finance WHERE user_id = ?r  g        z;UPDATE user_finance SET matricula_eur = ? WHERE user_id = ?r   TN>   r  r   )rZ   rI   rP   rr   r	   r  r  r  r   r?   r   r   r   )r/   r   rM  r  has_eur	has_centseurosr  r   r   r*  new_vals   &&&         r3   api_users_update_matricular  	  s    'w{{65)*002D>!4RSS(G!W,I94JKK	U%GO$< = E Ec3 OPRSTE	W 123E eemQ'	DllUX_WabkkmLLZ]dfi\jkGCFMMc*G5=GGOQ/GRU\Tfg $Ws53#78
 
  	UC8STT	U
  	WC8UVV	W 
sb   AG,G,%G,;5F  0G,2F< %G,)AG?AGG, F99G,<GG,G)	#	G,)Pathc                <    V ^8  d   QhR\         R\        R\        /# r  r  )r2   s   "r3   r4   r4   /
  s"     / / /3 /UY /r5   c                 ,  "   \        V 4       VP                  R 4      ;'       g    RP                  4       P                  4       pV\        9  d   \        RRR7      h\        4       ;_uu_ 4       pVP                  RV34      P                  4       pV'       g   \        RRR7      hVP                  RW134       VP                  4        VP                  R	V34      P                  4       pR
R
R
4       RRR\        X4      /#   + '       g   i     L; i5i)rl   rK   r   u   Rol inválidorM   z'SELECT id, role FROM users WHERE id = ?r   ru  rr  z@SELECT id, name, email, role, created_at FROM users WHERE id = ?Nr   TrY   )rZ   rP   rg  rr   VALID_ROLESr	   r   r   r   r   rv  )r/   r   rM  target_roler   r   updateds   &&&    r3   api_users_update_roler  .
  s     ';;v&,,"335;;=K+%ODD	DllDwjQZZ\C8OPP=?UV,,adkcmnwwy 
 $W.. 
s   A-D/A;D*DD	Dz/api/ratingsapi_ratings_createc                0    V ^8  d   QhR\         R\        /# rL  )r   r  )r2   s   "r3   r4   r4   @
  s      g  r5   c           
      p  "   \        V 4      p\        VP                  4      pV'       g   \        R RR7      h\	        VR,          4      P                  4       R8w  d   \        RRR7      h\        VP                  4      pVP                  ;'       g    RP                  4       p\        P                  ! 4       P                  RR	7      p\        4       ;_uu_ 4       pVP                  R
\        VP                  4      \        VR,          4      WEV34       RRR4       RR/#   + '       g   i     RR/# ; i5i)r   zJugador no encontradorM   rl   r  r   zSolo se pueden valorar alumnosrK   r  r  zaINSERT INTO player_ratings (player_id, docente_id, score, comment, created_at) VALUES (?,?,?,?,?)r   Nr   T)rz   r   r  r	   rI   rr   r?   r  r  rg  r   r   r   r   r   )r/   rM  rt   playerr  r  rP  r   s   &&      r3   r  r  ?
  s     	!'	*BG--.F4KLL
6&>  "h.4TUUE$$"++-G
//

%
%y
%
9C	Do""#SD]ECH	
 

 $< 

 $<s%   BD6AD6:D D6 D3	+D6api_ratings_listc                F    V ^8  d   QhR\         R\        \        ,          /# r.   r/   r  )r   r   r?   )r2   s   "r3   r4   r4   R
  s      G  r5   c                 X  "   \        V 4      p. pR pV'       d   RpVP                  \        V4      4       \        4       ;_uu_ 4       p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)rK   zWHERE r.player_id = ?a%  
            SELECT r.id, r.player_id, r.docente_id, r.score, r.comment, r.created_at,
                   p.name AS player_name, d.name AS docente_name
            FROM player_ratings r
            JOIN users p ON p.id = r.player_id
            JOIN users d ON d.id = r.docente_id
            z(
            ORDER BY r.id DESC
        N)rz   r  r?   r   r   r   rv  )	r/   r  rt   r   r8  r   r   r  r   s	   &&       r3   r  r  Q
  s     	!'	*BFE'c)n%	Dll   G 	  "%0AQ0 
 K 1 
 Ks0   AB*)B1BB
B*BB'	!	B*z/logoutc                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   g
  s     6 6' 6r5   c                 X   "   V P                   P                  4        \        R RR7      # 5i)rN  r   r   )r;   r<   r   rA   s   &r3   logoutr  f
  s"     OO55s   (*z/api/healthc                     "   R R/# 5i)r   r   r   r   r5   r3   healthr  k
  s     ds   )r   r   )r   r   c                   D   a  ] tR tRt o ]! ^^R7      tRtV 3R ltRtV t	R# )ValoracionItemis
  r  Nc                f   < V ^8  d   Qh/ S[ ;R&   S[ ;R&   S[ ;R&   S[;R&   S[S[ ,          ;R&   # )r.   area	subescala	indicadorr  observacionesr@  )r2   rA  s   "r3   r4   ValoracionItem.__annotate__s
  sC     
I N  N  "	 
 C=' r5   r   )
rC  rD  rE  rF  r   r  r  rG  rH  rI  rJ  s   @r3   r  r  s
  s      !"E#'M  r5   r  c                   ,   a  ] tR tRt o V 3R ltRtV tR# )ValoracionJugadorIniz
  c                B   < V ^8  d   Qh/ S[ ;R&   S[S[,          ;R&   # )r.   r  r  )r?   r   r  )r2   rA  s   "r3   r4    ValoracionJugadorIn.__annotate__z
  s     N  r5   r   Nrn  rJ  s   @r3   r  r  z
  ro  r5   r  z/api/valoraciones_jugadorc                0    V ^8  d   QhR\         R\        /# r  r   )r2   s   "r3   r4   r4   
  s     ' ' 'S 'r5   c                   "   \        V 4       \        4       ;_uu_ 4       pVP                  R V34      P                  4       pV Uu. uF  p\	        V4      NK  	  upuuRRR4       # u upi   + '       g   i     R# ; i5i)a  
            SELECT eval_id, created_at, docente_id, 
                   area, subescala, indicador, score, COALESCE(observaciones,'') AS observaciones,
                   (SELECT name FROM users WHERE id = docente_id) AS docente_name
            FROM valoraciones_jugador
            WHERE player_id = ?
            ORDER BY created_at DESC, eval_id, area, subescala, indicador
        N)require_docenter   r   r   rv  )r/   r  r   r   r   s   &&   r3   api_valoraciones_jugador_listr  
  si     G	D||  \ $8: 	 "&&AQ& 
 ' 
s.   B &A,A'A,B 'A,,A=	7	B c                0    V ^8  d   QhR\         R\        /# )r.   r/   r   r   )r2   s   "r3   r4   r4   
  s     +1 +1G +1c +1r5   c                 4  "   \        V 4       \        V 4      pR p \        VR,          4      pTe   T\        T4      8X  d   \        RRR7      h\        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P                  RT34        TP                  R	Y34        TP                  R
T34       TP                  RT34       TP                  RT34       TP                  RT34       TP                  RT34       TP                  RT34       TP                  RT34       TP                  RT34       R R R 4       RRR\        T4      /#   \         d>     \        \	        T4      P                  R4      4      p EL  \         d    R p  ELi ; ii ; i  \         d     ELi ; i  \         d     ELi ; i  \         d     Li ; i  + '       g   i     L; i5i)Nr   r   z%No puedes eliminar tu propio usuario.rM   z!SELECT id FROM users WHERE id = ?r   r   r   r   z*DELETE FROM user_profile WHERE user_id = ?z*DELETE FROM user_sports  WHERE user_id = ?z*DELETE FROM user_health  WHERE user_id = ?z*DELETE FROM user_consent WHERE user_id = ?z,DELETE FROM user_guardians WHERE user_id = ?z,DELETE FROM user_marketing WHERE user_id = ?z,DELETE FROM user_finance   WHERE user_id = ?r   r   Tdeleted)rZ   r[   r?   r   rv  rP   r	   r   rp   rq   r   r   r   )r/   r   rt   rL  r   r   s   &&    r3   api_users_deleter  
  s    '	g	BEBtH Uc'l24[\\	D";;ll>
KTTVC8PQQ	LLMPWzZ	LL\_f^pq		LLEzRLLEzRLLEzRLLEzRLLG'TLLG'TLLG'T 	5zB3 
6 $	3w<00I  	RT*+E 	E	"  		  		  		- 
s   HF 3H!AH.GG"BG4H.HG#F74H7G	GHG		GHGHGH"G1-H0G11H4H?HHHH	H)r	   r   c                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   
  s     
 
W 
r5   c                     \        V 4      pV'       g   \        R RR7      h VR,          pVR9  d   \        R RR7      hV#   \         d    \        TRR4      p L0i ; i)rL   zSe requiere rol docente.rM   rl   Nrx   )r[   r	   r   r  rs   s   &  r3   r  r  
  sh    	g	B4NOO)&z ''4NOOI	  )r64()s   	A AAc                $    V ^8  d   QhR\         /# rW   r1   )r2   s   "r3   r4   r4   
  s     ! ! !r5   c                     V P                   P                  R 4      ;'       g&    V P                   P                  R4      ;'       g    Rp\        W4       R# )rb   zX-Csrf-TokenrK   N)re   rP   rT   rf   s   & r3   require_csrf_headerr  
  s>    OO/\\7??3F3F~3V\\Z\E r5   c                0    V ^8  d   QhR\         R\        /# rL  )r   r  )r2   s   "r3   r4   r4   
  s     , ,7 ,EX ,r5   c                   "   \        V 4      p\        V 4       VP                  '       g   \        R RR7      h\        P
                  ! ^4      p\        4       ;_uu_ 4       pVP                  4       pVP                   F  pTP                  RY1P                  VR,          VP                  P                  4       VP                  P                  4       VP                  P                  4       \        VP                  4      VP                   ;'       g    RP                  4       ;'       g    R34       K  	  VP#                  4        RRR4       RRR	V/#   + '       g   i     L; i5i)
r   u   Sin �tems en la evaluaci�n.rM   z
                INSERT INTO valoraciones_jugador
                (eval_id, player_id, docente_id, area, subescala, indicador, score, observaciones)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?)
            r   rK   Nr   Teval_id)r  r  r  r	   r=   	token_hexr   r   r   r  r  rg  r  r  r?   r  r  r   )r/   rM  rt   r  r   r   its   &&     r3   api_valoraciones_jugador_creater  
  s    		!B ===4UVV"G	Dkkm--BKK 
 **BtH!3!3!5r||7I7I7KBHH 0 0 6 6B==?GG4	   	 
 $	7++ 
s%   AE& CE)EE&E#	E&)HTTP_403_FORBIDDENHTTP_404_NOT_FOUNDc                0    V ^8  d   QhR\         R\        /# )r.   r/   exc)r   StarletteHTTPException)r2   s   "r3   r4   r4   
  s     	M 	M' 	M8N 	Mr5   c                 b  "    \        V 4      pVP                  \        8X  d!   \        P                  RRV RV/\        R7      # VP                  \        8X  d!   \        P                  RRV RV/\        R7      # \        RVP                  /VP                  R7      #   \         d    R p Li ; i5i)Nz404.htmlr/   rY   )rN   z403.htmlrO   )	r[   r   rN   r  r\   r]   r  r   rO   )r/   r  user_ctxs   && r3   http_exception_handlerr  
  s     ( ,,))*y'6S[6\j|)}}
,,))*y'6S[6\j|)}}3::.COOLL  s(   B/B BB/B,)B/+B,,B/c                $    V ^8  d   QhR\         /# r   r   )r2   s   "r3   r4   r4     s      s r5   c                     \        4       ;_uu_ 4       pVP                  R V 34      P                  4       pVuuRRR4       #   + '       g   i     R# ; i)a  
            SELECT id, created_at, title, body, sender_id, recipient_id, reservation_id
            FROM notifications
            WHERE recipient_id=? AND COALESCE(is_read,0)=0 AND COALESCE(deleted_by_recipient,0)=0
            ORDER BY created_at DESC
        Nr:  )r   r   r   s   &  r3   r   r     sB    	D|| 
 Z
 " 	  
r   startupc                      \        4       ;_uu_ 4       p V P                  R 4       V P                  4        RRR4       \	        4         \        4       ;_uu_ 4       p T P                  R4       T P                  R4       RRR4       \        4        R#   + '       g   i     Ld; i  \         d     Lti ; i  + '       g   i     L@; i  \         d     LPi ; 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
            NzPRAGMA optimize;z PRAGMA wal_checkpoint(TRUNCATE);)r   r   r   r   r   r&  r   s    r3   
on_startupr    s    	WWLL  
 KKM  IWWLL+,LL;< 
 ! W   W  s]   B% "BB% 	C	 #B6>C	 B"	B% "B% %B32B36C	C	 C	 	CC)prod
productioni:	 >   PUTPOSTPATCHDELETE)r  NN)   r   )NNN>   rm   r  ry   >   seniorcadetesjuvenilalevinesbenjamin
infantilesprebenjamin>   	cancelada	pendienter  )NNNNN)fastapir   r   r   r   r   r   r	   fastapi.responsesr
   r   r   fastapi.staticfilesr   fastapi.templatingr   starlette.middleware.sessionsr   passlib.contextr   pydanticr   rp   pathlibr  retypingr   r   r   r   r   r   r   r   r   r   r   rp  rQ   r=   r@   r  r  r,  r3  urllib.parseurllibr%  r   appr  __file__resolveparentr  r   getenvrr   IS_PRODr>   
SECRET_KEYadd_middlewarer   rB   mountr\   rT   rP   r_   rd   rg   rZ   rz   r   r   r   r   r   r   r   postr   r   r   r   r   r   r   rv  r  r#  r&  r6  r[   r;  r>  rB  rF  rG  rS  rX  r[  ra  rb  rm  rq  rr  r|  r}  r  UPLOADS_DIRr  r  r  rf  rm   r  r;  r=  rS  deleterV  rW  r^  r  rz  rb  rk  rs  rv  r|  r  rI   r  r  r  r  r  r   patchr  r  r  r4  r=  rA  rK  rP  r   passlib.hashr)   ro  r   rt  r{  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  starlette.exceptionsr  starlette.statusr  r  exception_handlerr  r   on_eventr  r   r5   r3   <module>r     s   Q Q Q J J + . ; (    	   ( 1 1 * 8 8   ! !      6 6  !K <<!))+22
\
!
))Iu
%
+
+
-1G
GYY'(EEG,A,A",E
   %   H:&A5 		)[<8x	 Ho6	L 6_ 7_ 4%
AJ"
&k 
&9: 9:; ;;@00 , 	$\B& C& 
:<X Y$ 	%lC!& D!&J 	.tDT ET, 	+,aA+?@bQ34JK"4[ %d!$K@W -@WD

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