From e64a08326cf57bf20dfd74e1e1732db5420abf4d Mon Sep 17 00:00:00 2001 From: adrigongv23 Date: Fri, 6 Mar 2026 21:21:27 +0100 Subject: [PATCH] Admins.py configurados correctamente dados los cambios realizado en la base de datos --- .../__pycache__/admin.cpython-314.pyc | Bin 1187 -> 1864 bytes .../__pycache__/models.cpython-314.pyc | Bin 3070 -> 4106 bytes Plataform_Web/documentos/admin.py | 35 ++++++- ...actura_alter_documento_options_and_more.py | 66 +++++++++++++ ...documento_options_and_more.cpython-314.pyc | Bin 0 -> 3372 bytes Plataform_Web/documentos/models.py | 4 +- .../gestion/__pycache__/admin.cpython-314.pyc | Bin 1143 -> 2283 bytes .../__pycache__/models.cpython-314.pyc | Bin 3466 -> 6531 bytes Plataform_Web/gestion/admin.py | 52 ++++++++-- ...e_patrocinador_contacto_equipo_and_more.py | 92 ++++++++++++++++++ ...r_contacto_equipo_and_more.cpython-314.pyc | Bin 0 -> 6046 bytes .../pruebas/__pycache__/admin.cpython-314.pyc | Bin 772 -> 2191 bytes .../__pycache__/models.cpython-314.pyc | Bin 2088 -> 4854 bytes Plataform_Web/pruebas/admin.py | 52 +++++++++- ..._telemetria_variable_delete_testgeneral.py | 67 +++++++++++++ ...ariable_delete_testgeneral.cpython-314.pyc | Bin 0 -> 4344 bytes .../__pycache__/admin.cpython-314.pyc | Bin 747 -> 816 bytes .../__pycache__/models.cpython-314.pyc | Bin 2013 -> 2281 bytes Plataform_Web/temporadas/admin.py | 14 ++- .../migrations/0002_temporada_miembros.py | 20 ++++ .../0002_temporada_miembros.cpython-314.pyc | Bin 0 -> 1094 bytes .../users/__pycache__/admin.cpython-314.pyc | Bin 925 -> 1076 bytes .../users/__pycache__/models.cpython-314.pyc | Bin 1570 -> 1579 bytes Plataform_Web/users/admin.py | 25 +++-- ...muser_especialidad_alter_customuser_rol.py | 23 +++++ ...lidad_alter_customuser_rol.cpython-314.pyc | Bin 0 -> 1491 bytes 26 files changed, 416 insertions(+), 34 deletions(-) create mode 100644 Plataform_Web/documentos/migrations/0002_factura_alter_documento_options_and_more.py create mode 100644 Plataform_Web/documentos/migrations/__pycache__/0002_factura_alter_documento_options_and_more.cpython-314.pyc create mode 100644 Plataform_Web/gestion/migrations/0002_remove_patrocinador_contacto_equipo_and_more.py create mode 100644 Plataform_Web/gestion/migrations/__pycache__/0002_remove_patrocinador_contacto_equipo_and_more.cpython-314.pyc create mode 100644 Plataform_Web/pruebas/migrations/0002_prueba_telemetria_variable_delete_testgeneral.py create mode 100644 Plataform_Web/pruebas/migrations/__pycache__/0002_prueba_telemetria_variable_delete_testgeneral.cpython-314.pyc create mode 100644 Plataform_Web/temporadas/migrations/0002_temporada_miembros.py create mode 100644 Plataform_Web/temporadas/migrations/__pycache__/0002_temporada_miembros.cpython-314.pyc create mode 100644 Plataform_Web/users/migrations/0003_alter_customuser_especialidad_alter_customuser_rol.py create mode 100644 Plataform_Web/users/migrations/__pycache__/0003_alter_customuser_especialidad_alter_customuser_rol.cpython-314.pyc diff --git a/Plataform_Web/documentos/__pycache__/admin.cpython-314.pyc b/Plataform_Web/documentos/__pycache__/admin.cpython-314.pyc index c50c4acd33b8d644e8b41ebb171efa8a00a67cb1..9ca0ba27734a7574026422548ca214cba0e7c53e 100644 GIT binary patch delta 1003 zcmZ3?d4i8mn~#@^fq{YHfZ^)QgRB$zB$Q4uFfcSQ#4!XhdNO!0mN3dQ#4!djc`|u0 zmoR&0FV+V zjv#hr22GBaAbCy3TdavGxtV#IOt&~)@{>z*Q}aslZ?U^2CYO{JB_@N^z%Ub(@!4tO z1y!XWwi5O*24lt`MsbE5juMU_rV`FD#uBbD25ZI=Ze<2d_Q}GGGgwwK`mLP2o>7f) z<>YIO^^AOz!GD>8<#g>7g$8U zvoW)pe`R21H7}Bc>BkXn3=9m342g^l46zI)j6n<~OmUJW%wi1rj6r71B`iTKC9FZL zC2WL4_7)E`ekRK?_SP41f~*Clnj(IXyV)2R7}P+Zp$P0NK2YF@Lv=WUB3rLGu`D${ zH$NpcM+Kx;0z`lvFU7#XpveXaPxjQ@f}+&o#9Qo{ppY&}g@isRUW(*E>X^U+_27`! zWCm+0G65N-03sAYgc69*1Gx&6dK?@eE;0m(f(VeE#p=l69M9O`^FTWHa^HWN5QtgVY7#J8p`K36Pfq~%zGb1D8T?U2w3~CP;+1llrP1o2&kTZ$=AW4vn4~{|g!MmYFfg%$m9k%El=#BL%V<8q^t!O}MPcR7 O47?DflAl1rVEX}5Oy%VO delta 508 zcmX@Xx0sVpn~#@^fq{WxNzjzccBYAZ5=uo33=9nnaSTC>o(vw0C5-Y6ag0Gso=hIh zCCu^+v5Wy66Bme1OcZ0}ns`Rpk}Zf;nL(57CCCg-##^k3DY=<>nvAzNUGkGlb5rw5 z@{>VQFw6vHe72ix$fzn8#$e1C#3;^?!%@N>#8ko&##q7`#$e4@!UZyPas}fI7EMM! z&B-E6YK)qbt(oc>xhL;tl4Ip&U|=Yoe2>W}p6wP}NoGlDPW~;<iLv$0z3`78j>vCYQv=7lXXy z;7}w4GKdXEuz(yW$H2hwvz?)V;el{$gU<~ilLqe_BDxK}-`SX1&A&1*vzix)z%=-2 zvQMsHQ<^-VO*|QFiYQ11EDbXG7Kcr4eoARhs$G#b0|Nsi$arH028IvJjEszT85Hg^ v$Ub0XYnN-1o4|RQQR)j5C!_g<(CebA7e!S+GjKARe`aQ2lKun|2HOb$Ne_4C diff --git a/Plataform_Web/documentos/__pycache__/models.cpython-314.pyc b/Plataform_Web/documentos/__pycache__/models.cpython-314.pyc index a7eff1df9aff0701aad4f497a493b07f8800594a..b64606a9e3eff09b3d1162fbe7031d82b11ef38a 100644 GIT binary patch delta 2421 zcmew--lf2&&Bx2dz`($uXSh0Z4);Vp3C5y{>d`Wy42ldv?BWbT9I+fG%pe5}3?-aF zEXoX;oD(}78P`laCB-gU!V)A_!a6yTQF1a1<4N8ijv#JxMyTS+=NQGc6&YfMf_Q>> z&6%L0!m(@t8W1)zsmKsJ*?>vBK8PcTFNoiq1tM1>4t9osI75)23CskEAR%#v63H+I zW5yt1afTd@5~(1O66r9;5}7atYsL~;Wd=?0TbwTW$)&lec_sO`*faCe@{4j)t3>?r zbCZfv6;e`j6jET)E17O_8TpyXsl}SiMIe3=F9QR^ zE%ubuw8YY!l8{m<1_lO~)Z*l#%!1_1!<+L^&D3PR#hR3pn3sKvC9gCmr-++@fkBh; z7EfYnNq&4@etCRiO3Ez}xD$%w6N~ecGZRzti!~WlK~`dAfyR|V&Gv2Vl)CJ4yGz51&v#bnwm_v*z&-^eM>YwwIn_{ zu_QG;zbG>?J|(lbASbbMCF3oY;?$h9Vo-WfD^dbEm_0texTGjP{+1xz<$6#da|Q-& zhGJy~28ITP8$x2!wI^y%ke!jVK;*ij^+iSN%Zj!a6zp~+Uf_4Qz~NA&xcLohCL^Qf zXOP(@M${i&AfK1VdSqJ2{kt zIW(DWai=9F6=fzTCWFl2VPIfzgYhAH*-|o#Q}gmmK}pmlvpDte#(V{R1!qSWkh#hE zdC92-CHc2FoT04A_c;{mZwaU57Z+!y7R47NmK5bDXXYiQ{UfC7G7pw!X@CHp@&1G$ILrCJfkkTa~r4=F@ zTrRjLUlB@a@V+4|d0kljlCb)QkSoGg4L%<@7zD+y3#eTZP+L%W!9MhgK-gqKZuzk9 zEX=H`9~qcgRX=etvN|$;XJcj6_{zY_ssYK2pj@2{&2eA~1Lo7oH zV-Q0LQ=C%?vlv4@Lo7=G*TnbY{ER_N@FJKkmSy5w@p`T}rXc1Z7ISE>F5v)|wXEU{ zL2U4{mJ?J3lyC)clyHYJl<)*`Dl=$u-C}o3OfD%cN<=D96><_4QgaK6Qi~IdI2jli zz=_cl6k8>!3L1}^)@W)nL(18d%=FBX;#++6DXGbsxrsUP1v!bysm0(j62)(zasli& zIdG$BIf$`@C5WknHHf){4O}I$-r|9}NzXU6B(W$76vZ4+q2eM?-uBaEM@g0S z3=Bn}WC^yo2xLc*0w|$?)IvfVTyB6SlR0t!x#cUNe@XJ#N=TJVlrY?X3%7=f_Xxr zidjKdp%fHZpwMKx#SRVbTkM&TU@ihxt4O6OINjgkhXw+y9Q6iyLmup^8-n$cGgRj5 z%+#47x1e~1$$FcWHY@aYFkj%exxirq@fj#I{4{w{LJk&iAh#3+g2F5l6x=*6kO+lj z*esAZC|tnKfCOzEsEB1ON&qaYfJp#tQ-QSNIYd+`qFhv1)!~U}Dw$&cVoP`+VR>67$mY^-_|GKyJRpQ(Bx_RIHbqKe?V;DPIrdcvj#1l++w>t_QmWoMa$| zfRe#24x8Nkl+v73yP`q{1_qGhi$VH6Ff%eT-er)v%bk delta 1285 zcmeBD_$SV%&Bx2dz`(%J^L$FCJm*9{3C5U->d|aLEXoX;>=WlXG9H-tK#EnQge6FH z;{PX%v6DYAiU$O7n=^qlF))+}#j*v+LDrSL$=8^*OiP78Zh$#m zA>{DN_GGa7-?1XC50g2pXIO--g-Y$chXFuuiElA2qPUzC`VsL6PXr8qSwtr%pIT9N$Z zb*%E5#vtoKmNYQj5E7fNJyCmt?2M!ZBFp6#%3V+}*uZ#!-{=B|QIXu{->jL8jH;7U z+11$OK>?;ec_Ou?p978j)E6=&w>m2xvMFa$%n zhd1YGGTma$%`eF>suJ)8QTmh1ICLj}=1?$Zy2VkPpH@LK^O}93IRo_#ia$Msl_GvnoPG?@=J>HZ?X876y$UYH+XU|x3%^I zA&KikN|%I`R)}nHx!@jqMJTSp`vV7qp!jtG#Y+N;3p6*BZLix{cSXQ$@-c3C(+9$m z*M-$D39D}ixgu=U;Pah@nN{^812e1YCoV=-QiP0q>j{5G*# zAfL1P=BK3Q6oG`n$pE4X?wODI>%p0N8+3wEzGB diff --git a/Plataform_Web/documentos/admin.py b/Plataform_Web/documentos/admin.py index 97dc990..d14f08f 100644 --- a/Plataform_Web/documentos/admin.py +++ b/Plataform_Web/documentos/admin.py @@ -1,13 +1,38 @@ from django.contrib import admin -from .models import Documento +from .models import Documento, Factura @admin.register(Documento) class DocumentoAdmin(admin.ModelAdmin): - list_display = ('titulo', 'categoria', 'tipo', 'temporada', 'subido_por', 'fecha_subida') - list_filter = ('temporada', 'categoria', 'tipo') # ¡Filtros laterales muy útiles! - search_fields = ('titulo', 'descripcion') + # Columnas principales + list_display = ('nombre', 'categoria', 'tipo', 'subido_por', 'fecha_subida') - # Esto hace que el campo "subido_por" se rellene solo con tu usuario al crear un doc + # Filtros por área técnica, tipo de documento y temporada del documento + list_filter = ('categoria', 'tipo', 'temporada') + + # Buscador de documentos por su nombre o descripción + search_fields = ('nombre', 'descripcion') + + # Para asignar a que temporada pertenece el documento + filter_horizontal = ('temporada',) + + # Automatización: para rellenar el creador del nuevo documento de manera automática + def save_model(self, request, obj, form, change): + if not obj.subido_por: + obj.subido_por = request.user + super().save_model(request, obj, form, change) + + +@admin.register(Factura) +class FacturaAdmin(admin.ModelAdmin): + # Herncia de Documento + list_display = ('nombre', 'empresa', 'importe', 'categoria', 'subido_por', 'fecha_subida') + + list_filter = ('categoria', 'temporada') + search_fields = ('nombre', 'empresa', 'descripcion') + + filter_horizontal = ('temporada',) + + # Mantenemos la misma automatización def save_model(self, request, obj, form, change): if not obj.subido_por: obj.subido_por = request.user diff --git a/Plataform_Web/documentos/migrations/0002_factura_alter_documento_options_and_more.py b/Plataform_Web/documentos/migrations/0002_factura_alter_documento_options_and_more.py new file mode 100644 index 0000000..d29ff00 --- /dev/null +++ b/Plataform_Web/documentos/migrations/0002_factura_alter_documento_options_and_more.py @@ -0,0 +1,66 @@ +# Generated by Django 6.0.2 on 2026-03-06 19:29 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('documentos', '0001_initial'), + ('temporadas', '0002_temporada_miembros'), + ] + + operations = [ + migrations.CreateModel( + name='Factura', + fields=[ + ('documento_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='documentos.documento')), + ('empresa', models.CharField(max_length=100, verbose_name='Nombre de la empresa')), + ('importe', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Importe (€)')), + ], + options={ + 'verbose_name': 'Factura', + 'verbose_name_plural': 'Facturas', + }, + bases=('documentos.documento',), + ), + migrations.AlterModelOptions( + name='documento', + options={'ordering': ['-fecha_subida'], 'verbose_name': 'Documento', 'verbose_name_plural': 'Documentos'}, + ), + migrations.RemoveField( + model_name='documento', + name='titulo', + ), + migrations.AddField( + model_name='documento', + name='nombre', + field=models.CharField(default='Documento antiguo', max_length=100, verbose_name='Nombre del documento'), + preserve_default=False, + ), + migrations.AlterField( + model_name='documento', + name='categoria', + field=models.CharField(choices=[('aerodinamica', 'Aerodinámica'), ('chasis', 'Chasis'), ('business', 'Business & Operations'), ('e_powertrain', 'E-Powertrain'), ('electronica', 'Electrónica'), ('sdf', 'SDF'), ('motor_transmision', 'Motor & Transmisión'), ('software', 'Software'), ('normativa', 'General / Normativa')], max_length=20), + ), + migrations.AlterField( + model_name='documento', + name='descripcion', + field=models.TextField(blank=True, null=True, verbose_name='Descripción del documento'), + ), + migrations.RemoveField( + model_name='documento', + name='temporada', + ), + migrations.AlterField( + model_name='documento', + name='tipo', + field=models.CharField(choices=[('fabricacion', 'Fabricación'), ('diseno', 'Diseño / CAD'), ('concepto', 'Concepto'), ('simulacion', 'Simulación'), ('dossier_patrocinado', 'Dossier Patrocinio'), ('informe', 'Informe'), ('tutorial', 'Tutorial'), ('otro', 'Otro')], default='informe', max_length=20), + ), + migrations.AddField( + model_name='documento', + name='temporada', + field=models.ManyToManyField(related_name='documentos_asociados', to='temporadas.temporada'), + ), + ] diff --git a/Plataform_Web/documentos/migrations/__pycache__/0002_factura_alter_documento_options_and_more.cpython-314.pyc b/Plataform_Web/documentos/migrations/__pycache__/0002_factura_alter_documento_options_and_more.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0cf2119b89f62effaa169e4c0002b2df604f21e5 GIT binary patch literal 3372 zcmdPq+zUY+@fn}Ojmhy%l{P{wBu1_p)(hB$^GMo)$k#yEx`CQl|0<`QNP zmJ$|u22ln@h9G8fh9H($<^Zs1P<>F!gc-spVGUwbX3%7P3F7)`GTq|J%}g&!EXmBz zE55~+o1c=JQ=ANvgJD4^5g5~euz66PS?AU!>%5|&uj03N6+BubGX zh%tyMmOVfKNf62exiywEKm^J~q5}AkI8bJQ7?goT1xO%qpv)lVAm$*JAl4u@b2f;O zF;ftGEPH?ygojKjGQ_0>aRhOiGeJa+nS!`t*#l%CJY-UlA&x1ID~LOY#~d1l#!Pz5 zLA*hXL3}~{`bDkx!s%T851 zelYZB3{r~|2~x*uFRoBliDeJaKz2Wbt;i6h5u_QUg&87xoF$?`+9hH^I?4>1Mz=V9 zVfpM9yIW#%Noi5yE#8#;aTpaf>6rC?&NhGcUc0S2ry+IU_N?xHKsC8_E8MVX13Ot;vRGx9T&Q;Wfd zXfh-87lBgtE$)=m;^d;tg5=Enyi$-KTwwgeoAVS>Qc+#Rnv|26mwk&RuQVqI?4Vnm zC8?nJN=!+-#Zr=4kbjFkGcPT_C^uD;xkw%4RAmqW^1v;mq!*u9oS&STn37*yB?32~ zSP#zBWV*#ul$rxdi;y7XXJBAh$pEfR;2~6ei^ssgz%V{DFS8^wF$Wara07~Oi5nOg z7{$W{;&U@obCZhli!~XGI2jliG&wah0eOl%=4i;9rnh1gYXc#-_#>%wl@ujr=2h{y z>IT4hnoPI2Q*%<2ON#RIKz4#^HCHhI@Me&JCetnE;*_*o%)u^hnoPF@bMs5`i{eX) z67!04GmAlS1gg<|L81z33L!A@!<+L!PAkq&D=AMbO1;Gq3}tCD-Qvv4FUn0U$t+8( z5_V6`OD#&wQP5ZLg9&PKfZUXpm{gRRoCr<@AUCxW4gj^tk3IR~T%zRCzB3%XshFk2O&_u;_i=(8p1eCOMZgGS_S(;3@Sn^AX z@^7*DmlWk|ir?ah2dA3&_*-1@@wxdar8%kb@wa&5;|og@b3o-leEco``1rKUqT-UA z%)HdRe2{cXYC&pVN@`wmW@>Q}s3N|_?F=pteL-2d2vh;z;`Pr<4axVy=`rp`X7M4ZIjOm+B}JKu z@gZ*RF#$P=C5fPn93P&V6obffF^I-o3^<3SL28=#M39f-;R@rS1#Em`UP^p!eo?Ak zL1huB%>*Xc85kIfnV1+D+892tF>tEi;4u8a$}Gax;PZipfm8T8hukF&xf_B~4+Iq! zs9jewyQE}xz~w?n)b)_qiy^VsLsBk=q+Acly%>^vJ*4zvNa+U#1{Wp|rVk7ZVN6jV zDvc={L=`Z(F@IrTPLNm91OxbU&MJhxjsmN-Kuhl zL*<5`%necb1^O2hjW+ll@V*e3b|ItWf=KBXR%TAF4;)~1U_Xf~-4K*S7L~rlA$x>D!C!6^o5g^lM5OwvX?ky!HQ+zia#+h==iaIU|@)5 zjb;79z#tsQ`h}f^lj{Q)*iyI-Ik=7$A{$&TxF=r`N)_hO;o3nKhOvBL zU`Sxe1W{!y6)YfoD_M|@gL@0&QjJSO8W+rbE(E4u5z2t5i)SD> zc1seHpY&3a^dKDtJy@nH3I>$}oN#$?1_kFyaDoCSZirDyAcY(@kZf;Pl*+)szz9li q@(c_NAD9^#89%czFe=_>(D=e;&B!)^>$-r-MFEv>4AzWnU;_Zn8jU^x literal 0 HcmV?d00001 diff --git a/Plataform_Web/documentos/models.py b/Plataform_Web/documentos/models.py index a4370f8..0d8c6c9 100644 --- a/Plataform_Web/documentos/models.py +++ b/Plataform_Web/documentos/models.py @@ -23,7 +23,7 @@ class Documento(models.Model): ('concepto', 'Concepto'), ('simulacion', 'Simulación'), ('dossier_patrocinado', 'Dossier Patrocinio'), - ('informe', 'Informe') + ('informe', 'Informe'), ('tutorial', 'Tutorial'), ('otro', 'Otro'), ) @@ -53,7 +53,7 @@ class Documento(models.Model): ordering = ['-fecha_subida'] def __str__(self): - return f"{self.nombre} ({self.temporada})" + return f"{self.nombre} ({self.get_categoria_display()})" def delete(self, *args, **kwargs): # Esto borra el archivo físico del disco duro cuando borras la entrada en la base de datos diff --git a/Plataform_Web/gestion/__pycache__/admin.cpython-314.pyc b/Plataform_Web/gestion/__pycache__/admin.cpython-314.pyc index fcd2106f693415ce94eadcac631d56004a0c394e..2383af1014cc99445441f27db3ce715c7bb686f5 100644 GIT binary patch literal 2283 zcmdPqxt>XI^?yYH@xtNDB-@gP!5D90MrIV;M>qgBVJf;#fVG?{O4gAMe|%gM}3UCH35$#IJ#K0YroH#I)~7FT?HZhlH>4v5VY zA75CSm;;sJkB?8wEGjMm>B`HGk1t|nU|_h#nwy`JnsbXawW6db@s?RTMYH@sg5h$&G2D$Z?gR@mkXmM&$aZF-LQD%CKyOCLZNNP@MZfZ$UW@3DZ zn|n+^PGU)7T7FS(e0XY7OnPc@NoIat3^-u)3Mz{@85kJA1jzbg9tH-6HijEKf(@=W zcz9b}i$IAJER8*UbWp>GtAsg-xr8N%rGzzzwS+B*t%N<6Lyxh9Gl;Q-3mjVPxA+lJ z;RuQyuy6b{*>16?<`xvC7AM|fOD!%*Ov%5+Uy@mnA76loIl;`_g8ZVA)cDlo{Ji|! z%;fxAoF%CsvBZ?bTl~rSc_oR-CHe8Gg{7GV`I?MH;tUK7n#^FTNCM`fl;1<|bz5!1a;)8KtW#I?cq0~>>YbVqKBJ481~BlZ|VOTpqu zF$7A*pcKq{iwm5Bk)wn87F%9^Zc zn(WwutqA0hB9ND``dkI%a}WWFGH5btsW=_9dqK_S7LpH!S$RF;^WnV*+hypj`l7$|_Wf&$_eUrJ(0 zYJ5g!Y7r=zRALPnEs$yuAVd~OKofRckDI5~*Pw)jE938b2+ za8kz`PCU?(5gbww&x4YsUlAzN7a4%uWe6gSK?Fz!Vmmk?n}NhYggVI8psd%%@IcrX zr;|ZS{WSS+@ug%X=B4NBfwE*#W>OKTp1j2dE)$E3SU`q?im4({m0ZLQ4)&15q|%(k zB1q{A$zmKusp*-;pbW_63o1<^9sp&LB2W@40)Bs!a4|5kx63ujP2jrB zDE)UA--i(+b@8Mqi_J~J~g$$S6_e~^HwWWCHN_JxUw(QJa~bwS08f{LFR zm>A7KD#bs5gb`*!RI)S5B2=<7%0gALGs=Dtf|<#FnNi{k6C0!K1k>xn$`^%|KQpjF MR7!pV34?tK01V*ixBvhE delta 741 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 delta 2243 zcmZoR?vm!y=HumJU|?Y2xj!xQ3g<*V3C6mK>b1&29LfxuoG(E#nvA#Da`RJCbBZ+? zZ*e)77MJAbh8Cw5O_pYqQfCLLU|?YQT)@b{kjT)$5X(@)7{pM*6vtY^EXI(}5F}W_ z63aSqgNTSCLtIJ_V-S-$6GTr5JCZmvk~jxgeDZw(c77JPV$N9B0FlWHc}2v6Sc6!D z*n-&2nW5%z$Fc@UfTTo%ID$BXxZrwtV_5@aKoUB!{IRS73J~?kWDsi*cMy*`3q-6$ z5T+p_Rw$M=Kn)^{Oa}47O&1B`6K5z94dO2m3u7n|4-!yj&=k7G?v|KbQd*Q)CFY!; zmz-KqlCO}Gs*sbYkOmf?oWU$xUnT6CTTql*oT#9$5Kxp~mYSN9U$l~`h?9YV;TC&x zMt){;YH>)Z5Ca2)Q&DPJszOR?adJ^+L2~Bd&3T&4w^);M67#ZevE-HJS3QNI`EG|t- zUCDflGe0jrB{e6tB(;c-fq?<6b|qtxAOizKG9yxOfMS4|fq~<*1p@;^!{jw$Qj=S` zC3TFLl^HY{tC$sZ6*QS{vE}9GCKaXLVo!y5dL`p6mg3Z$v|^A+YLhpxx;V4P#}}6r z#mC>`hlZXWR6ve_fuUF$WH`eOA+hP&6SXJE&PZOMvRr4O&H}j${00{|3_gP#v~qHY za2ykN>g27$a~UNjJFuG8-{Nw13~_b$5At*jE&{pq7N>JYVv$>BYEDX#2*_Kapz!8Q zPAo}H&o9bMyu}%kT2TU)zr_s?^8CD8oNk#psSt7Y#G>Sk%(DDjTyFVAshR0{-l>&E zpyYFlBiJ=0-Y?Y0=N4CSX;NkiYkqt|e$nI!98xTj3=9mD`&q>&zvR%amjKxe$~HwH zf)(V!wG0dlKiU}@7(Os@39&VJeUM<_6S>YSdx=+eh42OI;48c#4Q@C1M6UD6UE-5l zp?tw6@Csj0gZm8uvFic~mjo16IPKuNBH-NMc|%Czx{%T(A*B@}8(c29M_&<&Y4HBQ z#=tKM)hk_p!8!H{UtELx2Q~&FiR*$&mjsm-SnUwoFTYd%M9GDu@+*QB4PIcA6)y=W zF3{Xiw!Lm+-4y}12G8#-jI4$q7#LX%i$HM#_CPWy^kEp}BM|%Z9Q4va30fKmv6Zj{ z374==Vv-a_Ee$wg*#d+>nUybyIf%s^lsFg|7)rP%F-fw^1+jw4hshThRe9Oq8IUKI zZL%Prm{1UV5IZR6!wUqyNldb=TtVFC%#;0?6m((*W7z^!K<+}tLF_?1LA>zHFC5Dj zpa60}T&zeeTYwg-Vh}Hg4{ocP2IC?vB0Ry@F@xfvK3LP|9m7#LhqOA>Q(5{ncHOAoJ9 zC{9(#Pb*4IPE{z*R7fpWNX=77EiOn+&P*-VWG>y~UZ4no|&8l3G!6iz7Kd zuOu=AZ=XccKU&IPh04fZNEI}-gzl*FuENc*9 z1M({Syy-i8{9syF^J1v7gN6^roMt}N80}Uo%t6+A}*v?UJK&Amw`kL$kBe9oVPervJ&&s^Yv1aASEnMX>n>%u^yzkFnOV12ZEd<6Q=sy9~;A8Pvb9NHH3Ar1j@?=6qq0 ZVl@0>CCex?!ECzCM4N96vWyUi008@XMl%2a diff --git a/Plataform_Web/gestion/admin.py b/Plataform_Web/gestion/admin.py index daffb6a..0d47392 100644 --- a/Plataform_Web/gestion/admin.py +++ b/Plataform_Web/gestion/admin.py @@ -1,14 +1,46 @@ from django.contrib import admin -from .models import Factura, Patrocinador +from .models import Patrocinio, Pieza, Gasto, Ingreso -@admin.register(Factura) -class FacturaAdmin(admin.ModelAdmin): - list_display = ('nombre', 'empresa', 'categoria', 'temporada', 'subido_por') +# INLINES +class PiezaInline(admin.TabularInline): + model = Pieza + extra = 1 + +# PANEL PARA ADMINISTRACIÓN +@admin.register(Patrocinio) +class PatrocinioAdmin(admin.ModelAdmin): + list_display = ('empresa', 'estado', 'tipo_patrocinio', 'importe_economico', 'temporada', 'contacto_equipo') + + # Para editar el estado y pasar de En contacto a Aceptado o Denagado desde la lista, sin tener que hacerlo manual + list_editable = ('estado',) + + list_filter = ('estado', 'tipo_patrocinio', 'temporada') + search_fields = ('empresa', 'persona_contacto', 'email_contacto') + + # Metemos las piezas en el patrocinio, por si hiciera falta + inlines = [PiezaInline] + +@admin.register(Pieza) +class PiezaAdmin(admin.ModelAdmin): + list_display = ('nombre', 'cantidad', 'patrocinio') + search_fields = ('nombre', 'patrocinio__empresa') + +# CONTABILIDAD (Gastos e Ingresos) +@admin.register(Gasto) +class GastoAdmin(admin.ModelAdmin): + # Heredamos los campos de Contabilidad + list_display = ('concepto', 'importe', 'categoria', 'fecha', 'temporada') list_filter = ('categoria', 'temporada') - search_fields = ('nombre', 'empresa') + search_fields = ('concepto', 'observaciones') + + # Barra de navegación por fecha de gasto + date_hierarchy = 'fecha' -@admin.register(Patrocinador) -class PatrocinadorAdmin(admin.ModelAdmin): - list_display = ('empresa', 'tipo_empresa', 'tipo_patrocinio', 'estado', 'temporada') - list_filter = ('estado', 'tipo_empresa', 'tipo_patrocinio', 'temporada') - search_fields = ('empresa', 'email_contacto') \ No newline at end of file +@admin.register(Ingreso) +class IngresoAdmin(admin.ModelAdmin): + list_display = ('concepto', 'importe', 'categoria', 'fecha', 'temporada') + list_filter = ('categoria', 'temporada') + search_fields = ('concepto', 'observaciones') + + # Barra de navegación por fecha de ingreso + date_hierarchy = 'fecha' \ No newline at end of file diff --git a/Plataform_Web/gestion/migrations/0002_remove_patrocinador_contacto_equipo_and_more.py b/Plataform_Web/gestion/migrations/0002_remove_patrocinador_contacto_equipo_and_more.py new file mode 100644 index 0000000..84fb76c --- /dev/null +++ b/Plataform_Web/gestion/migrations/0002_remove_patrocinador_contacto_equipo_and_more.py @@ -0,0 +1,92 @@ +# Generated by Django 6.0.2 on 2026-03-06 19:29 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('gestion', '0001_initial'), + ('temporadas', '0002_temporada_miembros'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.RemoveField( + model_name='patrocinador', + name='contacto_equipo', + ), + migrations.RemoveField( + model_name='patrocinador', + name='temporada', + ), + migrations.CreateModel( + name='Gasto', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('concepto', models.CharField(max_length=150)), + ('importe', models.DecimalField(decimal_places=2, max_digits=10)), + ('fecha', models.DateField()), + ('observaciones', models.TextField(blank=True, null=True)), + ('categoria', models.CharField(choices=[('aerodinamica', 'Aerodinámica'), ('chasis', 'Chasis'), ('business', 'Business & Operations'), ('e_powertrain', 'E-Powertrain'), ('electronica', 'Electrónica'), ('sdf', 'SDF'), ('motor_transmision', 'Motor & Transmisión'), ('software', 'Software'), ('general', 'General')], max_length=30, verbose_name='Área del gasto')), + ('doc_justificativo', models.FileField(blank=True, null=True, upload_to='contabilidad/gastos/', verbose_name='Ticket o Factura (PDF/IMG)')), + ('temporada', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='%(class)s_registrados', to='temporadas.temporada')), + ], + options={ + 'verbose_name': 'Gasto', + 'verbose_name_plural': 'Gastos', + }, + ), + migrations.CreateModel( + name='Ingreso', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('concepto', models.CharField(max_length=150)), + ('importe', models.DecimalField(decimal_places=2, max_digits=10)), + ('fecha', models.DateField()), + ('observaciones', models.TextField(blank=True, null=True)), + ('categoria', models.CharField(choices=[('patrocinador', 'Patrocinador'), ('donación', 'Donación'), ('premio', 'Premio'), ('recaudación', 'Recaudación'), ('Cuotas', 'Cuotas'), ('Ventas', 'ventas')], max_length=30, verbose_name='Categoria del Ingreso')), + ('temporada', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='%(class)s_registrados', to='temporadas.temporada')), + ], + options={ + 'verbose_name': 'Ingreso', + 'verbose_name_plural': 'Ingresos', + }, + ), + migrations.CreateModel( + name='Patrocinio', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('empresa', models.CharField(max_length=100, verbose_name='Nombre de la Empresa')), + ('persona_contacto', models.CharField(blank=True, max_length=100, null=True, verbose_name='Persona de contacto')), + ('email_contacto', models.EmailField(max_length=254, verbose_name='Correo de contacto')), + ('tipo_patrocinio', models.CharField(choices=[('economico', 'Económico'), ('piezas/materiales', 'Piezas/Materiales'), ('mixto', 'Mixto (Dinero y Piezas)')], max_length=30)), + ('estado', models.CharField(choices=[('en_contacto', 'En contacto'), ('aceptado', 'Aceptado / Activo'), ('denegado', 'Denegado')], default='en_contacto', max_length=20)), + ('importe_economico', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='Importe (€)')), + ('fecha_contacto', models.DateField(auto_now_add=True)), + ('contacto_equipo', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='patrocinios_gestionados', to=settings.AUTH_USER_MODEL, verbose_name='Persona al cargo del Patrocinio')), + ('temporada', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='patrocinios', to='temporadas.temporada', verbose_name='Temporada del patrocinio')), + ], + options={ + 'verbose_name': 'Patrocinio', + 'verbose_name_plural': 'Patrocinios', + }, + ), + migrations.CreateModel( + name='Pieza', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nombre', models.CharField(max_length=100, verbose_name='Nombre de la pieza/material')), + ('cantidad', models.PositiveIntegerField(default=1)), + ('patrocinio', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='piezas', to='gestion.patrocinio')), + ], + ), + migrations.DeleteModel( + name='Factura', + ), + migrations.DeleteModel( + name='Patrocinador', + ), + ] diff --git a/Plataform_Web/gestion/migrations/__pycache__/0002_remove_patrocinador_contacto_equipo_and_more.cpython-314.pyc b/Plataform_Web/gestion/migrations/__pycache__/0002_remove_patrocinador_contacto_equipo_and_more.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..23ba326f27b62507c4d1ae63ff9bdcdd7e7ec954 GIT binary patch literal 6046 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 literal 0 HcmV?d00001 diff --git a/Plataform_Web/pruebas/__pycache__/admin.cpython-314.pyc b/Plataform_Web/pruebas/__pycache__/admin.cpython-314.pyc index fd6e07bd99124473e29380e771b621cb3772eeb8..bfe8d02906f82d13a7c72b4af683951756773628 100644 GIT binary patch literal 2191 zcmdPqilkpa7VoGjio+k4xwt%A2)TG2)Tp_7Bskx~oMVX1W zIKmQ(G82<>Qjr~K=BvLP{J6*P{I_)R>B<1QoSi&B}q|Bhn ze2WiehG$+*W?t$_20u-XTO9H6d5O8H@$t8~;^TAkQ%Z9{Y@Yb|!qUVXs0@F6d|GBv zaS2FQUVeOh5h&ftvY(_`F?%;FIqj1O^hj|s?0EJ;kuFUpM%Pfdy`0EYrd zd2VK&UO{CM2Ll5Gm;hN{3`&1(3^#a08eDJi@V2-X3Bsg_3L-9O5HX+xkpRL)kU#=^ zz)zE-2$YG6xItEcEH2^&u~Eny8}gSb1ELyxh9Gl;2#D~MT{L6iL!Hze^mg3{70p0w2DjKuiN zyv*dxe5hAgZ?Wa&=Oz`U-r`J7EJ;nzFUm|T5@%pwxW!qLnp==xl$erui?=8>F(2AtTt%tHr8y;uDfz{k+}MKZ z7EexQaY=kiW^qAIV&yGvFfT1LrzExL7H@HCVo`ENd|GB|PD=4DzLdn0)cB0d)FO~* zB{=YIv1fvlY;h5`Fct&34Mc!qp;(Q9fuW7zfpA2F&j&UJVciDr4{QvgHVwWX*cilA z8vH)6F$gGJ;8SREheQ)dBlghOKn;C`66PT05|$vA64oHr61G@&J;oA_AaLj_Gib8i z;zy(%aOgwB8ya40kmL-DlH$^&%#=h;rdxs#@%VT|;KPOB@uSHE33NV~Vn_^Xa$yVW zB2ZyaBo7J{1rPzwHcB8Cw!l*XNq`8D+G3C{P~e$E0?!r_c!uD>6Og;WCkG2PkPhsj z2C}_@0bUg8A%z;KI06+#thab!MG=;e;w{a~Oi4_M&rMCqOi8@ORRS*sVZk7T5Q>k7 z1_e9rpaA&{Yr@e6`5i>)F)%O`gEDd(!v{775!(iz8zLqxzK{e0QsAe_cZ)A2D={xU zUoSa74^+SvfhxOOY~Vt$xQGR06u3M96;8K!LlTopa}tZ7g$OtbK-v5jM^S2eW-%z) zbNPabPl*3PX|MeD`#bE;}m+gu`RUD|yFW$hw!0>^Yk&*E(gTj3V zgNqCXUpSZ;`6h&37uC2Zs_}(^iIEQ?QhHrn>!P?8SmXm20~33@T$9`cw#$s-Uzm6q z6(^`(7gD+?r1Y7Amr?OEGXs;v2axaw1(-^%%Z$=rn7A0_C!}5%Q@bdp_L+f;Q68jH r<^xFhgA`09$7M#zFHFpgrW0JRi>O=_QTfck%xDTyDfI~?4E7NK_c+iQ delta 472 zcmeAdY+>Wm=HumJU|?W~e>^SImvJJWgi;X$149Et977PJCxZuL38Oqi9AglZCzA(r z39~#yEMox2#3jm{%;F3|EU}CMToW%StFQ&JDl=%Zy#yJg$#{!3F(o%MPm}Q$cSve+ ziF;~ZYEfd&qgBVJf;#f+UgP2QLf>=segIG)0f*4EKgP1@j-4a03 z=?F4yC4-+P>n*mt{M@9X)LT4hsmU3M@tJv<$(i}LI3c{W%)DEi$%!SY>G?&OiMKdQ zQgaLPixN{3HJOUI85kIfc$66!7&MuSI2afhZgHoi7AF^F79?lp=iTBeN-ZwUDM?Jp zFP<#RWInl#MO#8NKEAjlu_QA&KCz^vC^MlWW4ahMuEP4>y2>`IgS*u|4UdWzUVGGJ*5kW)Bpa`RJ4 zb5iY!WEmJ37(pf)GcYiGU}j`wyvv|)mqGpkBU`&%liURE%ZxH#n3x%DCX`+mSHCE( U{+WT9(dIKV1C#70kTBRz0P^m8k^lez diff --git a/Plataform_Web/pruebas/__pycache__/models.cpython-314.pyc b/Plataform_Web/pruebas/__pycache__/models.cpython-314.pyc index 7bf436781529812f860770e5c19372b5d111e36f..5a56fd1d87fe52544c12debeb99691523d814618 100644 GIT binary patch literal 4854 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 HgS`O&!M8J5 delta 843 zcmeySx||;GAJ?xF^e+Jo7G(`$ zRc6p+dkIpk$#{z`H$NpcXW~0)RW^_a0|Ue71V#piM1}^2ScVeDAchjAIF=G-F@}7G zAb}E=$p;uEC%ZHLuQz9cC@&ELTfr^P5X55w6B7>N6=x_B3F0de4Pz(~3*uL1&=kDI z9gyRY*zAQ2;5>WV*$bn^+N_lbV-al5vZtEVU>p zzc@8MFEKZ@RDpqk!9OW0wPdmcv#4N>LP=_Ii6&zaCj$e6CUX(TWG7}vK`@8$7H585 zd`fCgYDwzkC(NphvXi-3r1b?rHb9-A=bKuRSj7VpQGg0n@q>89FmCE(I~H$7&dFUY zR*Zs^kFo@53NSD*$TBc66pJ!2Ftjn;5LfNsxgn>2fkXO+i1Gztl^%{FNd^XnBI(Hv ztQAI@jJH^dQ*+Xa85tND)QY4S7#MD`$Hy0!6vfBi5(ZfXwO0=+s5JR0t0o)R1i{H7 zY_{?oNu|Y^d8x(4RiaK%mV%mse?e+dVo7Fx-eh04D#appu(?p9G{uXAKrRpl5h5T$ zbn-toRYtkVD(vcv@{@hojTl)b*RxA-OM@g8L4?HQi|k@LnvA!2PO4pzEdv7sDEx~-{{6tr$jEq?LFO)l`WF^?MzaZO({(25d}EMjgt!3! D9}nG8 diff --git a/Plataform_Web/pruebas/admin.py b/Plataform_Web/pruebas/admin.py index b7de1ae..c2bb061 100644 --- a/Plataform_Web/pruebas/admin.py +++ b/Plataform_Web/pruebas/admin.py @@ -1,8 +1,50 @@ from django.contrib import admin -from .models import TestGeneral +from .models import Prueba, Telemetria, Variable -@admin.register(TestGeneral) -class TestGeneralAdmin(admin.ModelAdmin): - list_display = ('nombre', 'fecha_inicio', 'fecha_fin', 'categoria', 'temporada') +# INLINES +# Usamos inlines que nos sirve para cuando se este creando un registro de Telemetría, podremos añadir sus Variables en la misma pantalla sin tener que ir a otro menú +class VariableInline(admin.TabularInline): + model = Variable + extra = 1 + +class TelemetriaInline(admin.TabularInline): + model = Telemetria + extra = 0 + +# PANELES DE ADMINISTRACIÓN +@admin.register(Prueba) +class PruebaAdmin(admin.ModelAdmin): + list_display = ('nombre', 'categoria', 'fecha_inicio', 'temporada', 'realizado_por') + + # Filtros para encontrar los test dado una temporada y una área técnica list_filter = ('categoria', 'temporada') - search_fields = ('nombre', 'descripcion', 'resultados') \ No newline at end of file + + # Buscador de texto + search_fields = ('nombre', 'descripcion', 'resultados') + + # Una barra de navegación en la parte superior, para poder hacer clic en un año y en un mes y mostrar todos los datos de ese me + date_hierarchy = 'fecha_inicio' + + # Mostramos los archivos de telemetría directamente dentro del test + inlines = [TelemetriaInline] + + +@admin.register(Telemetria) +class TelemetriaAdmin(admin.ModelAdmin): + list_display = ('nombre', 'prueba', 'fecha_subida') + + # Filtra test de telemetría basandose en la temporada o área tecnica de su test correspondiente + list_filter = ('prueba__temporada', 'prueba__categoria') + + # Buscador del nombre de la telemetría o por el nombre de la prueba + search_fields = ('nombre', 'prueba__nombre') + + # Mostramos las variables de su telemetría + inlines = [VariableInline] + + +@admin.register(Variable) +class VariableAdmin(admin.ModelAdmin): + # Aunque se pueden crear desde el Inline, dejamos su tabla propia por si fuese necesario, por prevenir + list_display = ('nombre', 'unidad_medida', 'telemetria') + search_fields = ('nombre', 'telemetria__nombre') \ No newline at end of file diff --git a/Plataform_Web/pruebas/migrations/0002_prueba_telemetria_variable_delete_testgeneral.py b/Plataform_Web/pruebas/migrations/0002_prueba_telemetria_variable_delete_testgeneral.py new file mode 100644 index 0000000..8bc4e3b --- /dev/null +++ b/Plataform_Web/pruebas/migrations/0002_prueba_telemetria_variable_delete_testgeneral.py @@ -0,0 +1,67 @@ +# Generated by Django 6.0.2 on 2026-03-06 19:29 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pruebas', '0001_initial'), + ('temporadas', '0002_temporada_miembros'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Prueba', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nombre', models.CharField(max_length=150, verbose_name='Nombre del Test')), + ('descripcion', models.TextField(verbose_name='Objetivo / Descripción de la prueba')), + ('fecha_inicio', models.DateField()), + ('fecha_fin', models.DateField()), + ('categoria', models.CharField(choices=[('aerodinamica', 'Aerodinámica'), ('chasis', 'Chasis'), ('epowertrain', 'E-Powertrain'), ('electronica', 'Electrónica'), ('sdf', 'SDF'), ('motor_transmision', 'Motor & Transmisión'), ('software', 'Software'), ('general', 'General')], default='general', max_length=30)), + ('resultados', models.TextField(blank=True, null=True, verbose_name='Conclusiones y Resultados')), + ('realizado_por', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pruebas_realizadas', to=settings.AUTH_USER_MODEL, verbose_name='Realizado por')), + ('temporada', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pruebas', to='temporadas.temporada')), + ], + options={ + 'verbose_name': 'Prueba', + 'verbose_name_plural': 'Pruebas', + 'ordering': ['-fecha_inicio'], + }, + ), + migrations.CreateModel( + name='Telemetria', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nombre', models.CharField(max_length=100, verbose_name='Nombre del registro')), + ('archivo_csv', models.FileField(upload_to='telemetria/archivos_csv/', verbose_name='Archivo de Datos (CSV)')), + ('fecha_subida', models.DateTimeField(auto_now_add=True)), + ('prueba', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='archivos_telemetria', to='pruebas.prueba')), + ], + options={ + 'verbose_name': 'Registro de Telemetría', + 'verbose_name_plural': 'Registros de Telemetría', + }, + ), + migrations.CreateModel( + name='Variable', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nombre', models.CharField(max_length=50, verbose_name='Nombre ')), + ('unidad_medida', models.CharField(blank=True, max_length=20, null=True, verbose_name='Unidad de medida')), + ('descripcion', models.TextField(blank=True, null=True)), + ('telemetria', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='variables', to='pruebas.telemetria')), + ], + options={ + 'verbose_name': 'Variable de Telemetría', + 'verbose_name_plural': 'Variables de Telemetría', + }, + ), + migrations.DeleteModel( + name='TestGeneral', + ), + ] diff --git a/Plataform_Web/pruebas/migrations/__pycache__/0002_prueba_telemetria_variable_delete_testgeneral.cpython-314.pyc b/Plataform_Web/pruebas/migrations/__pycache__/0002_prueba_telemetria_variable_delete_testgeneral.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..91a8eb9dec2cd6a6ed4e713d1074c4d37b99e77b GIT binary patch literal 4344 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 literal 0 HcmV?d00001 diff --git a/Plataform_Web/temporadas/__pycache__/admin.cpython-314.pyc b/Plataform_Web/temporadas/__pycache__/admin.cpython-314.pyc index c57527b987ef2c7f4b7b1f9aca11263beaa37809..c681e16cde8b53806cbab5362604a354061f6848 100644 GIT binary patch delta 244 zcmaFOx`B;Pn~#@^fq{V`T6cBk0;Y+42N|^{UXT)HDPap@EnyF0E8z%YEa41dQfAO( zpZGnBm+=-yZf0t3Qc-@fCfDR3Mi*P&oXp~q_|%lllEkE()LYzOZdzteNovt8-s056 zqU4PDw9M3;l;T^05aIZY{G!aN{JfIHoXHy*OLf&57#P|ZKCm%}gfKSvd|+b`RcP@2 zz{Vgf*WiudNvd685iOFK?84+HD#5_OP$bE~z;KJhCO1E&G$+-rNN)0SCRKSpMzsl{ d*F{w?imHBQ;A2$#%*?QLPB12>_}gNIC!j delta 151 zcmdnM_L`MXn~#@^fq{WRA#h6OJ;sTA2N{(nUXbEtEny2{EMX5~QfAO(oA^J9kz;Zi zqs!!-j53p7FqX(kFfcH*F??WS5D8&y@cF>TAS~D5{eg`^RH4PUNOW>1lb@(40|P^m z7y|>tEe@O9{FKt1RJ$VS$#0lco(vw0C5-YQHj^il2XhIt zJcB5MB0~_fI71LiEMou%NGB>bVTSNaSc6!V88q2mg1DNDx7c#?Q&Mw^H5qSl6sMMy zWagz8CxfJ5m>tUaEaJt;z>vt0$k@OT%TU4?#8AQ%$1-u@5tdk%0GY{-j3NoK`~eD3 z)kstjM-XEWXAqY;3q-I)5bRWLafTos6DFvbP!O*;Ly2%0gE3=KQ67#Z)co-NM zCMz?kGD=PMWYT72n_S8i$;dPLJd+ip@MJFLP)$Jw1_mhx28Lo$1_p*Uh8yBa9XvPW zv@UQ+-w;v0Agt2EQ6$a4z)&PRxq~^FQD*WTW_fXWkb02G4GcHWut$SpH9C#6V!vL#!f8_2F({Jx2Kl_B{c5+VnR zkz4$Zp&=gep~0>}@xJ~pu0FRoa-pGCBnvW75k!F8QzSKcKAVQV9>{6D@$tzyiN(b! znaL&b@x`EMbZ{sFJDm-r9z=jlFP=U58(U)i2Mz`SvFrS*m-tn0a0p!IP`JpUa6?q@ z2A|LkQLQhWtO9He9^d(xSyewWFte(D;$mc#{?5kAs`izEl~oNAtRNHpG}&%(rer1N zrRVFVBo%?Z$_?cw=jWvrfvmj6>I+KIMIa4Dpnxipb^tjE^Bja5LnY#=MUs#kG)h4h_=b6a!jX{|aVmknkxy}3l delta 629 zcmaDUc$c3~n~#@^fq{V`FJMaMc9w~J67@C=3=9nnaSTC>o(vw0C5-Y6q6~@*K}_Nd zLCmp?0W2WZsMv%V!Y^SCVo_$$WPJ(ZYBJtp%gs+o%_&X>abcJZ%J|I1$iR@ukjU7; z5X(@)7{pM*6vte`EXFW#?*R+2g&g7xL7XN`5cMT|L0sYtCH!Fw#*9JS;tV+)B?3V_ zC4ym$B|>2g){G^>$_$#klfN>S2!XtFi>EBLC@H@V-grFo*yJ>Mc&^ zjKm_h%+#EeBI(Ju*#bquc1eQdWkCeU_#&~%MeG`kT9aq9ONoFjWd%ur2#^`Y<&#gc zC)R&wVPRGM$iTv?`iX~;Rr)&{E34X923A(JBCtb1s{J%sZgHk$CFZ5)>!l+zUY(i9#K7pPBF`YopvVx!EY1+b63ZL_HW8{9N|`W27$vMhtjY|UY%f7vO~zXs#i=DFnR)5O znoPI2ax>G55=%1k^NMe=<>sfP<`gG`l)*4Jl<|2N*g3HbC5%A~B}{SbCCouwu`JlE zRb+@|3*dw5L!wL=AsjuX5{_7w03iqunN(y5Vhm!6*Fj3qol93{L#oXQNE+_yM=VLrXZS(2JtkYALTl6Z?FH#0RisVKiV0Zy0fe=;cnk~-4C6EN zGD|WOb2RyGam0gl#mC>`ijU9DPbtkwjgP;@6CYn#nwSGJDL(!de|&seW>IlTPG(+e zUVeOh5hx&Ti4>P778E2V<)p@^q!y&+rKIL1R~CUn<`%zWXoyFAXs~Ngysy8DtIsVS zxQfiw;#(Y!DJgCs=M{mH;w^sP#JtLod=Lp1y~UMZkP1sNqVe&?C5a`O$?=ILB}JJ@ zr6sAw@$p5VsQnCzj#~-NRxzQ)sYS&xi77>y=`rp`X7M4ZIjOm+B}JKu@gZ*RF#$P= zC5dVIMY-|esYx-2z=%Pl%oqa$1EYAjR6H!s^a?7A*cliYzyyc^PP=UkAJ`Z;)o*YJ zUFT50#G$@|385kIDao9j&)vic|fq?;(L5k%W7#Kb< lGcq!MWn*Aeyw9NVg^ibyZ35SI0hNmaD&H7*8QH)F000yo8pQwr literal 0 HcmV?d00001 diff --git a/Plataform_Web/users/__pycache__/admin.cpython-314.pyc b/Plataform_Web/users/__pycache__/admin.cpython-314.pyc index de243a5a9ba054166ac0a4ab74cb77865c89f0ed..5f5d8363aafaf987cb37e8c65108b9582f6b7077 100644 GIT binary patch delta 619 zcmbQszJ)_wn~#@^fq{XcN@sQEVrB-0#~=<2vq2f3vnHx*D#kJf@IVESC`E=?Rue|B zz(jvhE)y_|fuV$b;yhQSCI$wE28LLM62>5g5~euT66PS*5|$vg64oI061G_O0D*~r z#U(lP8I75Y8FipqK~xDxEPH^^#J}S5*d#fFm`k{VSdeag^rlc0%VoS?R z%}FU<$>68Sc8jC5IJGD*F*o%VS6XIKaY;Ow&6$%3V=@=z=iK5+EiOn+&P>e7Oi4_+ z#gSPYUtE%ymZr&4#LK|IP{ao!_!$@&ZgFN7$0sJ2WR|6BvJ`;=tcV*V2MUi{tiq|e ziJ3W?ObAVy+>>`OnrhwR$;m7(iBHKaF33r&yu}UXrDf)nq!!)cEly1=O3sLfIC}C= z#{T+j1_p*Uh6lp24L%>(7=)b}8@xZTF^IY{Hu!#EV-S?OE}(o-K=}rz#tj~k3u3w- zn3=S>J}@wGa(`fEQD^(gz#_=j;Q4`%K~(O#i1tMhZR{%bK`KSrT6~LSKwe;HU|{gm zpboLD4cRl*j_7{CV=MWO-( zkvLFhENd*A2@`}P&oFU`w# zjhT!Ybs&a-$rAQhwg3Sz6NSL3o+F64gfoamnL(40ZE`H5p1MYeo4e*MwzSODoRs2~ z41StSx0s9ab8hjZ78j%@XC~%krX;3la!rW%T7#KbE19i?g_BB) fGxJi5i{tYPQi~ExGV}8`?`B@k$S65EnRPz^YZw@k delta 69 zcmZ3@vxtXRn~#@^fq{WxmG6{H=Z(C|j2s-Pxdl0?i7A`S87-MOI9wsT$>q#e92`ld V#hH1j#hZ^XFK1+wnw-PB9{_V96aoMM diff --git a/Plataform_Web/users/admin.py b/Plataform_Web/users/admin.py index b797f2c..81671c8 100644 --- a/Plataform_Web/users/admin.py +++ b/Plataform_Web/users/admin.py @@ -2,17 +2,26 @@ from django.contrib import admin from django.contrib.auth.admin import UserAdmin from .models import CustomUser +@admin.register(CustomUser) class CustomUserAdmin(UserAdmin): - model = CustomUser + list_display = ('username', 'first_name', 'last_name', 'rol', 'especialidad', 'is_staff') - # Esto añade una sección nueva al editar un usuario existente + # Filtramos por rol y área técnica + list_filter = ('rol', 'especialidad', 'is_staff', 'is_active') + + # Buscador de usuarios + search_fields = ('username', 'first_name', 'last_name', 'email') + + # Para editar al usuario con los datos insertados fieldsets = UserAdmin.fieldsets + ( - ('Información del Equipo (TFG)', {'fields': ('rol', 'especialidad')}), + ('Información del Equipo Gades', { + 'fields': ('rol', 'especialidad'), + }), ) - # Esto permite añadir estos campos cuando creas un usuario nuevo desde el admin + # Para crear al usuario con los datos insertados add_fieldsets = UserAdmin.add_fieldsets + ( - ('Información del Equipo (TFG)', {'fields': ('rol', 'especialidad')}), - ) - -admin.site.register(CustomUser, CustomUserAdmin) \ No newline at end of file + ('Información del Equipo Gades', { + 'fields': ('rol', 'especialidad'), + }), + ) \ No newline at end of file diff --git a/Plataform_Web/users/migrations/0003_alter_customuser_especialidad_alter_customuser_rol.py b/Plataform_Web/users/migrations/0003_alter_customuser_especialidad_alter_customuser_rol.py new file mode 100644 index 0000000..68dc9a3 --- /dev/null +++ b/Plataform_Web/users/migrations/0003_alter_customuser_especialidad_alter_customuser_rol.py @@ -0,0 +1,23 @@ +# Generated by Django 6.0.2 on 2026-03-06 19:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0002_alter_customuser_especialidad_alter_customuser_rol'), + ] + + operations = [ + migrations.AlterField( + model_name='customuser', + name='especialidad', + field=models.CharField(blank=True, choices=[('aerodinamica', 'Aerodinámica'), ('chasis', 'Chasis'), ('business_operations', 'Business & Operations'), ('epowertrain', 'E-Powertrain'), ('electronica', 'Electrónica'), ('sdf', 'SDF'), ('motor_transmision', 'Motor & Transmisión'), ('software', 'Software')], max_length=30, null=True, verbose_name='Área Técnica'), + ), + migrations.AlterField( + model_name='customuser', + name='rol', + field=models.CharField(choices=[('directiva', 'Directiva'), ('jefe_area', 'Jefe de Área'), ('miembro', 'Miembro')], default='miembro', max_length=20, verbose_name='Rol en el equipo'), + ), + ] diff --git a/Plataform_Web/users/migrations/__pycache__/0003_alter_customuser_especialidad_alter_customuser_rol.cpython-314.pyc b/Plataform_Web/users/migrations/__pycache__/0003_alter_customuser_especialidad_alter_customuser_rol.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e521688cae488cbb11ef2e3f347539addedf9f6b GIT binary patch literal 1491 zcmdPq+zUY%*o!octt#DQT}DC4sO0|P??LmWd8qbGw0V+o@NQwftigD8U{ zLlBcVLlAQ;V*ndeEfQtI4B?b82eBwKXtKTpaW$E4aph*F7bTWt=I0gPV$01>NzExv z21&s%50vrw6xiBWh7!ggh7zVYwi4zbUOmPVmRQyRm>Q^35T(cv#2CaB%N`&A;-O+i zh9G7=h9EwF#yGhk<{*|JR&%K5g4oQV&ctIXJ1$f87=rly8G|_DM1nYjxXf7~wj#{b zV=Cbc;x6F|;!$SM6u8Cd3-kFcuH@3R7FTX!MSM%q^2d7=9Cn1GcYg|@iH(ltYq-hWV*!)a&z%5a{~hd zqxi&}lGLJjgkR#3y@DxQl%J!?p~-ZMCo#1sKP59SF*h?gu@q#sBShfvLXe0i(=E2- zjKt#1;#+LaU|N&umT*#Oab{j>adCWpL23~s{ZxrMK?N1m6#U`BnoPI2Qw#FTQ;SN9 z5;OCvcwBV@;5@KoPHJ*VQ9dYaOF>D=70f@p86=>|bc?w-CG8e-u#1}}(=EZ={F3~l z_>!W;yyD!<;>`TKQV|9Q249e{Z*e+jBo=}Bx400&drLGvzPKc@Br`cav81FZ zGpV#BwKzV$2owOHL23O~wX;=BXmM&$aZF-LQD%CKyOCLZNNP@MZfZ$UW@3DZn|n+^ zPGU)7T7FS(e0XY73^?(`AWDE30|NtN%!EQP8R->N7Jr2p0#g!*Dr9nI25EL- zhG^#H7Gi7hD$)mKAdnmVG+AzOrer1NrRVFVB!Qy>9Q$wktAX vU|?WmU|=YgVPIhRz|6?V_??Y`QS%F%AS2rZuImCS7X?(lF$glUfpr4_ZSJDB literal 0 HcmV?d00001