
    *i                       S SK JrJrJrJrJrJrJr  S SKJ	r	J
r
Jr  S SKJr  S SKJr  S SKJr  S SKJr  S SKJr  S SKrS SKrS SKrS SKrS S	KJr  S S
K Jr  S SKJrJr  S SKJrJrJ r J!r!  S SKJr  S SKJrJ"r"J#r#  S SKr$S S
K Jr  S SKJrJ%r%  S SK Jr  S SK&r&S SK'r'S SKJ%r%  S SK(r(S SK)r)S SK*r*S SK+r+S SK(r,S SK-r-S SK.r/S SKr0S SK.J1r1  \" SS9r2\Rf                  " \45      Rk                  5       Rl                  r7\7S-  r8\Rr                  " SS5      Ru                  5       S;   r;\Rr                  " S5      =(       d    \(Rx                  " S5      r=\2R}                  \\=S\;SSS9  \" S/S S!9r?S"\S#S4S$ jr@\2R                  S%\" S&S'9S(S)9  \" S*S'9rBS"\S+\CS-  4S, jrD\2R                  S-\	S.9S"\4S/ j5       rF1 S0krGS"\4S1 jrHS"\4S2 jrIS"\4S3 jrJS4 rKS5 rLS6 rMS7 rNS#\O4S8 jrPS#\Q4S9 jrRS:\O4S; jrS\2R                  S<S=S)9\" S>5      \" S5      4S"\S:\OS?\CS-  4S@ jj5       rUSA\C4SB jrVS:\O4SC jrW  GSSD\CSA\CSE\CSF\CSG\CS-  SH\CS-  4SI jjrX\2R                  SJ\S.9S"\4SK j5       rY\2R                  SL\S.9S"\SM\O4SN j5       rZ\2R                  SO\S.9S"\SP\O4SQ j5       r[\2R                  SR\\SS9S"\SP\O4ST j5       r]\2R                  SU5      \" SVSVSWSX9\" SYSVSZS[S\9\" S5      \" S5      \" S5      4S]\OS^\OS:\\O   S_\\O   S`\\C   4
Sa jj5       r^Sb r_GSSc\OS#\C4Sd jjr`S"\4Se jraSf rbS:\O4Sg jrcSh\O4Si jrdSh\OSj\O4Sk jre\2R                  SlSmS)9\" S>5      \" S5      \" S5      \" S5      4S"\SM\OS?\CS-  Sn\OS-  So\CS-  4
Sp jj5       rf\2R                  Sq\	S.9S"\4Sr j5       rg\2R                  Ss\	S.9S"\4St j5       rh\2R                  Su\	S.9S"\4Sv j5       ri\2R                  SwSx\	Sy9S"\4Sz j5       rj\2R                  SwS{\	Sy9\" S>5      \" S>5      4S"\SA\CSE\C4S| jj5       rk\2R                  S}S~\	Sy9S"\4S j5       rl\2R                  SS\	Sy9S"\4S j5       rm\2R                  S\SS9S:\OS"\4S j5       rn\2R                  SS\	Sy9S"\4S j5       ro\2R                  SS\	Sy9\" S>5      \" S>5      \" S>5      4S"\SD\CSA\CSE\C4S jj5       rp\2R                  SS\	Sy9S"\4S j5       rq\7S(-  S-  S-  rr\2R                  SSS)9S"\4S j5       rs\2R                  S\	S.9S"\4S j5       rt\2R                  S\	SS9S"\4S j5       ru\2R                  SS\	Sy9S"\4S j5       rv\2R                  S\	S.9S"\4S j5       rw\2R                  SS\	Sy9GSS"\S:\OS-  4S jj5       rxS SKJ%r%  \2R                  S\%\\   SS9   GSS"\S\\C   S\\C   S:\\O   4S jj5       ry " S S\5      rz\2R                  S\\SS9S"\S\z4S j5       r{\2R                  S\\SS9S"\S\O4S j5       r}\2R                  SSS)9\" S>5      \" S>5      \" S>5      \" S5      \" S5      \" S5      4S"\Sj\OS\CS\CS?\CS-  S\OS-  So\CS-  4S jj5       r~\2R                  S\SS9S"\4S j5       r1 Skr1 Skr " S S\5      r " S S\5      rS:\OSF\C4S jr1 Skr " S S\5      r\2R                  SSS)9S:\OS\S"\4S j5       r\2R                  S\SS9\" S5      \" S5      4S"\S\\C   SF\\C   4S jj5       r\2R                  SSS)9S:\OS\S"\4S j5       r\!\C\#" SS94   r\!\C\#" SS94   r " S S\5      r " S S\5      r " S S\5      rS r\2GR                  SO\\SS9S"\SP\OS\4S j5       r\2R                  S\\SS9S"\S\O4S j5       r1 Skr\2R                  S\\SS9S"\S\4S j5       r\2R                  S\%\\   SS9     GSS"\S\\C   S\\C   S:\\O   S`\\C   S_\\O   4S jj5       r\2R                  S\	S.9S"\4S j5       r\2R                  S\	S.9S"\4S j5       r\2R                  S\	S.9\" S>5      \" S>5      \" S5      \" S5      \" S5      \" S5      \" S5      \" S5      \" S>5      4	S"\SD\CSA\CS\CS\S\CS\CS\CS\CSo\C4S jj5       r\2R                  S\	S.9S"\4S j5       r S SKJr  SrS\CS#\C4S jrS\CS\CS#\Q4S jr\2R                  S\	S.9\" S>5      \" S>5      \" S>5      \" S>5      4S"\S\CS\CS\CSo\C4
S jj5       r " S S\5      r\2GR                  S\\SS9\" S>5      4S"\S:\OS\\4S jj5       rS SK J3r3  1 Skr\2GR                  S\\SS9\3" S>5      \" S>5      4S"\S:\OS\\4S jj5       r\2R                  S\SS9S"\S\4S j5       r\2R                  S\SS9\" S5      4S"\S\\O   4S jj5       r\2R                  S5      S"\4S j5       r\2R                  S5      S 5       rS GS KJrJ"r"  S GSKJ%r%Jr  S SK(r( " GS GS\5      r " GS GS\5      r\2R                  GS\\\   SS9\" S>5      4S"\S\O4GS jj5       r\2R                  S\\SS9S"\S:\O4GS j5       rS GS	K JrJr  S GS	K JrJr  S SKrS"\4GS
 jrS"\4GS jr\2R                  GS\\SS9S"\S\4GS j5       rS SKJr  S GSKJrJr  \2GRi                  \5      S"\GS\4GS j5       rS:\O4GS jr\2GRo                  GS5      GS 5       rg! \ a    Sr GNPf = f(      )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)prod
productionAPP_SECRET_KEY@   laxi:	 thelfpro_session)
secret_key	same_site
https_onlymax_agesession_cookiebcryptauto)schemes
deprecatedrequestreturnc                    U R                   R                  5         [        R                  " S5      U R                   S'   [        R                  " S5      U R                   S'   [	        [
        R
                  " 5       5      U R                   S'   g )N    sidcsrf
created_at)sessionclearsecretstoken_urlsafeinttimer0   s    /var/www/html/app/main.pyrotate_sessionr?   0   s]    OO$2226GOOE%33B7GOOF$'		$4GOOL!    z/staticz
app/static)	directorystatic)namezapp/templatestokenc                     U R                   R                  S5      nU(       a>  U(       a7  [        R                  " [	        U5      [	        U=(       d    S5      5      (       d
  [        SSS9eg )Nr5      u   CSRF token inválidostatus_codedetail)r7   gethmaccompare_digeststrr	   )r0   rD   sesss      r>   require_csrfrP   9   sO    ??v&DuD$7$7D	3u{PRCS$T$T4JKK %Ur@   z/contabilidad)response_classc                 f   #    [        U 5        [        U 5      n[        R                  SXS.5      $ 7f)Nzcontabilidad.htmlr0   user)require_admincurrent_user	templatesTemplateResponserS   s     r>   contabilidadrY   ?   s.     ' D%%&9w;]^^s   /1>   PUTPOSTPATCHDELETEc                 z    U R                   [        ;   a'  U R                  R                  S5      n[	        X5        g g )NX-CSRF-Token)methodUNSAFE_METHODSheadersrK   rP   r0   rD   s     r>   _enforce_csrf_if_unsaferd   H   s/    ~~'##N3W$ (r@   c                 2   [        U 5      nU(       d
  [        SSS9e[        U 5        [        U[        R
                  5      (       a  US   O[        UR                  SS5      5      =(       d    Sn[        U5      R                  5       S:w  a
  [        SSS9eU$ )	N  No autenticadorH   rolerF   adminrG   zSolo administradores	rV   r	   rd   
isinstancesqlite3RowrN   rK   lowerr0   merh   s      r>   rU   rU   M   s|    	g	B4DEEG$$R55BvJ3rvvfb?Q;RYWYD
4yG#4JKKIr@   c                 2   [        U 5      nU(       d
  [        SSS9e[        U 5        [        U[        R
                  5      (       a  US   O[        UR                  SS5      5      =(       d    Sn[        U5      R                  5       S;  a
  [        SSS9eU$ )	Nrf   rg   rH   rh   rF   docenteri   rG   Solo docentes o adminrj   ro   s      r>   require_docente_or_adminru   W   s}    	g	B4DEEG$$R55BvJ3rvvfb?Q;RYWYD
4y 444KLLIr@   c                  v   [         R                  " [        S SS9n [         R                  U l        U R                  S5        U R                  S5        U R                  S5        U R                  S5        U R                  S5        U R                  S5         U R                  S	5        U $ ! [         a     U $ f = f)
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;)rl   connectDB_PATHrm   row_factoryexecute	Exceptionconns    r>   get_connr   a   s    ??7DERD{{DLL,-LL-.LL/0LL./LL./LL./45 K  Ks   B* *
B87B8c                      [        5       $ N)r    r@   r>   _connr   p   s
    :r@   c                      U R                  SU S35      R                  5        Vs1 s H  o"S   iM	     sn$ s  snf ! [         a    [        5       s $ f = f)NzPRAGMA table_info()   )r|   fetchallr}   set)r   tablers      r>   _table_columnsr   s   sU    "ll-?wa+HIRRTUT!TUUU us   %= 8= = AAc                  4   [        5        n U R                  5       nUR                  S5        UR                  S5        UR                  S5      R                  5        Vs1 s H  o"S   iM	     nnSU;  a  UR                  S5        SU;  a  UR                  S5        S	U;  a  UR                  S
5        UR                  S5        UR                  S5        UR                  S5        UR                  S5        UR                  S5        UR                  S5        UR                  S5        UR                  S5        UR                  S5      R                  5        Vs1 s H  o"S   iM	     nnSU;  a"  UR                  S5        UR                  S5        SU;  a  UR                  S5        SU;  a  UR                  S5        SU;  a  UR                  S5        SU;  a  UR                  S5        SU;  a  UR                  S 5        S	U;  a  UR                  S!5        S"U;  a  UR                  S#5        S$U;  a  UR                  S%5        S&U;  a  UR                  S'5        S(U;  a  UR                  S)5        S*U;  a  UR                  S+5        UR                  S,5        UR                  S-5        UR                  S.5        UR                  S/5        UR                  S05        UR                  S15        UR                  S25        UR                  S35        UR                  S45        UR                  S55        UR                  S65        UR                  S75        UR                  S85        UR                  S95        UR                  S:5        UR                  S;5        UR                  S<5        UR                  S=5        UR                  S>5        UR                  S?5        U R	                  5         S S S 5        g s  snf s  snf ! , (       d  f       g = f)@Nz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)r   
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)r6   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 0rC   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 users)r   cursorr|   r   commit)r   cr   
cols_userscols_ress        r>   init_dbr   y   s   	DKKM			*+			  	 %&II.H$I$R$R$TU$Tqd$T
Uz)IIDEj(IICD*$II?@			 
 
	 	
		  	 	
		  	 	
		 
 
	 	
		 	 		 	
		 	 		 	
		  	 	
		  	( #$)),M"N"W"W"YZ"YQaD"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	O?-C0P	P+JP	?
P		
Pc                      [        5        n U R                  S5      R                  5       n[        US   =(       d    S5      sS S S 5        $ ! , (       d  f       g = f)Nz2SELECT COUNT(1) AS c FROM users WHERE role='admin'r   r   )r   r|   fetchoner;   )r   rows     r>   count_adminsr   ~  s;    	DllOPYY[3s8=q! 
s   6A
Ac                 $    [        U S   5      S:H  $ )Nrh   ri   )rN   )rp   s    r>   is_adminr     s    r&z?g%%r@   r   c                    U R                  SU45        U R                  SU45        U R                  SU45        U R                  SU45        U R                  SU45        U R                  SU45        U R                  SU45        g )N6INSERT 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))r|   )r   r   s     r>   _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jr@   z/admin/users/deleteadmin_delete_user.next_urlc                   #    [        U 5      nU(       d
  [        SSS9$ [        U5      (       d
  [        SSS9e[	        U5      nU(       d
  [        SSS9e[        US	   5      [        US	   5      :X  a
  [        S
SS9e[        5        n UR                  S5        UR                  SX45        UR                  SU45        UR                  SU45        UR                  SU45        UR                  5          S S S 5        U(       a5  [        U5      nUR                  S:X  a  UR                  S:X  a
  [        USS9$ [        SSS9$ ! [         a    UR                  5         e f = f! , (       d  f       Ns= f7f)N/login/  urlrI   rG   z&Solo un admin puede eliminar usuarios.rH     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 = ?rF   /admin)rV   r   r   r	   get_user_by_idr;   r   r|   r   r}   rollbackr   schemenetloc)r0   r   r   rp   targetr   ps          r>   r   r     sH     
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::  ==? 
s2   BE5E$	A-E7AE5E!!E$$
E2.E5r   c                     [        5        nUR                  SU 45      nUR                  5       sS S S 5        $ ! , (       d  f       g = f)Na"  
            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(?)
        r   r|   r   )r   r   curs      r>   get_user_by_emailr     s8    	Dll & X'( ||~+ 
	   #8
Ac                     [        5        nUR                  SU 45      nUR                  5       sS S S 5        $ ! , (       d  f       g = f)Na  
            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=?
        r   r   r   r   s      r>   r   r     s8    	Dll & Z'( ||~+ 
r   rC   passwordrh   r   r   c                    [         R                  U5      n[        5        n[        US5      n[        R
                  R                  5       R                  5       n	SU;   a  SU;   a  UR                  SXXiX4U45      n
OUR                  SXXiU45      n
U
R                  n[        X{5        UR                  5         S S S 5        g ! , (       d  f       g = f)N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 (?,?,?,?,?))pwd_contexthashr   r   dtr   utcnow	isoformatr|   	lastrowidr   r   )rC   r   r   rh   r   r   password_hashr   colsr6   r   uids               r>   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                    #    [        U 5      nU(       d
  [        SSS9e[        [        US   5      5      nS nU Vs/ s H
  oC" U5      PM     sn$ s  snf 7f)Nrf   rg   rH   r   c                 R    U R                  5        Vs0 s H  oX   _M	     sn$ s  snf r   )keysr   ks     r>   to_dict)api_notifications_unread.<locals>.to_dict  s#    QVVX6XqtGX666s   $)rV   r	   !get_unread_notifications_for_userr;   )r0   rp   rowsr   r   s        r>   api_notifications_unreadr     sQ     	g	B4DEE,SD];D6 $%1GAJ%%%s   ;AAAz./api/notifications/{notification_id}/mark-readnotification_idc           	      D  #    [        U 5      nU(       d
  [        SSS9eU R                  R                  S5      n[	        X5        [        5        nUR                  SU[        US   5      45        UR                  5         S S S 5        SS0$ ! , (       d  f       SS0$ = f7f)	Nrf   rg   rH   r_   zx
            UPDATE notifications
            SET is_read = 1
            WHERE id = ? AND recipient_id = ?
            r   okT)	rV   r	   rb   rK   rP   r   r|   r;   r   )r0   r   rp   rD   r   s        r>   api_notifications_mark_readr      s     	g	B4DEEOO/E 	D
 c"T(m,	
 	 
 $< 
 $<s   AB 1B B 
B
B z/api/reservations/{res_id}res_idc                   #    [        U 5      nU(       d
  [        SSS9e[        5        nUR                  SU45      R	                  5       nS S S 5        W(       d
  [        SSS9e[        U5      n[        US9$ ! , (       d  f       N3= f7f)Nrf   rg   rH   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 = ?
            r   zNo encontrada)content)rV   r	   r   r|   r   _reservation_row_to_dictr   )r0   r   rp   r   r   datas         r>   api_reservation_getr     s     	g	B4DEE	Dll& I)
* (*+ 	 
0 ODD#C(D%%9 
s   'B	"A8-B	8
BB	z#/api/reservations/{res_id}/students)response_modelc                 <  #    [        U 5      nU(       d
  [        SSS9e[        5        n[        R                  Ul        UR                  SU45      R                  5       nU(       d`  UR                  SU45      R                  5       nU(       a8  US   (       a.  UR                  SUS   45      R                  5       nU(       a  U/nS S S 5        W Vs/ s H  n[        US   5      US	   US
   S.PM     nnU[        U5      US.$ ! , (       d  f       NE= fs  snf 7f)Nrf   rg   rH   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 = ?r   rC   r   r   rC   r   )reservation_idcountstudents)rV   r	   r   rl   rm   r{   r|   r   r   r;   len)r0   r   rp   r   r   r   ur   s           r>   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[[VZQRs1T7|QvY7LVZH[$s8}(SS! 
 \s)   'DBDD"D5D
DDz /api/reservations/list/paginatedr   u   P�gina (1-based))gedescription
   d   u   Tama�o de p�gina)r   ler   pagesizer   r   c                 B    U S-
  U-  nS/n/ nUb"  UR                  S5        UR                  U5        Ub"  UR                  S5        UR                  U5        Ub"  UR                  S5        UR                  U5        SSR                  U5      -   n[        5        n	U	R                  SU 3[	        U5      5      R                  5       n
[        U
S	   =(       d    S
5      nU	R                  SU S3[	        U5      X4-   5      R                  5       nS S S 5        W Vs/ s H  n[        U5      PM     nnW(       a"  [        S[        R                  " X-  5      5      OSnUU UUUS.S.$ ! , (       d  f       N^= fs  snf ! [         a    e [         a    [        SSS9ef = f)Nr   z1=1user_id = ?docente_id = ?z
status = ?zWHERE  AND z'SELECT COUNT(*) AS c FROM reservations r   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 ?
                )r   r   totalpages)itemsmetai  zError interno listando reservasrH   )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                   r>   reservations_paginatedr  P  s   9W(d"  /MM'"!  !12MM*%  .MM&!w||M::	W9)Ef hj  	#+!,E<<   !( f.+, hj-  : 7;;d)!,d;38Atyy./a	
 	
? W: <   W4UVVWs1   BE? A5E)E? E:26E? )
E73E? ?Fc                      [        5        n U R                  S[        R                  R	                  5       R                  5       45        U R                  5         S S S 5        g ! , (       d  f       g = f)NzADELETE FROM "formulario-registro" WHERE used=0 AND expires_at < ?)r   r|   _dtr   r   r   r   r~   s    r>   purge_expired_temp_regsr    sG    	DX[^[g[g[n[n[p[z[z[|Z~ 
s   AA""
A0lengthc                 x  ^ [         R                  m SR                  U4S j[        U 5       5       5      n[	        5        nUR                  SU[        R                  R                  5       R                  5       45      R                  5       nU(       d  UsS S S 5        $  S S S 5        M  ! , (       d  f       N= f)NrF   c              3   P   >#    U  H  n[         R                  " T5      v   M     g 7fr   )_secretschoice).0_digitss     r>   	<genexpr>&generate_unique_pin.<locals>.<genexpr>  s     E}!hoof--}s   #&zQSELECT 1 FROM "formulario-registro" WHERE pin = ? AND used = 0 AND expires_at > ?)stringr  r  ranger   r|   r  r   r   r   r   )r  pinr   r   r  s       @r>   generate_unique_pinr    s    ]]F
ggEuV}EEW,,ccll))+5578 hj   W
   Ws   AB++
B9c                 p    U R                   R                  S5      nU(       d  g [        [        U5      5      $ )Nr   )r7   rK   r   r;   )r0   r   s     r>   rV   rV     s+    oo!!),G#g,''r@   c                      [        5        n U R                  S5      nUR                  5       sS S S 5        $ ! , (       d  f       g = f)NzCSELECT id, name, email FROM users WHERE role='alumno' ORDER BY namer   r|   r   )r   r   s     r>   get_studentsr!    s+    	Dll`a||~ 
s	   !6
Ac                     [        5        nUR                  SU 45      nUR                  5       sS S S 5        $ ! , (       d  f       g = f)Na  
            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
        r   r   s      r>   get_notifications_for_userr#    s8    	Dll 	 Z	 ||~ 
r   	sender_idc                     [        5        nUR                  SU 45      nUR                  5       sS S S 5        $ ! , (       d  f       g = f)Na  
            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
        r   )r$  r   r   s      r>   get_notifications_sent_by_userr&    s8    	Dll 	 \	 ||~ 
r   recipient_idc                     [        5        nUR                  SX45      nUR                  5       sS S S 5        $ ! , (       d  f       g = f)Na  
            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
        r   )r$  r'  r   r   s       r>   &get_notifications_sent_by_user_to_userr)    s9    	Dll  &( ||~ 
r   z/notificaciones/eliminardelete_notificationtarget_recipient_idr5   c                 |  #    [        U 5      nU(       d
  [        SSS9$ [        X5        [        5        nUR	                  SU45      R                  5       nU(       d
  [        SSS9e[        US   5      nUS	   b  [        US	   5      OS n	[        US
   5      n
X:X  a$  UR	                  SU45        UR                  5         OU	bO  X:X  aJ  Ub#  [        U5      U
:X  a  UR	                  SU45        OUR	                  SU45        UR                  5         OIUS   S;   a6  Ub3  [        U5      U
:X  a$  UR	                  SU45        UR                  5         O
[        SSS9eS S S 5        U(       a5  [        U5      nUR                  S:X  a  UR                  S:X  a
  [        USS9$ [        SSS9$ ! , (       d  f       NT= f7f)Nr   r   r   zBSELECT id, sender_id, recipient_id FROM notifications WHERE id = ?r   u   Notificaci�n no encontrada.rH   r   r$  r'  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 = ?rh   rr   rG   u'   No puedes eliminar esta notificaci�n.rF   /notificaciones)rV   r   rP   r   r|   r   r	   r;   r   r   r   r   )r0   r   r   r+  r5   rp   r   r   me_idr$  r'  parseds               r>   r*  r*    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   2F<D)F+AF<+
F95F</c                 P   #    [        U 5      n[        R                  SXS.5      $ 7f)Nz
index.htmlrS   rV   rW   rX   r0   rp   s     r>   homer4    %     	g	B%%l4TUU   $&z/aboutc                 P   #    [        U 5      n[        R                  SXS.5      $ 7f)Nz
about.htmlrS   r2  r3  s     r>   aboutr8  
  r5  r6  z
/ticketingc                 N   #    [         R                  SU [        U 5      S.5      $ 7f)Nzticketing.htmlrS   )rW   rX   rV   r=   s    r>   	ticketingr:    s%     %%&6GUabiUj8klls   #%r   login)rC   rQ   c                 <   #    [         R                  SU S S.5      $ 7f)N
login.htmlr0   error)rW   rX   r=   s    r>   	login_getr@    s     %%lRV4WXXs   
login_postc                   #    UR                  5       R                  5       n[        U5      nU(       a  [        R	                  X$S   5      (       d  [
        R                  SU SS.5      $ [        U 5        [        US   5      U R                  S'   US   U R                  S'   US   S:X  d  US	:X  a  [        U R                  S5      S
S9$ US   S:X  a  [        U R                  S5      S
S9$ [        U R                  S5      S
S9$ 7f)Nr   r=  u   Credenciales inv�lidasr>  r   r   rh   ri   admin@admin.esr   r   rs   	dashboard)striprn   r   r   verifyrW   rX   r?   r;   r7   r   url_for)r0   r   r   
email_normrT   s        r>   rA  rA    s     $$&JZ(D{))(4IJJ)),GVp8q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/docenters   c                    #    [        U 5      nU(       d  [        U R                  S5      SS9$ / n US   S;   a
  [        5       n[
        R                  SU UUS.5      $ ! [         a    / n N(f = f7f)Nr;  r   r   rh   rr   zdocente.html)r0   rT   r   )rV   r   rG  r!  r}   rW   rX   )r0   rp   r   s      r>   docente_dashboardrJ  '  s     	g	BGOOG$<#NNHf:--#~H %% 	
   s(   .A0A A0A-*A0,A--A0z/valoracionesvaloracionesc                 2  #    [        U 5      nU(       d  [        U R                  S5      SS9$ SUR                  5       ;   a  [	        US   5      R                  5       OSnUS;  a  [        U R                  S5      SS9$ [        R                  SXS	.5      $ 7f)
Nr;  r   r   rh   rF   rr   rD  zvaloraciones.htmlrS   )rV   r   rG  r   rN   rn   rW   rX   ro   s      r>   valoraciones_pagerM  ;  s     	g	BGOOG$<#NN&,	&93r&z?  "rD''GOOK$@cRR%%&9w;[\\s   BBz/api/users/{user_id}api_user_detail)rQ   rC   c                 *  #    [        U5      nU(       d
  [        SSS9$ US   S;  a
  [        SSS9e[        5        nUR	                  S	U 45      R                  5       nS S S 5        W(       d
  [        S
SS9e[        U5      $ ! , (       d  f       N*= f7f)Nr   r   r   rh   rr   rG   rt   rH   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 = ?
        r   Usuario no encontrado)rV   r   r	   r   r|   r   dict)r   r0   rp   r   r   s        r>   rN  rN  E  s     	g	BH#>>	&z--4KLL	Dll * Z+* "+ 	 
. 4KLL93 
s   :B"B$B
BBz	/registerregisterc                 r   #    [        U 5      nU=(       d    SSSS.n[        R                  SU S US.5      $ 7f)NrF   rC   r   r   register.htmlr0   r?  rT   r2  )r0   rp   ctx_users      r>   register_getrX  g  s<     	g	B;b2;H%%o7UYck7lmm   57register_postc           	      X  #    UR                  5       R                  5       n[        U5      (       a,  [        R	                  SU SUR                  5       USS.S.5      $ [        U5      S:  a,  [        R	                  SU SUR                  5       USS.S.5      $ [        UR                  5       XCSS	9  [        U5      n[        US
   5      U R                  S'   US   U R                  S'   US   S:X  d  US:X  a  [        U R                  S5      SS9$ [        U R                  S5      SS9$ 7f)NrU  zEse email ya existerF   rT  rV     u(   La contrase�a debe tener 6+ caracteresalumno)rh   r   r   rh   ri   rC  r   r   rD  )rE  rn   r   rW   rX   r   r   r;   r7   r   rG  )r0   rC   r   r   rH  rT   s         r>   rZ  rZ  m  s:    $$&J$$))*?RVR\R\R^is  A  JB  C
 	
 8}q))*Tgkgqgqgs  I  TV  _W  X
 	
 

jBZ(D!$T$ZGOOI"6lGOOFF|w*0@"@GOOG$<#NNGOOK$@cRRs   D(D*z/academy-registeracademy_register_getc                 P   #    [        U 5      n[        R                  SXS.5      $ 7f)Nzacademy-register.htmlrS   r2  r3  s     r>   r^  r^    s+     	g	B%%( r6  uploadsacademyacademy_register_postc                   ^ #    [        S5        [        S5        [        S5        U R                  5       I S h  vN n[        S[        UR                  5       5       35        [        SSU;    35        UR	                  S5      =(       d    SR                  5       R                  5       nUR	                  S5      =(       d    SR                  5       nUR	                  S	5      =(       d    SnUR	                  S
5      =(       d    SR                  5       nUR	                  S5      =(       d    SR                  5       n[        SU SU SU SU 35        U(       d
  [        SSS9eU(       a  [        U5      S:  a
  [        SSS9eU(       a  [        U5      S:  a
  [        SSS9eU(       a  [        U5      S:  a
  [        SSS9eU(       a  [        U5      S:  a
  [        SSS9e[        U5      nU(       a
  [        SSS9eS nS n	UR	                  S5      n
[        S[        U
5       35        [        U
S5      =(       a    [        U
S5      n[        SU 35        U(       a  [        SU
R                   35        U(       a  U
R                  (       a   U
R                  5       I S h  vN n[        S U(       a  [        U5      OS! 35        U(       aN  [        R                  R!                  U
R                  5      S"   R                  5       =(       d    S#n	[        S$5        [)        UR                  5       X$S&XVS'9  [        U5      n[+        US(   5      nS nU(       a  U	(       a~   [,        S)-  S*-  nUR/                  S+S+S,9  S-U U	 3nUU-  n[        S.U 35        [1        US/5       nUR3                  U5        S S S 5        [        S0U 35        S1U 3n[        S2U 35        0 m UR5                  5        H3  u  nn[7        U[8        5      (       a  M  US4;  d  M%  [;        U5      T U'   M5     U 4S5 jnU" S6S75      U" S85      U" S9S:5      U" S;5      U=(       d	    U" SS<5      S=.nU" S>S?S@5      U" SA5      U" SBSCSD5      U" SE5      U" SF5      U" SG5      U" SH5      U" SISJSK5      SL.nU" SM5      U" SN5      U" SO5      U" SP5      U" SQ5      U" SR5      U" SS5      ST.nU" SU5      U" SV5      U" SW5      U" SX5      U" SY5      SZ.nU" S[5      U" S\S]5      U" S^S_5      U" S`Sa5      Sb.nU" ScSd5      U" Se5      U" SfSg5      U" ShSi5      Sj.n[=        5        n[?        UU5        [A        Sk URC                  5        5       5      (       a_  SlRE                  UR                  5        Vs/ s H  nU SmU Sn3PM     sn5      nURG                  SoU Sp3/ URC                  5       QUP75        [A        Sq URC                  5        5       5      (       a_  SlRE                  UR                  5        Vs/ s H  nU SmU Sn3PM     sn5      nURG                  SrU Sp3/ URC                  5       QUP75        [A        Ss URC                  5        5       5      (       a_  SlRE                  UR                  5        Vs/ s H  nU SmU Sn3PM     sn5      nURG                  StU Sp3/ URC                  5       QUP75        [A        Su URC                  5        5       5      (       a_  SlRE                  UR                  5        Vs/ s H  nU SmU Sn3PM     sn5      nURG                  SvU Sp3/ URC                  5       QUP75        [A        Sw URC                  5        5       5      (       a_  SlRE                  UR                  5        Vs/ s H  nU SmU Sn3PM     sn5      nURG                  SxU Sp3/ URC                  5       QUP75        [A        Sy URC                  5        5       5      (       a_  SlRE                  UR                  5        Vs/ s H  nU SmU Sn3PM     sn5      nURG                  SzU Sp3/ URC                  5       QUP75        URI                  5         S S S 5        [        S5        [        S{5        [        S5        [K        S+S|S}.5      $  GN| GN! ["         a-  n[        S%U 35        S!S KnUR'                  5          S nAGNS nAff = f! , (       d  f       GNF= f! ["         a-  n[        S3U 35        S!S KnUR'                  5          S nAGNZS nAff = fs  snf s  snf s  snf s  snf s  snf s  snf ! , (       d  f       N= f7f)~NzP================================================================================z,DEBUG: academy_register_post function calledzDEBUG: Form keys: zDEBUG: Form has playerPhoto: playerPhotor   rF   rC   r   	firstNamelastNamezDEBUG: email=z, name=z, first_name=z, last_name=r   zEl email es obligatorio.rH      zIndica tu nombre.zIndica tus apellidos.u(   Indica tu nombre (mínimo 2 caracteres).r\  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: r   r   .jpgz<DEBUG: Photo stored in memory, will save after user creationzERROR: Failed to read photo: r]  )rh   r   r   r   rB   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: NrF   nullc                  N   > U  H  nTR                  U5      nUS;  d  M  Us  $    g )Nrq  )rK   )r   r   valr   s      r>   pick#academy_register_post.<locals>.pick  s-    A((1+C,,
  r@   r   whatsappdni	birthDate
birth_datecityavatar)r   rx  rz  r{  r|  currentTeamteamclubcategorycurrentPositionpreferredPositionpositiondominantFoot	strengths
weaknessestrainingTypeinjuriesinjuryHistoryinjury_history)r~  r  r  dominant_footr  r  training_typer  physicalWorkphysicalWorkDetailssmokingalcoholrecovery	chestPain
discomfort)physical_workphysical_work_detailsr  r  r  
chest_painr  whatsappContentvideoPermissionprivacyAcceptancedataConfirmation	agreement)whatsapp_contentvideo_permissionprivacy_acceptancedata_confirmationr  
occupation
studyPlacestudy_place
parentNameparent_nameparentEmailparent_email)r  r  r  r  foundUsfound_us	enjoymentnervesConfidencenerves_confidenceadditionalCommentsadditional_comments)r  r  r  r  c              3   (   #    U  H  oS Lv   M
     g 7fr   r   r  vs     r>   r  (academy_register_post.<locals>.<genexpr>       <&;}&;   , z=COALESCE(?, r   zUPDATE user_profile SET z WHERE user_id=?c              3   (   #    U  H  oS Lv   M
     g 7fr   r   r  s     r>   r  r         ;&:}&:r  zUPDATE user_sports SET c              3   (   #    U  H  oS Lv   M
     g 7fr   r   r  s     r>   r  r    r  r  zUPDATE user_health SET c              3   (   #    U  H  oS Lv   M
     g 7fr   r   r  s     r>   r  r    r  r  zUPDATE user_consent SET c              3   (   #    U  H  oS Lv   M
     g 7fr   r   r  s     r>   r  r         >&=}&=r  zUPDATE user_guardians SET c              3   (   #    U  H  oS Lv   M
     g 7fr   r   r  s     r>   r  r    r  r  zUPDATE user_marketing SET zHDEBUG: About to return JSON response: {'ok': True, 'redirect': '/login'}r   )r   redirect)&printformlistr   rK   rE  rn   r	   r   r   typehasattrri  rj  ospathsplitextr}   	traceback	print_excr   r;   BASE_DIRmkdiropenwriter   rk   r   rN   r   r   anyvaluesr  r|   r   r   )!r0   r  r   rC   r   r   r   existingphoto_content	photo_extplayer_photo	is_uploader  rT   r   avatar_pathuploads_dirri  	file_pathfr   r  ru  profile_valssports_valshealth_valsconsent_valsguardians_valsmarketing_valsr   setsr   s!                                   @r>   rb  rb    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SglF6SI	.yk
:;.|/D/D.EFG\**		""."3"3"55M+-C,>UV+WXYGG,,\-B-BCAFLLN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*E{;5V>mX!>L ]FF3$*,?Ln-+&<(n-z?<LM	K n-!%&;!<	?	?$;'<(K !!23 !23"#67!"45+&L <(L-8L-8]N;	N J/+&!"46IJ#$8:OP	N 
D w/<l&9&9&;<<<99|?P?P?RS?R!=15?RSTDLL3D69IJLmlNaNaNcLmelLmn;k&8&8&:;;;99{?O?O?QR?Q!=15?QRSDLL24&8HIKk[M_M_MaKkcjKkl;k&8&8&:;;;99{?O?O?QR?Q!=15?QRSDLL24&8HIKk[M_M_MaKkcjKkl<l&9&9&;<<<99|?P?P?RS?R!=15?RSTDLL3D69IJLmlNaNaNcLmelLmn>n&;&;&=>>>99~?R?R?TU?T!=15?TUVDLL5dV;KLNqP^PePePgNqipNqr>n&;&;&=>>>99~?R?R?TU?T!=15?TUVDLL5dV;KLNqP^PePePgNqipNqr) 
* 
&M	
TU	&Mt:;;i  B 6
  	"1!56!!	"& '&
  	"9!=>!!	"B T S S T V V% 
s  5e/b4Ie/b: #b7$A9b: Ae/!Ad #c45)d 3e/D3e/Aee 
)A2ee
-A2ee

1A2e#e
5A2e'e
9A2e+e
=A e=8e/7b: :
c1"c,&e/,c11e/4
d>d 
d="d82e/8d==e/ e
e,(e/z/info-usuariosc                    #    [        U 5      nU(       d  [        U R                  S5      SS9$ [        R	                  SU US.5      $ 7f)Nr;  r   r   zinfo-usuarios.htmlrS   )rV   r   rG  rW   rX   r3  s     r>   info_usuarior  *  sI     	g	BGOOG$<#NN%%&:=  s   AAz/gestion-usuariosgestion_usuariosc                   #    [        U 5      nU(       d  [        U R                  S5      SS9$ [        U[        R
                  5      (       a  [        U5      n[        [        U[        5      (       a  UR                  S5      OUS   =(       d    S5      R                  5       nUS:w  a  [        U R                  S5      SS9$ [        5        nUR                  S5      nUR                  5        Vs/ s H  n[        U5      PM     nnS S S 5        [        R                  S	U UWS
.5      $ s  snf ! , (       d  f       N-= f7f)Nr;  r   r   rh   rF   ri   rD  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
        zgestion-usuarios.html)r0   rT   r   )rV   r   rG  rk   rl   rm   rQ  rN   rK   rn   r   r|   r   rW   rX   )r0   rp   rh   r   r   r   r   s          r>   r  r  4  s    	g	BGOOG$<#NN"gkk"""X*R"6"6vBvJM2NTTVDwGOOK$@cRR	Dll   #&,,.1.Qa.1 
 %%	
  2 
s0   C
D?$D.0D)D."D?)D..
D<8D?z
/dashboardrD  c                   #    [        U 5      nU(       d  [        U R                  S5      SS9$ [        U[        R
                  5      (       a  [        US   5      O[        UR                  S5      5      n[        U[        R
                  5      (       a  US   OUR                  S5      =(       d    SR                  5       n[        5        nUR                  SX"U45      R                  5       n[        U(       a  US   b  US   OS	5      nS S S 5        [        R                  S
U UWS.5      $ ! , (       d  f       N(= f7f)Nr;  r   r   r   r   rF   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   r   zdashboard.htmlr0   rT   reservation_count)rV   r   rG  rk   rl   rm   r;   rK   rE  r   r|   r   rW   rX   r0   rp   r.  me_emailr   r   r  s          r>   rD  rD  Y  s    	g	BGOOG$<#NN'GKK88C4Mc"&&,>OE)"gkk::7w@USU\\^H	Dll  H%' (0xz 	  CCH4HCaP 
 %%!2	
  
s   C	D>A D-"D>-
D;7D>r   c                 r   #    [        U 5      nU(       d
  [        SSS9$ [        R                  SXS.5      $ 7f)Nr   r   r   z
admin.htmlrS   )rV   r   rW   rX   rS   s     r>   ri   ri   s  s5      DH#>>%%l4VWWrY  r-  notificacionesc                   #    [        U 5      nU(       d
  [        SSS9$ [        US   5      nS nUb<   [        U5      nU(       a)  US   S;   a   [	        U5      nU(       a  [        US   5      n[        U5      n/ nUS   S;   a7  U(       a  [        [        US   5      U5      nO[        [        US   5      5      n/ nUS   S;   a
  [        5       nS nU=(       d    /  V	s/ s H
  o" U	5      PM     n
n	/ n0 n/ nU(       a  [        5        nUR                  SU45      R                  5       nS S S 5        U=(       d    /  Vs/ s H
  o" U5      PM     nnU=(       d    /  Vs0 s H  n[        US   5      U" U5      _M     nn[        R                  S	U UU(       a  [        U5      OS UUUU
UUUS
.
5      $ ! [         a    S n GNf = fs  sn	f ! , (       d  f       N= fs  snf s  snf 7f)Nr   r   r   r   rh   rr   c                      U R                  5        Vs0 s H  oX   _M	     sn$ s  snf ! [         a    [        U 5      s $ f = fr   )r   r}   rQ  r   s     r>   _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.html)
r0   rT   	view_usernotificationssent_notificationsr   notifications_jsonappointmentsappointments_jsonappointments_map)rV   r   r;   r}   r   r#  r)  r&  r!  r   r|   r   rW   rX   rQ  )r0   r   rp   target_user_idr  inboxsentr   r  nr  r  r  r  r   as                   r>   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:KRKAKa,q/KALW<< )
 !"$
 %-HJ   8D7Ir7IK7I\!_7IKDPDVTVDVXDVaC$L,q/9DVX%%,5i4""& "4(!2 0	
 G  	G	* B
 W LXsd   0G(F5 B"G( G1G(
"G,G(GG(!G# 5G(5GG(GG(
GG(z/api/expenses	date_fromdate_toc                 (  #    [        U 5        S[        4S jn/ n/ nU(       a*  U" U5        UR                  S5        UR                  U5        U(       a*  U" U5        UR                  S5        UR                  U5        Ub+  UR                  S5        UR                  [        U5      5        SnU(       a  USSR	                  U5      -   -  nUS	-  n[        5        n[        R                  Ul        UR                  U[        U5      5      R                  5       n	/ n
U	 HS  nU
R                  US
   US   US   US   US   US   US   [        US   =(       d    S5      US   US   US   S.5        MU     U
sS S S 5        $ ! , (       d  f       g = f7f)Nsc                 l     [         R                  " U S5        g ! [         a    [        SSU  S3S9ef = f)N%Y-%m-%dr   u   Fecha inv�lida: z (YYYY-MM-DD)rH   r   strptimer}   r	   r  s    r>   _ok_date#api_expenses_list.<locals>._ok_date  s@    	_a, 	_C:LQC}8]^^	_    3zjg.date >= ?zjg.date <= ?z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   r6   dater   	user_name
user_emailr   amount_centsr   r  conceptr   )r   r6   r  r   r  r  r   r	  r  r
  r   )rU   rN   r  r;   r  r   rl   rm   r{   r|   r  r   )r0   r  r  r   r  wherer	  sqlr   r   outr   s               r>   api_expenses_listr    st     '_C _ EFU\\.96==;S5<<7w9O%&c'l(CC  y7<<...--C	D";;||Cv/88:AJJgo&	Y<{^o"#$4"5 #An$5$: ;jMY<7   % 
s   CFBF7
F
FFc                       \ rS rSr% \\S'   \" SS9r\\S'   Sr	\
\   \S'   Sr\
\   \S'   Sr\
\   \S	'   Sr\
\   \S
'   Sr\
\   \S'   Srg)	ExpenseIni  r  r   r   r	  Nr  r
  r   r   r   r   )__name__
__module____qualname____firstlineno__rN   __annotations__r   r	  r;   r  r   r
  r   r   r   __static_attributes__r   r@   r>   r  r    s[    
IL##"Hhsm"!GXc]!E8C=!GXc]!$(NHSM(r@   r  payloadc                 n  #    [        U 5         [        R                  " UR                  S5        [        R                  " 5       R                  S5      n[        5        nUR                  SUUR                  R                  5       UR                  b  [        UR                  5      OS UR                  (       a  [        UR                  5      OS [        UR                  =(       d    S5      UR                  =(       d    SR                  5       =(       d    S UR                   =(       d    SR                  5       =(       d    S UR"                  =(       d    SR                  5       =(       d    S 45      nUR$                  nS S S 5        S	WS
.$ ! [         a    [        SSS9ef = f! , (       d  f       N+= f7f)Nr  r   u   Fecha inválida (YYYY-MM-DD).rH   %Y-%m-%d %H:%M:%Sz
            INSERT INTO jugadores_gastos (created_at, date, user_id, reservation_id, amount_cents, category, concept, notes)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        r   rF   Tr   r   )rU   r   r   r  r}   r	   nowstrftimer   r|   rE  r   r;   r   r	  r  r
  r   r   )r0   r  r6   r   r   gids         r>   api_expenses_creater     sK    'U',,
3 (()<=J	Dll  LL $+OO$?C T+2+A+AC&&'t$$)*#**,4__"))+3t]] b'')1T	
 mm 
 c""%  U4STTU 
s4   F5!F .F5D!F$?F5F!!F5$
F2.F5z/api/expenses/{gid}r  c                    #    [        U 5        [        5        nUR                  SU45        S S S 5        SS0$ ! , (       d  f       SS0$ = f7f)Nz)DELETE FROM jugadores_gastos WHERE id = ?r   T)rU   r   r|   )r0   r  r   s      r>   api_expenses_deleter!  9  sE     '	D@3&I 
$< 
$<s   A8A
A	
Acreate_notificationr   bodyr   c           
      j  #    [        U 5      nU(       d
  [        SSS9$ US   S;  a
  [        SSS9e[        X5        U=(       d    S	R	                  5       nU=(       d    S	R	                  5       nU(       a  U(       d
  [        S
SS9e [        U5      nS nUb  [        U5      R	                  5       S	:w  aw   [        U5      n[        5        n	U	R                  SU45      R                  5       n
U
(       d
  [        SSS9e[        U
S   =(       d    S5      U:w  a
  [        S
SS9e S S S 5        [        5        n	U	R                  S[        R                  R                  5       R                  5       [        US   5      XX845        U	R                  5         S S S 5        U(       a5  [!        U5      nUR"                  S	:X  a  UR$                  S	:X  a
  [        USS9$ [        SSS9$ ! [         a    [        S
SS9ef = f! [         a    [        S
SS9ef = f! , (       d  f       N= f! , (       d  f       N= f7f)Nr   r   r   rh   rr   rG   z3Solo docentes o admin pueden enviar notificaciones.rH   rF   r   u$   T�tulo y mensaje son obligatorios.u   Destinatario inv�lido.u   Reserva inv�lida.z1SELECT id, user_id FROM reservations WHERE id = ?r   Reserva no encontrada.r   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   r-  )rV   r   r	   rP   rE  r;   r}   rN   r   r|   r   r   r   r   r   r   r   r   r   )r0   r'  r   r#  r   r   r5   rp   res_id_to_saver   resr/  s               r>   r"  r"  A  s     
g	BH#>>	&z--4ijj[b!EJBD4Z[[P<( N!c.&9&?&?&AR&G	O 0N W,,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W 
si   BH3G! "H36G9 
H3AH$H36AH"AH3!G66H39HH3
HH3"
H0,H3z/api/teachersapi_teachersc                   #    [        U 5      nU(       d
  [        SSS9$ [        5        nUR                  S5      nUR	                  5        Vs/ s H  n[        U5      PM     nnS S S 5        U$ s  snf ! , (       d  f       W$ = f7f)Nr   r   r   z\SELECT id, name, email, created_at, role FROM users WHERE role = 'docente' ORDER BY name ASC)rV   r   r   r|   r   rQ  )r0   rT   r   r   r   r   s         r>   r(  r(  w  sv      DH#>>	Dllj
 "%0AQ0	 

 K 1	 

 Ks.   'B$A3A."A3$
B.A33
B=B>   ri   r]  rs   >   seniorcadetesjuvenilalevinesbenjamin
infantilesprebenjaminc                   *    \ rS rSr% Sr\\   \S'   Srg)CategoryUpdatei  Nr  r   	r  r  r  r  r  r   rN   r  r  r   r@   r>   r2  r2        "Hhsm"r@   r2  c                        \ rS rSr% \\S'   Srg)
RoleUpdatei  rh   r   N)r  r  r  r  rN   r  r  r   r@   r>   r6  r6    s    
Ir@   r6  c                     [        5        nUR                  SX45        UR                  5         S S S 5        g ! , (       d  f       g = f)N&UPDATE users SET role = ? WHERE id = ?)r   r|   r   )r   rh   r   s      r>   set_user_roler9    s-    	D=O 
s	   $8
Ac                   *    \ rS rSr% Sr\\   \S'   Srg)r2  i  Nr  r   r3  r   r@   r>   r2  r2    r4  r@   z/api/users/{user_id}/categoryapi_users_set_categoryc                   #    [        U5        [        U 5      nU(       d
  [        SSS9eUR                  =(       d    SR	                  5       R                  5       nU(       a  U[        ;  a
  [        SSS9e[        5        nUR                  SU 45        UR                  SU(       a  UOS U 45        UR                  5         S S S 5        S	XS
.$ ! , (       d  f       N= f7f)Nr   rP  rH   rF   r   u   Categoría no válidar   z5UPDATE user_sports SET category = ? WHERE user_id = ?T)r   r   r  )
rU   r   r	   r  rE  rn   ALLOWED_CATEGORIESr   r|   r   )r   r  r0   r   catr   s         r>   r;  r;    s     'G$F4KLL!r
(
(
*
0
0
2C
s,,4KLL	DLwjYLVYs_celNmn 
 7<<	 
s   A>C ACC
CCz
/api/users	api_usersrolesc                   #    [        U 5      nU(       d
  [        SSS9$ / nU(       aT  UR                  S5       Vs/ s H7  oUR                  5       (       d  M  UR                  5       R	                  5       PM9     nnO&U(       a  UR                  5       R	                  5       /nSn/ nU(       a4  SR                  S[        U5      -  5      nSU S3nUR                  U5        [        5        n	U	R                  S	U S
3U5      n
U
R                  5        Vs/ s H  n[        U5      PM     nnS S S 5        U$ s  snf s  snf ! , (       d  f       W$ = f7f)Nr   r   r   ,rF   ?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
        )rV   r   splitrE  rn   r  r   extendr   r|   r   rQ  )r0   r@  rh   rT   
roles_listr   r  r	  placeholdersr   r   r   s               r>   r?  r?    s/      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 KsA   9ED5"D59A2E+)D?D:)D?+E:D??
E	Ez/api/users/{user_id}/roleapi_users_set_rolec                   #    [        U5        [        U 5      nU(       d
  [        SSS9eUR                  =(       d    SR	                  5       R                  5       nU[        ;  a
  [        SSS9e[        US   5      R                  5       nUS:H  nU=(       a    US:g  nXT:X  a  S	XS
S.$ U(       a  [        5       nUS::  a
  [        SSS9e[        X5        S	XS	S.$ 7f)Nr   rP  rH   rF   r   u   Rol inv�lidorh   ri   TF)r   r   rh   changedr   uU   Debe existir al menos un usuario con rol admin. No puedes degradar al �ltimo admin.)
rU   r   r	   rh   rE  rn   ALLOWED_ROLESrN   r   r9  )	r   r  r0   r   new_rolecurrent_role	was_adminis_demoting_adminadmins_counts	            r>   rH  rH    s     'G$F4KLL"))+113H}$4DEEvf~&,,.L'I!9h'&9wUSS#~1n  '$7NNs   CCz^\d{4}-\d{2}-\d{2}$)patternz^\d{2}:\d{2}$c                      \ rS rSr% \\S'   \\S'   \" SSSS9r\	\S'   \" S	S	S
9r
\	\S'   \" \S9r\\	   \S'   Sr\\	   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\	   \S'   Sr\\S'   Srg)ReservationIni  r  r<   <        r   r   r   r   r  r   )default_factoryuser_idsNr   rC   r   r   
confirmadar   r   r   Fr   r   )r  r  r  r  DateStrr  TimeStrr   r   r;   r   r  rY  r   r   r   rC   rN   r   r   r   r   r   r   boolr  r   r@   r>   rS  rS    s    
M
M!"u5c5Q1~K%5Hd3i5!GXc]!D(3-E8C=E8C=(FHSM(E8C= $J$D$r@   rS  c                   6   \ rS rSr% Sr\\   \S'   Sr\\	   \S'   \
" SSSS9r\\   \S'   \
" SS	S
9r\\   \S'   Sr\\\      \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Sr\\   \S'   Srg)ReservationUpdatei  Nr  r<   rU  rV  rW  r   r   r  r   rY  r   rC   r   r   r   r   r   r   r   )r  r  r  r  r  r   r[  r  r<   r\  r   r   r;   r   rY  r   r   rC   rN   r   r   r   r   r   r   r]  r  r   r@   r>   r_  r_    s    "D(7
""D(7
"&+DQ5&AhsmA!&t!2K#2$(HhtCy!(!GXc]!D(3-E8C=E8C= FHSM E8C= $J$D(4.r@   r_  c                   L    \ rS rSr% \\S'   \" SSS9r\\S'   Sr\	\
   \S'   S	rg)
RatingIni  	player_idr   rU  rW  scoreNcommentr   )r  r  r  r  r;   r  r   rc  rd  r   rN   r  r   r@   r>   ra  ra    s&    N!"E3"!GXc]!r@   ra  c                    U S   U S   U S   U S   U S   [        U S   =(       d    S5      [        U S   =(       d    S5      S-  U S	   U S
   U S   U S   U S   U S   SU R                  5       ;   a  U S   OS SU R                  5       ;   a  U S   b  [        U S   5      OSS.n[        5        nUR	                  SU S   45      R                  5       nS S S 5        W Vs/ s H  n[        US   5      PM     snUS'   U Vs/ s H  n[        US   5      US	   US
   S.PM     snUS'   U$ ! , (       d  f       N^= fs  snf s  snf )Nr   r6   r  r<   r   r   r         Y@rC   r   r   r   r   r   r   r   F)r   r6   r  r<   r   r   	price_eurrC   r   r   r   r   r   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
        student_idsr   r   )r;   r   r]  r   r|   r   )r   baser   srowsr   s        r>   r   r     s`   $i,'FF 233}-23#m,12U:FWWWy>h-+7388:+Ec,'4%+sxxz%9c&k>US[![`D" 
A		  $i\ $8: 	 
 277A3qw<7D^cd^cYZs1T7|QvY7T^cdDK 
 8ds   ,%D)D:?"D?)
D7c                   #    [        U 5        [        US5      (       a  UR                  SS9O
U=(       d    0 n U R                  5       I S h  vN nSU;   a-  SU;  a'   [        UR                  S5      =(       d    S5      US'   SU;   a  SU;  a  UR                  S5      US'   S	U;   aF  S
U;  a@   [        [        [        [        US	   5      R                  SS5      5      S-  5      5      US
'   SU;   aF  S
U;  a@   [        [        [        [        US   5      R                  SS5      5      S-  5      5      US
'   [        U5      n[        5        n[        R                  Ul        UR!                  SU45      R#                  5       nS S S 5        W(       d
  [%        SSS9e [        US   5      nUn	SU;   a  US   b  [        US   5      n	OUR                  SUR                  S5      5      n
U
bk  ['        U
[        5      (       a  U
n	OS['        U
[
        [        45      (       a8  [        U
5      R)                  5       R+                  5       nUS;   a  Sn	OUS;   a  Sn	U(       d  X:X  a
  [%        SSS9eU	(       a  SOSUS'   SU;   a*  US   b$   [,        R.                  R1                  US   S5        SU;   a  US   b   [        US   5      R)                  5       S S n[3        [
        UR5                  S 5      5      u  pSUs=::  a  S":  a  O  OSUs=::  a  S#:  d  O  [%        SS$S9eUS:X  a  US:X  a
  [%        SS%S9eS&Us=::  a  S':  d  O  [%        SS(S9eUS) S US) 3US'   SU;   a*  US   b$  [        US   5      nUS::  d  US*:  a
  [%        SS+S9eS,U;   aL  US,   bF  [        US,   5      R)                  5       R+                  5       nU[6        ;  a  [%        SS-U 3S9eUUS,'   SU;   aQ  US   bK  US   n[        5        nUR!                  S.U45      R#                  5       nU(       d
  [%        SS/S9e S S S 5        S	U;   aF  S
U;  a@   [        [        [        [        US	   5      R                  SS5      5      S-  5      5      US
'   S
U;   a.   [        US
   =(       d    S5      US
'   US
   S:  a
  [%        SS0S9e1 S1kn/ n/ nUR9                  5        H3  u  nnUU;   d  M  UR;                  U S235        UR;                  U5        M5     U(       d
  [%        SS3S9e [        S
U;   a  UR                  S
5      OUS
   =(       d    S5      nU(       + =(       a    U	nUR;                  U5        [        5        n[        R                  Ul        U(       Ga  US:  Ga  UR!                  S4U45      R=                  5       nU Vs/ s H  nUS5   c  M  [        US5   5      PM     nnU(       d  US5   (       a   [        US5   5      /n0 n UR                  S65      =(       d    0 n['        U[        5      (       an  0 nUR9                  5        HV  u  nn ['        U[        5      (       a  [        U5      O
[        U5      n  [        U=(       d    S5      n![?        SU!5      UU '   MX     UnU(       Ga  URA                  S7U V"s/ s H  n"U"4PM     sn"5        0 n#U(       a;  U H4  n"[?        S[        UR                  U"U5      =(       d    S5      5      U#U"'   M6     O*U H$  n"[?        S[        U=(       d    S5      5      U#U"'   M&     [,        R.                  RC                  5       RE                  S85      n$UR                  S5      =(       d    US   n%UR                  S5      =(       d    US   =(       d    S9S S n&S:U% S;U& 3n'/ n(U#R9                  5        HS  u  n"n)[        U)S<-  S=5      n*UR!                  S>U*U"45        U)S:  d  M1  U(R;                  U$U%U"U[        U)5      S?U'S 45        MU     U((       a  URA                  S@U(5        UR!                  SASBRG                  U5       SC3[I        U5      5        URK                  5         S S S 5        SUSD.$  GN7! [         a    0 n GNDf = f! [         a     GN"f = f! [         a     GNf = f! [         a     GNf = f! , (       d  f       GNK= f! [         a    Sn GN=f = f! [         a    [%        SSS9ef = f! [         a    [%        SS!S9ef = f! , (       d  f       GN= f! [         a	    SUS
'    GNf = f! [         a	    SUS
'    GNf = f! [         a    Sn GN%f = fs  snf ! [         a    / n GNf = f! [         a     GMS  f = f! [         a    Sn! GNf = f! [         a    0 n GNf = fs  sn"f ! , (       d  f       GNX= f7f)ENrQ  T)exclude_unsetdurationr   r   
teacher_idr   rg  r   rB  .r   price'SELECT * FROM reservations WHERE id = ?r   zReserva no encontradarH   r   Fhas_paid1trueu   sísion)0falsenooffr   zNada que actualizarr   r  r  u(   Fecha inválida. Usa formato YYYY-MM-DD.r<   rU  :u"   Hora inválida. Usa formato HH:MM.   rT     Hora inválida.,No se admiten reservas a medianoche (00:00).      u&   Hora fuera de horario (08:00–22:00).02drV     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  rC   r   r<   r   r   r   r   r   r   r   r   z = ?u'   Ningún campo permitido para actualizarzASELECT user_id FROM reservation_students WHERE reservation_id = ?r   per_student_centsr   z%Y-%m-%dT%H:%M:%Sz00:00Reserva  rf  rg  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  )&ru   r  rQ  jsonr}   r;   rK   roundfloatrN   replacer]  r   rl   rm   r{   r|   r   r	   rk   rE  rn   r   r   r   maprD  ALLOWED_STATUSESr   r  r   r  executemanyr  r  r  r  r   )+r0   r   r  updatesrawhas_other_updatesr   prev_row	prev_paidnew_paidrt  r  thhmmdminstatus_normr   dallowed	set_partsargsr   r  effective_price_centsdo_charge_nowr   r   rh  r  psctmpkkvvr4   sharesnow_txtdate_txttime_txtconcept_baseto_insshare	share_eurs+                                              r>   api_reservations_updater  :  s	    W%29'62J2Jglll.QXQ^\^GLLN" S/w>	*-cggj.A.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$**,Ra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\*
WX hj  #<mnn   g-w">	'%(uS9M5N5V5VWZ\_5`/adg/g)h%iGM" 	'%()?)D1%EGM" =!A%C8KLLG ID1<s$Z(KKN   4]^^" #-SZBZGKK$>aijwaxa}|}  #]0MKK	D";;2Q6<<S	 hj  7;Wda	l,3q|,dKW8I#6%#&x	':#;"<K !#'gg128bc4((C #		1%+5a+=+=Q3q6B#!$QV!B #&a*B !, ),%   `'23{cV{3
 $*&)!S1B1F1FsLa1b1gfg-h&is  +  +&)!S1F1K!-L&Ms  + ++//+445HI";;v.B(62B#KK/N8F3CNwPRQR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\]]	^( W  	'%&GM"	'
  	'%&GM"	'&  " !" X
 ! %"$K%  ) %$%  ) #!"B#  '$&!' 4M 
so  7gb bb g&b ,g2?b+ 1g>?b< =g7c	g#c 1Cg#c2 1g>A d
 >Dg?3d"3g?d4 ge
 (5g!:g.e  
+g5A
g?
e3e3g3e8gAf0+f9ff0"g:gD/g:A=g7gb bgbg
b($g'b((g+
b95g8b99g<
c
g	c

g
cgc/+g.c//g2dg
dg"
d1,g4egeg
egeg e0,g/e00g3g8fgfg
ff0ff0f-)f0,f--f00g <g?g  g
ggz/api/reservations/{rid}ridc           
        ^#    [        U 5        S[        S[        4S jmS[        S[        [           4U4S jjn[        5        n[        R                  Ul        UR                  SU45      R                  5       nU(       d
  [        SSS	9eS
n [        US   5      nU(       Ga  [        UR                  5       5      nSU;   a  [        US   =(       d    S5      OSn/ nSU;   aG  US   (       a=   [        R                   " US   5      =(       d    /  V	s/ s H  n	[        U	5      PM     nn	O SU;   a  US   (       a   [        US   5      /nU(       d  U" X15      n[#        U V
s1 s H  n
[%        U
[        5      (       d  M  U
iM     sn
5      n0 nSU;   av  US   (       al   [        R                   " US   5      =(       d    0 nUR'                  5        H5  u  p [        U5      nU(       a  X;   a  [        U=(       d    S5      X'   M5  M7     U(       d  Un[)        U5      nUS:  at  [+        [-        U5      U5      u  nnU Vs0 s H  oU_M     nnUS U  H  nUU==   S-  ss'   M     US:  a)  [	        UR                  5       5       H  nUU   * UU'   M     UnUR'                  5        Hf  u  nnU=(       d    SS-  nUR                  SU45      R                  5       nU(       a  UR                  SUU45        MR  UR                  SUU45        Mh     UR                  SU45        UR                  SU45        UR/                  5         S S S 5        SS0$ ! [         a    S
n GNf = fs  sn	f ! [         a    / n GN1f = f! [         a    / n GNDf = fs  sn
f ! [         a     GM  f = f! [         a    0 n GNf = fs  snf ! , (       d  f       SS0$ = f7f)NrC   r1   c                 Z    U R                  SU45      R                  5       n[        U5      $ )Nz>SELECT name FROM sqlite_master WHERE type='table' AND name = ?)r|   r   r]  )r   rC   r   s      r>   _table_exists.api_reservations_delete.<locals>._table_exists  s0    llLG
 (* 	 Cyr@   r  c                   > S Hg  nT" X5      (       d  M   U R                  SU S3U45      R                  5       nU(       a(  U Vs/ s H  oDS   c  M
  [        US   5      PM     sns  $ Mi     / $ s  snf ! [         a     M  f = f)N)reservation_usersreservation_studentsreservation_alumnoszSELECT user_id FROM z WHERE reservation_id = ?r   )r|   r   r;   r}   )r   r  r  r   r   r  s        r>   _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)   0A6	A1A1&A61A66
BBrq  r   r%  rH   Fr   r   r   user_ids_jsonr   per_student_cents_jsonr   rf  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)ru   rN   r]  r;   r  r   rl   rm   r{   r|   r   r	   r}   r   r   r  loadssortedrk   r   r   divmodabsr   )r0   r  r  r   r   	paid_flagr   r   uidsxr   per_mapjr   r  r4   sidsr  ri  remr  centseurr   r  s                           @r>   api_reservations_deleter    s    W%# $  c  
D";;llDsfMVVXC8PQQ		S[)I sxxz?D:G4:O#c-05A6UVK D$&3+?,0JJs?7K,L,RPR,RS,RqCF,RDSD d"s9~I/0D ,T7dAdjC.@1dABD&(G'4/C8P4Q
!

3'?#@AGRA !	%"%a&C#'3;/216{ ,7 !* Iq5 &s;'7 ;ID#0459C5#DSzCA  *"Q!%chhj!1A&)!fWCF "2!G%mmo
UzU*llHF (*  LLqc

 LLYc
 ." LLPSVRXY<sfE[ 
^ $<M  	I	 T  D
 ! D B  ) %$%  ! G! 6c 
^ $<s  AOA
OMAO1$M/M**M/,O>NO%N
N
O"7N,-NN,6ON?C<OOM'#O&M''O*M//M?;O>M??ONONO
N)$N,(N))N,,N<8O;N<<O
O
O>   	cancelada	pendienterZ  z/api/reservationsc                 d  #    [        U 5         U R                  5       I S h  vN nSn[        US5      (       a#  UR                  b  [        UR                  5      nOUR                  SUR                  S5      5      n[        U[
        5      (       a  UnOJ[        U[        [        45      (       a/  [        U5      R                  5       R                  5       nUS;   a  SnUR                  R                  5       nUR                  R                  5       S S n [        R                  R                  U5         [#        [        UR%                  S
5      5      u  pSUs=::  a  S:  a  O  OSU	s=::  a  S:  d  O  [!        SSS	9eUS:X  a  U	S:X  a
  [!        SSS	9eSUs=::  a  S:  d  O  [!        SSS	9eUS S
U	S 3n[        UR&                  5      n
U
S::  d  U
S:  a
  [!        SSS	9e[        UR(                  =(       d    S5      n[+        USS 5      nUc!  UR                  SUR                  S5      5      nU(       dL  UbI  [        U5      S:w  a:   [        [-        [/        [        U5      R1                  SS5      5      S-  5      5      nUS:  a
  [!        SSS	9eUR2                  =(       d    SR                  5       R                  5       nU[4        ;  a  [!        SSU 3S	9eUR6                  =(       d    S nUR8                  =(       d    S nUR:                  =(       d    S n[=        UR>                  =(       d    / 5      nUR@                  (       a  URC                  UR@                  5         [E        [G        S  U 5       5      5      nU(       a  [I        5        nURK                  S"SRM                  S#[O        U5      -  5       S$3[Q        U5      5      RS                  5       nS S S 5        W Vs0 s H  n[        US%   5      U_M     nnU Vs/ s H  nUU;  d  UU   S&   S':w  d  M  UPM     nnU(       a  [!        SS(U 3S	9e[O        U5      S):X  a,  UUS      nU(       d  US*   nU(       d  US+   nU(       d  US,   nURT                  b  URT                  OS nUc  S-U;   a  UR                  S-5      nUb[   [        U5      nUS:  aG  [I        5        nURK                  S/U45      RW                  5       nU(       d
  [!        SS0S	9e S S S 5        OS n[O        U5      S):X  a  US   OS n[        RX                  R[                  5       R]                  S15      n0 n UR                  S25      =(       d    0 n[        U[^        5      (       an  0 nURa                  5        HV  u  n n! [        U [        5      (       a  [        U 5      O
[        U 5      n" [        U!=(       d    S5      n#[c        SU#5      UU"'   MX     UnU(       a  0 n$U(       a;  U H4  n[c        S[        UR                  UU5      =(       d    S5      5      U$U'   M6     O*U H$  n[c        S[        U=(       d    S5      5      U$U'   M&     [e        U$Rg                  5       5      n%O0 n$[        U=(       d    S5      n% [I        5        nURK                  S3UXgU
U%XUURh                  UUUU(       a  S)OS45      n&U&Rj                  n'U(       a  URm                  S4U Vs/ s H  nU'U4PM	     sn5        URm                  S5U Vs/ s H  nU4PM     sn5        U(       a  U$Ra                  5        H)  u  nn([-        U(S6-  S75      n)URK                  S8U)U45        M+     / n*S9U S:U 3n+U$Ra                  5        H9  u  nn([        U(5      S:  d  M  U*RC                  UUUU'[        U(5      S;U+S 45        M;     U*(       a  URm                  S<U*5        URo                  5         S S S 5        W'n, [I        5        n3U3RK                  SBW,45      RW                  5       n-U3RK                  SCU,45      RS                  5       n4U4(       a  [=        U45      O/ n5U5(       do  S n6U-SA   (       a$  U3RK                  SDU-SA   45      RW                  5       n6U6(       d.  U-S+   (       a$  U3RK                  SEU-S+   45      RW                  5       n6U6(       a  U6/n5S n7U-SF   b2  U3RK                  SGU-SF   45      RW                  5       nU(       a  US*   OS n7U5(       a  SHn8SIU-SJ    SKU-SL    3U7(       a  SMU7 3OS-   S-   n9 [        [u        U 5      S%   5      n:[        RX                  Rw                  5       Ry                  SNSO9n;U3Rm                  SPU5 Vs/ s H  nU;U:[        US%   5      U8U9U,4PM     sn5        U3Ro                  5         S S S 5        SW,SQ.$  G	N! [         a    0 n G	Nf = f! [         a    [!        SSS	9ef = f! [         a    [!        SSS	9ef = f! [         a    Sn GNf = f! [         a    [!        SS!S	9ef = f! , (       d  f       GNe= fs  snf s  snf ! [         a    [!        SS.S	9ef = f! , (       d  f       GNr= f! [         a     GM  f = f! [         a    Sn# GNf = f! [         a    0 n GNf = fs  snf s  snf ! , (       d  f       GN= f! [p        Rr                   Ga    [I        5        nURK                  S=XgU45      RW                  5       n-U-(       d
  [!        S>S?S	9e[        U-S%   5      n.URK                  S@U.45      RS                  5       n/U/ Vs/ s H  n[        USA   5      PM     Os  snf n0nU Vs/ s H  nUU0;  d  M  UPM     Os  snf n1nU1(       d  U.n,GO+URm                  S4U1 Vs/ s H  nU.U4PM	     Os  snf sn5        URm                  S5U1 Vs/ s H  nU4PM     Os  snf sn5        / n*S9U S:U 3n+U(       a  U1 H  nUR                  UU5      n2 [        U2=(       d    S5      n2O! [         a    Sn2 Of = f[-        [c        SU25      S6-  S75      n)URK                  S8U)U45        U2S:  d  Mr  U*RC                  UUUU.[        U25      S;U+S 45        M     U*(       a  URm                  S<U*5        URo                  5         U.n,S S S 5         GM  ! , (       d  f        GN= ff = f! [         a    Sn: GNf = fs  snf ! , (       d  f       GNV= f! [         a     GNff = f7f)RNFr   rr  rs  TrU  r   u!   Fecha inválida (usa YYYY-MM-DD).rH   r|  u   Hora inválida (usa HH:MM).r   r}  rT  r~  r  r  r  z$Hora fuera de horario (08:00-22:00).r  rV  r  rg  rp  rF   rB  ro  r   r  rZ  r  c              3   @   #    U  H  oc  M  [        U5      v   M     g 7fr   )r;   )r  r  s     r>   r  *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 (rC  r   r   rh   r]  u   IDs no v�lidos o no alumnos: r   rC   r   r   rn  u   docente_id inválido.r  r  r  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   rf  rg  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)rh  z%Ya existe una reserva en ese horario.z?SELECT user_id FROM reservation_students WHERE reservation_id=?r   rq  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 r  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  )=ru   r  r}   r  r   r]  rK   rk   r;   rN   rE  rn   r  r<   r   fromisoformatr	   r  rD  r   r   getattrr  r  r  r   r  rC   r   r   r  rY  r   r  r  r   r   r|   r  r   r  r   r   r   r   r  r  rQ  r   r  sumr  r   r   r  r   rl   IntegrityErrorrV   r   r   )<r0   r  r  r  rt  r  r  r  r  r  r  r   price_eur_rawr  rC   r   r   rh  r   r   r   foundr4   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  conn2rj  
recipientsrecipdocente_nametitulocuerpor$  now_isos<                                                               r>   api_reservations_creater    s    W%LLN" IwGLL$<&	ggfcggj12c4  Ic3Z((C &&(A44 	||!!#H||!!#BQ'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\88:@@BK**6KK=4YZZLL DD]]"dE]]"dEw''-2.K7??+RS N NNO W<<jknkskstwx{  }H  yI  uI  lJ  kK  KL  Mk" hj  
 +//$QQtWq$/)`ksS-=sFASW_A_sk`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)*0bc4  C		1#-a#5#5Q3q6BQV!B a*B $ !$ "!!S):)>)>sK)P)UTU%VWs # #!!S)9%:;s #0 0q1h5W,,   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W-- 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 W
 0`"  	QC8OPP	Q & !  ! B  2 ; 4 WZ !! :5W,,l:. hj  #<cddc$i.KllOn hj  7>>g3q|,g>K>%0K[cC{4Jc[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 Wb  s  t0g gg C0t0g! 8!g9 C4t09h C!t0)h$ t0A	h<t0*it0	i#i)B	t03i >t03i0At0Aj' +jjj' 0B%t0
k  Ak4j:kj?&A8k"Ak1
k <
t D0t7s5;t	t't>t t0g gt0gt0!g66t09ht0h!t0 h!!t0$h99t0<
it0i--t00
i?:t0
jj' jj' j$ j' #j$$j' 'j73t06j77t0:
k
kk s25A'sm54s 
nn#s7os"o0/5s%p:9s:q		sq			4sAss2t0
s.	(s2+t0.s22t05tttt
tt t0t 
t-)t0,t--t0c           	        #    [        U 5        S[        SS 4S jnU(       a  U" U5        U(       a  U" U5        U(       a  U(       a  X:  a  X!p!S nU(       aR  UR                  5       R                  5       nU[        ;  a*  [        SSSR                  [        [        5      5       S3S9e/ n/ n	U(       a"  UR                  S	5        U	R                  U5        U(       a"  UR                  S
5        U	R                  U5        Ub"  UR                  S5        U	R                  U5        U(       a"  UR                  S5        U	R                  U5        Ub"  UR                  S5        U	R                  U5        U(       a  SSR                  U5      -   OSn
SU
 S3n[        5        nUR                  X5      R                  5       nS S S 5        W Vs/ s H  n[        U5      PM     sn$ ! , (       d  f       N*= fs  snf 7f)Nr  r1   c                 l     [         R                  " U S5        g ! [         a    [        SSU  S3S9ef = f)Nr  r   u   Fecha inválida: z. Usa formato YYYY-MM-DD.rH   r  r  s    r>   _check_date*api_reservations_list.<locals>._check_date  sA    	ja, 	jC:KA3Ng8hii	jr  r   u   Estado inválido. Usa uno de: r  ro  rH   z	date >= ?z	date <= ?r   zLOWER(status) = ?r   r  r   rF   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
    )ru   rN   rE  rn   r  r	   r  r  r  r   r|   r   r   )r0   r  r  r   r   r   r  r  r  r	  clauser  r   r   r   s                  r>   api_reservations_listr    s     W%js jt 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 
 7s*   FG9 G#?G9G4 G9#
G1-G9/perfilc                 B  #    [        U 5      nU(       d
  [        SSS9$ [        U[        R                  5      (       a  [        US   5      O[        UR                  S5      5      n[        U[        R                  5      (       a  US   OUR                  S5      =(       d    SR                  5       n[        5        nUR                  SX#45      R                  5       nU(       a  US   OS	nS S S 5        [        R                  S
U UWS.5      $ ! , (       d  f       N(= f7f)Nr   r   r   r   r   rF   z
            SELECT COUNT(*) AS c
            FROM reservations r
            WHERE r.user_id = ?
               OR LOWER(COALESCE(r.email,'')) = LOWER(?)
            r   r   zprofile.htmlr  )rV   r   rk   rl   rm   r;   rK   rE  r   r|   r   rW   rX   r  s          r>   perfilr    s     	g	BH#>>'GKK88C4Mc"&&,>OE)"gkk::7w@USU\\^H	Dll 
 (* 	 ),CH 
 %%!2	
  
s   B:D<0D,"D
DD/ajustesc                 t  #    [        U 5      nU(       d
  [        SSS9$ [        5        nUR                  SUS   45      R	                  5       nUR                  SUS   45      R	                  5       nUR                  SUS   45      R	                  5       nS S S 5        W(       a  [        U5      O0 nW(       a  UR                  [        U5      5        W(       a  UR                  [        U5      5        [        R                  SU UU R                  R                  S	5      S
.5      $ ! , (       d  f       N= f7f)Nr   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=?settings.htmlr5   )r0   rT   r5   )rV   r   r   r|   r   rQ  updaterW   rX   r7   rK   )r0   rp   r   row_corerow_profile
row_sportsctxs          r>   ajustes_getr  	  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
#$%%OO''/	
  
s   'D8A-D'BD8'
D51D8r   r|  r~  r  r  r  c
           
        #    [        U 5      n
U
(       d
  [        SSS9$ [        X	5        U=(       d    SR                  5       nU=(       d    SR                  5       nU=(       d    SR                  5       =(       d    S nU=(       d    SR                  5       =(       d    S nU=(       d    SR                  5       =(       d    S nU=(       d    SR                  5       =(       d    S nU=(       d    SR                  5       =(       d    S n[	        5        nUR                  SU
S   45      R                  5       nU(       a  US   OS nS S S 5        WnU(       a  [        USS 5      (       a  [        R                  R                  UR                  5      S	   R                  5       nUS
;  a4  [        R                  SU U
SU R                  R!                  S5      S.5      $ ["        S-  S-  nUR%                  SSS9  USU
S    U 3-  n['        US5       nUR)                  UR+                  5       I S h  vN 5        S S S 5        SU
S    U 3n [	        5        nUR                  SXU
S   45        UR                  SU
S   45        UR                  SX>U
S   45        UR                  SU
S   45        UR                  SXVXxU
S   45        UR-                  5         S S S 5        [        SSS9$ ! , (       d  f       GN= f N! , (       d  f       N= f! , (       d  f       N== f! [.        R0                   a7    [        R                  SU U
SU R                  R!                  S5      S.5      s $ f = f7f)Nr   r   r   rF   z1SELECT avatar FROM user_profile WHERE user_id = ?r   r|  ri  r   )z.pngrk  z.jpegz.webpr  z:Formato de imagen no permitido. Usa PNG, JPG, JPEG o WebP.r5   )r0   rT   r?  r5   rB   r`  Trl  ro  rp  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  )rV   r   rP   rE  r   r|   r   r  r  r  r  ri  rn   rW   rX   r7   rK   r  r  r  r  rj  r   rl   r  )r0   rC   r   r   r|  r~  r  r  r  r5   rp   r   r   current_avatarr  extr  r  r  s                      r>   ajustes_postr  +	  s#     
g	BH#>>JBD[b!Ekr  "*dEZR (DDR&&(0DHR&&(0DH%+224<N	DllNQSTXQYP[\eeg*-X4 
 !K'&*d33ggv/288:88--o"U++F3	@   )I5$6E"T(C5"99	)T"aGG&++-'( #-bhZu=W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 !! ))/BOO''/	<
  	s   DM-3K)CM-K=.K;
/K=7M-

L BLL 
M-)
K83M-;K==
LM-
LL M-L AM*'M-)M**M-z/notesc                 r  ^^#    [        U 5      nU(       d
  [        SSS9$ Sn/ nSUR                  5       ;   a  US   b  [        US   5      OSnUS:X  a  OKUS:X  a#  US	-  nUR	                  [        US
   5      5        O"US-  nUR	                  [        US
   5      5        US-  n[        5        nUR                  X#5      R                  5       nS S S 5        S mU4S jmU4S jnU4S jn/ n	W GH  n
T" U
SS5      =(       d    SnT" U
SSS5      =(       d    SnU(       d\  T" U
S5      (       aN  U
S   (       aD  [        U
S   5      R                  5       n[        U5      S:  a  US   n[        U5      S:  a  US   nU(       d  U(       a  U SU 3R                  5       OT" U
S5      (       a  U
S   OSnU	R	                  T" U
S
5      (       a  U
S
   OS UUUT" U
S5      (       a  U
S   OS U
S   U" U
5      U" U
5      S.5        GM     [        R                  SU UU	S.5      $ ! , (       d  f       GN\= f7f)Nr   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) <> ''
    rh   rF   ri   rs   z AND r.docente_id = ?r   z AND r.user_id = ?z& ORDER BY r.created_at DESC, r.id DESCc                 H     XR                  5       ;   $ ! [         a     gf = f)NF)r   r}   )r   keys     r>   hasnotes.<locals>.has	  s(    	((*$$ 		s    
!!c                    > U H<  nT" X5      (       d  M  X   nUc  M  [        U5      R                  5       S:w  d  M:  Us  $    g )NrF   )rN   rE  )r   namesr  rt  r  s       r>   ru  notes.<locals>.pick	  s>    A3{{f?s3x~~'72'=J	 
 r@   c                 h   > T" U S5      =(       d"    T" U S5      =(       d    T" U S5      =(       d    S$ )Nstudent_namerC   r      —r   r   ru  s    r>   student_labelnotes.<locals>.student_label	  s.    C(_Df,=_c7AS_W__r@   c                 H   > T" U S5      =(       d    T" U S5      =(       d    S$ )Nr  docente_emailr  r   r  s    r>   docente_labelnotes.<locals>.docente_label	  s!    C(RDo,FR(Rr@   r  fechar<   hourhorar6   r   r   rg  r  r   )r   r  r<   
dt_displayr6   r   studentrs   z
notes.html)r0   rT   r   )rV   r   r   rN   r  r;   r   r|   r   rD  r   rE  rW   rX   )r0   rp   r  r	  rh   r   r   r  r  r   r   r  r  partsr  r  ru  s                  @@r>   r   r   h	  sE    	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VVV4:C\22s<7HL)*002E5zQ 85zQ 8;Cx
!H:.557knor  uA  lB  lBVYZfVg  HJ
"3~~#d)4$/23/E/E#l+4\$S)$S)	
 		 ( %%	
 O 
s   B,H70 H%EH7%
H4/H7)r,   TFplainc                     U =(       d    Sn [         (       a  [        R                  " U 5      $ S[        R                  " U R                  S5      5      R                  5       -   $ )NrF   sha256$utf-8)_HAS_BCRYPTr,   r   hashlibsha256encode	hexdigest)r  s    r>   hash_passwordr%  	  sE    KRE{{{5!!w~~ell7&;<FFHHHr@   stored_hashc                    U =(       d    Sn U=(       d    SnUR                  S5      (       d,  UR                  S5      (       d  UR                  S5      (       a#  [        (       a   [        R                  " X5      $ gUR                  S5      (       a^  UR                  SS5      S   n[        R                  " U R                  S5      5      R                  5       n[        R                  " X25      $ g! [         a     gf = f)	NrF   z$2a$z$2b$z$2y$Fr  r   r  )
startswithr   r,   rF  r}   rD  r!  r"  r#  r$  rL   rM   )r  r&  expecteddigests       r>   verify_passwordr+  	  s    KRE#Kf%%)?)?)G)G;KaKabhKiKi;}}U88 i(($$Y215W 56@@B""644  s   %C1 1
C>=C>z/ajustes/passwordcurrent_passwordnew_passwordconfirm_passwordc                   #    [        U 5      nU(       d
  [        SSS9$ [        X5        U=(       d    SR                  5       nU=(       d    SR                  5       nX#:w  a  [        R                  SU USS.5      $ [        U5      S:  a  [        R                  SU US	S.5      $ [        U[        5      (       a  UR                  S
5      OUS
   n[        X5      (       d  [        R                  SU USS.5      $ [        U5      n[        5        nUR                  SXuS   45        UR                  5         S S S 5        [        SSS9$ ! , (       d  f       N= f7f)Nr   r   r   rF   r  u   Las contrase�as no coinciden.)r0   rT   r?  r  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   r  )rV   r   rP   rE  rW   rX   r   rk   rQ  rK   r+  r%  r   r|   r   )	r0   r,  r-  r.  r5   rp   r&  new_hashr   s	            r>   ajustes_passwordr1  	  sK     
g	BH#>> &B--/L(.B557'))/6<
  	
 <1))/N<
  	
 .8D-A-A"&&)r/GZK+99))/=<
  	
 \*H	DBXRVxDXY 
 
<< 
s   DE'E5E
EEc                   @    \ rS rSr% \" SS9r\\S'   Sr\	\
   \S'   Srg)	MatriculaPayloadi	  r   r  matricula_centsaddmoder   N)r  r  r  r  r   r4  r;   r  r6  r   rN   r  r   r@   r>   r3  r3  	  s     A;OS&D(3-r@   r3  z/api/users/{user_id}/matriculac           	      f  #    [        U 5        [        UR                  SS5      5      R                  5       nUS;  a
  [	        SSS9eSU;   nSU;   nU(       d  U(       d
  [	        SS	S9eU(       a3   [        [        [        US   5      R                  S
S5      5      S5      nO [        US   5      n[        US-  S5      n[        5        nUR                  SU45      R                  5       n	U	(       d  UR                  SUS45        Sn
O[        U	S   =(       d    S5      n
US:X  a  UnO[        X-   S5      nUR                  SX45        SU[        [        US-  5      5      S.sS S S 5        $ ! [         a    [	        SSS9ef = f! [         a    [	        SSS9ef = f! , (       d  f       g = f7f)Nr6  r   >   r5  r   r   zmode debe ser 'set' o 'add'.rH   matricula_eurr4  zFalta matricula_eur.rB  ro  rg  u   matricula_eur inv�lido.u   matricula_cents inv�lido.rf  z8SELECT matricula_eur FROM user_finance WHERE user_id = ?r  g        r   z;UPDATE user_finance SET matricula_eur = ? WHERE user_id = ?Tr   )r   r8  r4  )rU   rN   rK   rn   r	   r  r  r  r}   r;   r   r|   r   )r0   r   r  r6  has_eur	has_centseurosr  r   r   r  new_vals               r>   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FMc*G5=GGOQ/GRU\Tfg $"53#78
 
  	UC8STT	U
  	WC8UVV	W 
sO   A.F111E0 "F1$F 2F1BF &
F10FF1FF1 
F.*F1)Pathc                   #    [        U 5        UR                  S5      =(       d    SR                  5       R                  5       nU[        ;  a
  [        SSS9e[        5        nUR                  SU45      R                  5       nU(       d
  [        SSS9eUR                  S	X145        UR                  5         UR                  S
U45      R                  5       nS S S 5        S[        W5      S.$ ! , (       d  f       N= f7f)Nrh   rF   r   u   Rol inválidorH   z'SELECT id, role FROM users WHERE id = ?r   rP  r8  z@SELECT id, name, email, role, created_at FROM users WHERE id = ?T)r   rT   )rU   rK   rE  rn   VALID_ROLESr	   r   r|   r   r   rQ  )r0   r   r  target_roler   r   updateds          r>   api_users_update_rolerC  .
  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 "A7C/D /
C=9D z/api/ratingsapi_ratings_createc           	      4  #    [        U 5      n[        UR                  5      nU(       d
  [        SSS9e[	        US   5      R                  5       S:w  a
  [        SSS9e[        UR                  5      nUR                  =(       d    SR                  5       n[        R                  " 5       R                  S	S
9n[        5        nUR                  S[        UR                  5      [        US   5      XEU45        S S S 5        SS0$ ! , (       d  f       SS0$ = f7f)Nr   zJugador no encontradorH   rh   r]  r   zSolo se pueden valorar alumnosrF   r  r  zaINSERT INTO player_ratings (player_id, docente_id, score, comment, created_at) VALUES (?,?,?,?,?)r   r   T)ru   r   rb  r	   rN   rn   r;   rc  rd  rE  r   r   r   r   r|   )r0   r  rp   playerrc  rd  r  r   s           r>   rD  rD  ?
  s     	!'	*BG--.F4KLL
6&>  "h.4TUUE$"++-G
//

%
%y
%
9C	Do""#SD]ECH	
 

 $< 

 $<s   C D6D8D
D
Dapi_ratings_listrb  c                 D  #    [        U 5      n/ nSnU(       a  SnUR                  [        U5      5        [        5        nUR	                  SU S3U5      nUR                  5        Vs/ s H  n[        U5      PM     nnS S S 5        U$ s  snf ! , (       d  f       W$ = f7f)NrF   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
        )ru   r  r;   r   r|   r   rQ  )	r0   rb  rp   r	  r  r   r   r  r   s	            r>   rG  rG  Q
  s     	!'	*BFE'c)n%	Dll   G 	  "%0AQ0 
 K 1 
 Ks.   =B )B(B	=B?
B 	B
BB z/logoutc                 R   #    U R                   R                  5         [        SSS9$ 7f)Nr0  r   r   )r7   r8   r   r=   s    r>   logoutrJ  f
  s"     OO55s   %'z/api/healthc                     #    SS0$ 7f)Nr   r   r   r   r@   r>   healthrL  k
  s     ds   )r   r   )r   r   c                   `    \ rS rSr% \\S'   \\S'   \\S'   \" SSS9r\\S'   S	r	\
\   \S
'   Srg	)ValoracionItemis
  area	subescala	indicadorr   rU  rW  rc  Nobservacionesr   )r  r  r  r  rN   r  r   rc  r;   rR  r   r  r   r@   r>   rN  rN  s
  s0    
INN!"E3"#'M8C='r@   rN  c                   0    \ rS rSr% \\S'   \\   \S'   Srg)ValoracionJugadorIniz
  rb  r   r   N)	r  r  r  r  r;   r  r   rN  r  r   r@   r>   rT  rT  z
  s    Nr@   rT  z/api/valoraciones_jugadorc                    #    [        U 5        [        5        nUR                  SU45      R                  5       nU Vs/ s H  n[	        U5      PM     snsS S S 5        $ s  snf ! , (       d  f       g = f7f)Na  
            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
        )require_docenter   r|   r   rQ  )r0   rb  r   r   r   s        r>   api_valoraciones_jugador_listrW  
  se     G	D||  \ $8: 	 "&&AQ& 
 ' 
s-   A5&A$AA$
A5A$$
A2.A5c                   #    [        U 5        [        U 5      nS n [        US   5      nUb  U[        U5      :X  a
  [        SSS9e[        5        n[        R                  Ul
        UR                  SU45      R                  5       nU(       d
  [        SSS9e UR                  SU45         UR                  S	X45         UR                  S
U45        UR                  SU45        UR                  SU45        UR                  SU45        UR                  SU45        UR                  SU45        UR                  SU45        UR                  SU45        S S S 5        S[        U5      S.$ ! [         a<     [        [	        U5      R                  S5      5      n GNv! [         a    S n  GNf = ff = f! [         a     GNf = f! [         a     GNf = f! [         a     Nf = f! , (       d  f       N= f7f)Nr   r   z%No puedes eliminar tu propio usuario.rH   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   T)r   deleted)rU   rV   r;   r}   rQ  rK   r	   r   rl   rm   r{   r|   r   )r0   r   rp   r.  r   r   s         r>   api_users_deleterZ  
  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   G;E/ &G;AG*F8-G	BGG*G;/
F5:#F G; F1,F5-G;0F11F55G;8
GG*GG*	
GG*GG*
G'$G*&G''G**
G84G;)r	   r   c                     [        U 5      nU(       d
  [        SSS9e US   nUS;  a
  [        SSS9eU$ ! [         a    [        USS 5      n N+f = f)NrG   zSe requiere rol docente.rH   rh   rr   )rV   r	   r}   r  ro   s      r>   rV  rV  
  sh    	g	B4NOO)&z ''4NOOI	  )r64()s   5 AAc                     U R                   R                  S5      =(       d$    U R                   R                  S5      =(       d    Sn[        X5        g )Nr_   zX-Csrf-TokenrF   )rb   rK   rP   rc   s     r>   require_csrf_headerr]  
  s8    OO/\7??3F3F~3V\Z\E r@   c                   #    [        U 5      n[        U 5        UR                  (       d
  [        SSS9e[        R
                  " S5      n[        5        nUR                  5       nUR                   H  nUR                  SX1R                  US   UR                  R                  5       UR                  R                  5       UR                  R                  5       [        UR                  5      UR                   =(       d    SR                  5       =(       d    S 45        M     UR#                  5         S S S 5        SUS	.$ ! , (       d  f       N= f7f)
Nr   u   Sin �tems en la evaluaci�n.rH   r  z
                INSERT INTO valoraciones_jugador
                (eval_id, player_id, docente_id, area, subescala, indicador, score, observaciones)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?)
            r   rF   T)r   eval_id)rV  r]  r   r	   r9   	token_hexr   r   r|   rb  rO  rE  rP  rQ  r;   rc  rR  r   )r0   r  rp   r_  r   r   its          r>   api_valoraciones_jugador_createrb  
  s     		!B ==4UVV"G	Dkkm--BKK 
 **BtH!3!3!5r||7I7I7KBHH 0 0 6B==?G4	   	 
 7++ 
s   AECE 3E 
E
E)HTTP_403_FORBIDDENHTTP_404_NOT_FOUNDexcc                 B  #     [        U 5      nUR                  [        :X  a  [        R                  SXS.[        S9$ UR                  [        :X  a  [        R                  SXS.[        S9$ [        SUR                  0UR                  S9$ ! [         a    S n Nf = f7f)Nz404.htmlrS   )rI   z403.htmlrJ   )	rV   r}   rI   rd  rW   rX   rc  r   rJ   )r0   re  user_ctxs      r>   http_exception_handlerrh  
  s     ( ,,))*'6\j|)}}
,,))*'6\j|)}}3::.COOLL  s(   BB A>BBBBBc                     [        5        nUR                  SU 45      R                  5       nUsS S S 5        $ ! , (       d  f       g = f)Na  
            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
        r   )r   r   r   s      r>   r   r     s>    	D|| 
 Z
 " 	  
r   startupc                      [        5        n U R                  S5        U R                  5         S S S 5        [	        5          [        5        n U R                  S5        U R                  S5        S S S 5        [        5         g ! , (       d  f       NY= f! [         a     Nhf = f! , (       d  f       N:= f! [         a     NIf = f)Nz
                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
            zPRAGMA optimize;z PRAGMA wal_checkpoint(TRUNCATE);)r   r|   r   r}   r   r  r~   s    r>   
on_startuprl    s    	WLL  
 KKM  IWLL+,LL;< 
 ! W   W  s]   
B "BB 
B3 #B".B3 
BB B 
BB"
B0,B3 0B3 3
C ?C )r]  NN)r\  r   )NNN)NNNNN)fastapir   r   r   r   r   r   r	   fastapi.responsesr
   r   r   fastapi.staticfilesr   fastapi.templatingr   starlette.middleware.sessionsr   passlib.contextr   pydanticr   rl   pathlibr  retypingr   r   r   r   r   r   r   r   r   r   r   r!  rL   r9   r<   r  r  r  r  urllib.parseurllibr  r   appr>  __file__resolveparentr  rz   getenvrn   IS_PRODr:   
SECRET_KEYadd_middlewarer   r?   mountrW   rN   rP   rK   rY   ra   rd   rU   ru   r   r   r   r   r;   r   r]  r   r   postr   r   r   r   r   r   r   rQ  r   r  r  r  rV   r!  r#  r&  r)  r*  r4  r8  r:  r@  rA  rJ  rM  rN  rX  rZ  r^  UPLOADS_DIRrb  r  r  rD  ri   r  r  r  r  deleter!  r"  r(  rK  r=  r2  r6  r9  r;  r?  rH  r[  r\  rS  r_  ra  r   patchr  r  r  r  r  r  r  r  r   passlib.hashr,   r   r}   r%  r+  r1  r3  r=  r@  rC  rD  rG  rJ  rL  rN  rT  r  rW  rZ  rV  r]  rb  starlette.exceptionsStarletteHTTPExceptionstarlette.statusrc  rd  exception_handlerrh  r   on_eventrl  r   r@   r>   <module>r     s4   Q Q Q J J + . ; (    	   ( 1 1 * 8 8   ! !      6 6  !K <<!))+22
\
!
))Iu
%
+
+
-1G
GYY'(EG,A,A",E
   %   H:&A5G 5 5 		)[<8x	 Ho6	L' L#* L 6_ _ 7_ 4%W %
7 g AJ"c "
&D &kC k 
&9: 9:;;; Dj; ;;@S 0C 0 CKGKc #  C $J:=*, 	$\B&G & C& 
:<Xw   Y$ 	%lC!&w !& !& D!&J 	.tDTG TS T ET, 	+,aA+?@bQ34JK"4[ %d!$K@W
@W
@W c]@W 	@W
 SM@W -@WD

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