From f2fbe7e3946109449767a5eb8cb7decba2a5a4a5 Mon Sep 17 00:00:00 2001 From: kdeterme Date: Fri, 18 Sep 2026 16:14:04 +0200 Subject: [PATCH] feat: promote existing base inspections to HotBoxInspection instances and add pending visual checks UI --- .../locale/en/LC_MESSAGES/django.mo | Bin 21757 -> 21935 bytes .../locale/en/LC_MESSAGES/django.po | 5 ++ .../locale/fr/LC_MESSAGES/django.mo | Bin 27112 -> 27318 bytes .../locale/fr/LC_MESSAGES/django.po | 7 +++ .../locale/nl/LC_MESSAGES/django.mo | Bin 21256 -> 21456 bytes .../locale/nl/LC_MESSAGES/django.po | 7 +++ ...013_promote_existing_hotbox_inspections.py | 35 +++++++++++ loko/inspections/models.py | 5 +- .../components/asset_details/_hotbox.html | 6 ++ loko/inspections/tests.py | 58 +++++++++++++++++- loko/inspections/views.py | 10 +++ 11 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 loko/inspections/migrations/0013_promote_existing_hotbox_inspections.py diff --git a/loko/inspections/locale/en/LC_MESSAGES/django.mo b/loko/inspections/locale/en/LC_MESSAGES/django.mo index dfd3154c3fb6119bf6705717fa97e826b75e1fc0..02ac4aa1eec963d178911a0163d1664c46707ade 100644 GIT binary patch delta 5209 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 delta 5031 zcmYM$3y_Z28Nl%)mSxvsEpg|=x~r^vmas1CQdRdhCM%&b2r8*6jcwx-VWJ_EB5F*9 zQTHIU5~?n(P$X?MniQ>EN`$6p=}02klK%hRGtjQjTnG*DXk~jLd^hj^_MthQejVJ24mlD1Gghbn9_HXR%*8USfjKopsEaAg z!0uQPi;%x`7{I@^xlj^s%#4mf{Lp^DoiV<&f|Du?}*u!w77S z6EPbXqw}mpYrhi>d{6A3LJ!|rbll(3z;2~!I8n7m$%QWHghS9Bk3j>Qjz<0*I?;=0 zpsUduZ$mS167%sxq$(kU^xVw|I(`7Up>IXg<7rU#Fbz|<08RZyB&%UBy5o1yj9f-* z`Xx5OCaGit{m_7?pyTJF8(D_VzXrX(7tPEck>}IlG7WE3rq>o5VJjSr)_Nv(#Fc1j z-$XVSPN6Bhjs}`Z8q8EPwBI}S$6|Z>bI^IVAhCyYn9us5jD`!RSgjon!8SMtJ!Biu z`|n~8G{3Fk0d(9Xblg&8NH~n$@#AQU`nuy1G{D(t;LEWw>xY+VxbU0U2R}z6E+o&y z79K;dFGe%<7J8a5Ae#@juo~8*(3YqTdKP-3H6MzOe;D1!Ow7c!nD)WVH2UFQ^mQyl z-{;oU!3R4cn+b!^*K;~%VkuU@`Pd&9VMRQN?(i>YAXm}U-^LUckUsVpMzkjXrtF7Y zD33o!7g&qgxE^J(4pyb# z1%0j<&Dc;RL+S8X(ge;V5PCY6gi(^7aHKXc>OX? zpkJ{o&zIvuR>z{)AKsn(XK-N(7p&RiXnz@+s+DN1)}b}r zg9dg1{qlW=PWWGRTn;}F2GA6prvU3=7c?Wo(f5BG7UA494I?{*ruGcF!w<18-avPn z&B1U-HPMCIV0|n?$CuzYaXOl*{g}en(eWRl<8PrGsL4me%%oeIHPdRp*)9z{Sx!hQguZG7=oQ~GMdTN=owg#KKI*x0EP6|O`B`Caq^wxplYKd~J)qdyu`_#`^tD)jk%{mH+l z@d6i|xblGHu(U*efkO$Jp+%U&&1eQrpn<-R25=Ma!+QrNI~;({Hvv1~JoLF=p&2@k zP4WFS4Nr3zlnkhj8FZVYHE)AHP>3!xEZ(0H@6X0oTwjQ${1x>1H_&-cVm^L=ro8;u zlTy@*rW??pjG8&3GrHhNG;>qX z*Yf#ze+@eC0W4tsaFT{K`U?HP*IC@5AVRc-L9>&%2{$9+be+bRM z+gJ&&qNVs04Xnz@Bop<~0NRcu|5-GOxZq9(qcwaOTi}n-n*Rd*kvWXH_*Wc{S8y^8 z8I^o5Ud1B%=g|P0a3X8q1888w&`eK516-aP2dqZQA9jx3U7Gi7=I-(JvzqPR(d(Yt F{{t;v6zKo} diff --git a/loko/inspections/locale/en/LC_MESSAGES/django.po b/loko/inspections/locale/en/LC_MESSAGES/django.po index f9b5e8a..2d0ebb8 100644 --- a/loko/inspections/locale/en/LC_MESSAGES/django.po +++ b/loko/inspections/locale/en/LC_MESSAGES/django.po @@ -1965,6 +1965,11 @@ msgstr "" "Please answer each of the 4 visual checks of the Hot Box repair (Flatness, " "Joints, Cracking, Drainage)." +msgid "" +"Contrôles visuels non encore renseignés (inspection planifiée ou en attente " +"d'évaluation)." +msgstr "Visual checks not yet filled in (scheduled or pending evaluation)." + #~ msgid "Renforcement de l'entretien préventif" #~ msgstr "Reinforcement of preventive maintenance" diff --git a/loko/inspections/locale/fr/LC_MESSAGES/django.mo b/loko/inspections/locale/fr/LC_MESSAGES/django.mo index 8b6f41faa0671d269b075264e55fba3ec6cff7dc..9c33eb74e9333d6f3513d7af02af5165f3479219 100644 GIT binary patch delta 6016 zcmciGiFc1z9>?*UN6q$F^(e8H9y)00yg#}3ocRyN$;s>9`+J^yzxR8;&-2Ssaxvg< zmjk?iRS8^Y_%|`Ym^#?6yn4pWt^PkFY0jgs&(~p1+>1$g7HeQQ7lmM)vo%(t-x2qz#^!hs zN8?RQ#-5}@8(NOTa2-~_`>5jk1$BRz&j!%Q=h+1l8PJ(#U`u=xiN)+d?lGrOXIp{_ z=qd7JqN8mFx}!ES9CZ}aP&G9hmBEG14X7I0gUZNJkA}|pDyo?7pmy*AmAViPN-1rC zRdF;b6FJxj3s30%k3-Fqh1ysi5|hbCWpEqvWA^il8u83k8jA2|RBB&hHQm?* zhhRrkM&3q6ywUadp^oe`^x+lM89zg1t^x(6j5R`KHUS&s0OZHa=2x_y|1C7Q#~gQ- zpmr8cG@2j=72wOL1(Q*qk3NiLA`(O*4h;48kmKG~2#U-df!YGJl*b!A56Zxeg{{wou z;24e0cn`V9G-i;dNkd&Y9~Jp7?1UGbVa%!w^hO0V9u@ckR3PslKW0C_lJGhz;D$WA zs)-@Z$-h3B#Xuk)LZ$X7>T$Y+O6_f|h!wb7FP1u}GmUrlK^50X49BUc`{yFDnm=M$ zJc63%Br0QnZ$bW(X@sy%)-e6C9L_;auo#ufjaUJXq9!_vL3jyM@Smt7^tG}Xh(iU` z1+~xs^x+~@t^F01(bFD{GBoa?7I=u|@dbusC|_w6u_mhD7{jmwsyKV1UR3F*+L(o! zXDwF7cTqJ}h`Rm)YP}n%OnbL!Xh*-Hs=F-V>Ovom!FJdU*J35SjGFL_zYM!I$V|{aph8BE`S}=+iz8RmRHtMJ=cINzbhP8S7)WnXc3)7ra zFp~a4R8?<4ExZkN{bAIOFQYQ}6q{oG1bgHZ$9=qRAsjk%BR(}*K)vZtyC1W6tLcNH_p?02$T6n%2U+>(6 zn%8^JHTF4ABCi7THL3+@f_+sat*ccE!Tg6s)1l8Q!!RV zZ6q1luxAF*(8Nc%T zE^5JmzP5-Ppx&5WPyuA4GQ0wHv^!A&ecG4&`)K^YfHDx=&+eoyhR|<|Wib(z!W8Ey zR1wWUWh5VU##>Oev>QY5I4YxGqB435t785BHWTsv$$ujTMlzrXmpHd#6Z$7G9v@(N zj7znFw8dcheNmYh?D|tt0q3Cto{QSpT5NzHxPCEez7mgyQuqk9laK*+=M7O4wZd@h zfGW0Ls1#1YSe%2Zku9hR51~?f5_R8w9D>hL8A%&x10Id)d$Vcq9Gb=G!%e6&K7vZ! zc~r{oqEc%H*>AO~sA5aRXqasec!>kprj{a{i)dV%s za4fA>REl?^0x8C3_#9OmO~`9Y9D@3M33kRk*ck7ju8VxlUe_HJa1M6D^^)~XF%4y) z!cZGw99E~_0~N>!)WUNx3E#&ScpFs{HF-ugo`8WkA0sdyt6>2uv%9b&o=4Tpcj#52 z@r;HH8*Yoshbo@ds0q5EcK8~qC>Nn7T8_%tMoh*pu{l;ww=bx!sQY`PGC3M6U_NS| z)#*I{dKDHhkb;|0XLuczfjd|UUm9T-s)|1PJyFFr36;{7SO)i?7TAa7@i=NDU!em2 z*7fgU82w*IkpHSQLPy#+RTS2ypMaWZ7*<9XYXP86!8eyCc=Le1~3qEVN|7E}!!K^0dq>g>!|dqZ_pzXK*>D(XeE0yX|Is_M@; zAE6%Gs0=%AFKkIa9hI@=NTxmW7aH{#IE*^eZ%_dRjI-nQP!o4Wona=1;A||da`e$J zKrMI>wUO^p8GVeZfhyzeebJ~)HpS}t{!b}w@Ew5KNiN3VTc{g9#J2bes%Rdds{92i zfMyfyeMzXZABy#HI`+UdsDS^0n*V#}6O3Se6YjSY$DmT*8nuJ5SPOHp9Iis0^*b1g zyHIC+5tXrjqjvTjbzS5{YYU8|pMomtQK-PDp#C${cr;>g11g1|VpF_<(O6}Yy`dd0 zpx+0V;TcT8w8{3b=+&rVyM_wDWZEN*M2#n+-iRYnfiKPEWc9%s1~?|O7u#dCDfZ9k zzNi;WJ{A^t%PKc&T6SJe(Z^Z-T;I&h+!_9?TwnIIY@a`S{InduFUOyq>(88&U9>&d z*C;bPce;OkUM3$;&&tTooS0d(-S3+=gNuC`d3pZqJil*3T+#NK8Cf$jbXnsTg`N9+ P=qt?cdMM=ou+D!0L=W9Q delta 5812 zcmYM%4Rp`f9mny@KS2^nB=Q_d{z5_$qT;C}B&krrDjp+6rP5#?SKFF;{F%;k7f#pG zYMW|T+f>zzP^yMALsWIxY-VU>?T+V?9ZIWve{%0R?a9gO-uwIg?)~2H{r-N^U4Lux z-_uRJ3y}e@82+nlVoVz>3Q^CP88JT?OLHcDU0;gv_zo80K8(YM7=*FhEZbr$%)(I2 z!w4LVkvJZi$1}5O1Te4?n_)FZ;Va0GdC!d>avnoX{F(D}=WXoDxQ}Rxum|?Td8h^V zI6uKe`WG>R_00ns%^3(K94#D;>StmL%)xG$i`vO-{Tej2rbE2twdZEfuYqcRui%tY1BW2j7&ppJH?M?*!l0JVcPsFZC$rE(Xx#+#@N z_&B(Zn1Kp#gmVsN(tini;>V~OYCr{|?W*|VP?<<^eXkDBeyG(hl;m4^}v9P#O3qD!>L*;1R5*Ksurp9>lLg{5dM%-AFx}FWq=h zXYwDwzz|+$rLY9`I#r@lJ0HXGO;pirMV;vp=Q&hyT}Rcffm@3ZEJ#PR4TKuC6=Hjnt*{=i34ytHpA_x419RB@g~eIc)+Y9)w&`ZP}(>TSqD z)l?Dc{tDEBRj5qQM{USkOGDNDD(c4VI1vwH0j9ByRyY|oVU=?o>g;P#M{^1z@EYoj zAG-0j-R$*T3}$>ZDpTdQ@0ltZ+W8Wkj@77z?xTt+zPqi3-lzq}p>{qKBXKoydZq?- zbSF@?bJ_I+dl=J~ej@VbnKIOUzrYN=|LYqYe9@3M%3MWF9M#jl1syPoekm%|Gf;u8 zK)xyF_o#qAb>r7iZ&S-&_6U1o5dDFuc}mcamDrK>%`zHVa2qP6hfp0I^`XFkeGZ=t3P#>Z@sGZ+OEgb%s9q-`G zM$Oy9=?!#^Qsk94Q&Bar0ojzfh*~hYzqKnS(l0^q3DfWdDr0w0--EDX^536E9u4heF^V`VY zQsf^x^Aps<8!-jo8xR$>Z+V;P{s2*R3>Us zXL|}&oS$PbHlQ;3Jt~ulL+w9mqfi-`iXE{U72xinb?(9HS-tLg8z1X-xGGe1k_uSj@n4BM?*Uwi<)Q>hT$|+kp?3J8^8#vT0mJR{@u&bhqZaIqx;_FG&=h1I&n$5l-o-2~>_MH; ze^5mhHo}_Y9D_NG&qE!_R!qj7sMMcEZR83n#m#t^)o+LD=VLaG#~i)?t7)hP_M=jK z0TqaEl>IBV3#vB8V;5YGy1pB8@iHnyDWmOu#i;v!hT6cp*awd~ePe6}`e7T^H)S*w z`E#g1eubTID;DB8RK#ugil`=rpvGrm0R91^uok1S4s}GAFdUnXwKWrok@Pz`^U-U? zzz7;Do(j|ib5J{6fhx+KsEPJr4t|3AZhViOv45HUFg=TUejX~5Yq2HPqUJe-fmnwF z@Ut@VuQQB!(q}1ba5UPzw)7opFU5U*_D1dY|`V3?6p<^QfJFh12m4YN3fw*;-nJ zs)ZWV{0A@zPoZkTyG29A<(p{FE(i6%AlILUed#YoeQ5T(@h?$T|E)8<+`hIYsEOyI z-hvlV8QX`6_*YE9>&TIMCiH0=Q8(0u;i!q9MHSua7=&A}vC7d;zYg`CxQbdZYLZQ9 z2h^Dtp`IIw@i+mMxhiKhM(h3GL_iYB$fR{0~S0G>is`A<=2zYu}=yo5UIz)G932-MEH zpzbSnmSZgaDpXOgK`s0S>i+H64v(X!6yBtfg>jSZ*%zT6n2d{YKCZxTF%Oqcv41`v z!esibr`iB=FpYjOYJ4{8%UO*Ie2*JHj3n38PbHonG#>x4{quPt=FqRj9R-CmTI>iJ Pyv4uccK+U=#@7D<#v6r~ diff --git a/loko/inspections/locale/fr/LC_MESSAGES/django.po b/loko/inspections/locale/fr/LC_MESSAGES/django.po index 8d4f846..3b1c422 100644 --- a/loko/inspections/locale/fr/LC_MESSAGES/django.po +++ b/loko/inspections/locale/fr/LC_MESSAGES/django.po @@ -1973,6 +1973,13 @@ msgstr "" "Veuillez répondre à chacun des 4 contrôles visuels de la réparation Hot Box " "(Planéité, Joints, Fissuration, Évacuation des eaux)." +msgid "" +"Contrôles visuels non encore renseignés (inspection planifiée ou en attente " +"d'évaluation)." +msgstr "" +"Contrôles visuels non encore renseignés (inspection planifiée ou en attente " +"d'évaluation)." + #~ msgid "Renforcement de l'entretien préventif" #~ msgstr "Renforcement de l’entretien préventif" diff --git a/loko/inspections/locale/nl/LC_MESSAGES/django.mo b/loko/inspections/locale/nl/LC_MESSAGES/django.mo index 611b7f3291966d6d372877ce92c4c2f4e7fa149e..febaab22de16cd914996c5f9687a4617e6da73c2 100644 GIT binary patch delta 4861 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 diff --git a/loko/inspections/locale/nl/LC_MESSAGES/django.po b/loko/inspections/locale/nl/LC_MESSAGES/django.po index ba155cb..1f3d363 100644 --- a/loko/inspections/locale/nl/LC_MESSAGES/django.po +++ b/loko/inspections/locale/nl/LC_MESSAGES/django.po @@ -1964,6 +1964,13 @@ msgstr "" "Gelieve elk van de 4 visuele controles van de Hot Box-herstelling te " "beantwoorden (Vlakheid, Voegen, Scheurvorming, Afwatering)." +msgid "" +"Contrôles visuels non encore renseignés (inspection planifiée ou en attente " +"d'évaluation)." +msgstr "" +"Visuele controles nog niet ingevuld (geplande inspectie of in afwachting van" +" evaluatie)." + #~ msgid "Renforcement de l'entretien préventif" #~ msgstr "Versterking van preventief onderhoud" diff --git a/loko/inspections/migrations/0013_promote_existing_hotbox_inspections.py b/loko/inspections/migrations/0013_promote_existing_hotbox_inspections.py new file mode 100644 index 0000000..54f9164 --- /dev/null +++ b/loko/inspections/migrations/0013_promote_existing_hotbox_inspections.py @@ -0,0 +1,35 @@ +from django.db import migrations, models + + +def promote_existing_hotbox_inspections(apps, schema_editor): + Inspection = apps.get_model('inspections', 'Inspection') + HotBoxInspection = apps.get_model('inspections', 'HotBoxInspection') + db_alias = schema_editor.connection.alias + + existing_hb_ids = set(HotBoxInspection.objects.using(db_alias).values_list('inspection_ptr_id', flat=True)) + + inspections_to_promote = Inspection.objects.using(db_alias).filter( + models.Q(checked_intervention__sub_type__code='hotbox') | + models.Q(mission_intervention__sub_type__code='hotbox') + ).exclude(id__in=existing_hb_ids) + + for insp in inspections_to_promote: + hb = HotBoxInspection(inspection_ptr=insp) + for f in insp._meta.fields: + setattr(hb, f.attname, getattr(insp, f.attname)) + hb.save_base(raw=True, using=db_alias) + + +def reverse_func(apps, schema_editor): + pass + + +class Migration(migrations.Migration): + + dependencies = [ + ('inspections', '0012_alter_hotboxinspection_water_drainage'), + ] + + operations = [ + migrations.RunPython(promote_existing_hotbox_inspections, reverse_func), + ] diff --git a/loko/inspections/models.py b/loko/inspections/models.py index dafc01a..c085779 100644 --- a/loko/inspections/models.py +++ b/loko/inspections/models.py @@ -598,7 +598,10 @@ class Inspection(models.Model): return self.hotboxinspection if self.is_hotbox_related and self.pk: try: - hb, _ = HotBoxInspection.objects.get_or_create(inspection_ptr=self) + hb = HotBoxInspection(inspection_ptr=self) + for f in self._meta.fields: + setattr(hb, f.attname, getattr(self, f.attname)) + hb.save_base(raw=True) return hb except Exception: pass diff --git a/loko/inspections/templates/inspections/components/asset_details/_hotbox.html b/loko/inspections/templates/inspections/components/asset_details/_hotbox.html index a1cb635..93d9fd3 100644 --- a/loko/inspections/templates/inspections/components/asset_details/_hotbox.html +++ b/loko/inspections/templates/inspections/components/asset_details/_hotbox.html @@ -8,6 +8,12 @@
    + {% if not leaf.joint_level and not leaf.joint_sealing and not leaf.cracking and not leaf.water_drainage %} +
  • + {% translate "Contrôles visuels non encore renseignés (inspection planifiée ou en attente d'évaluation)." %} +
  • + {% endif %} + {% if leaf.joint_level %}
  • diff --git a/loko/inspections/tests.py b/loko/inspections/tests.py index 7645d02..78004db 100644 --- a/loko/inspections/tests.py +++ b/loko/inspections/tests.py @@ -2018,7 +2018,63 @@ class PostInterventionDurabilityInspectionTestCase(TestCase): insp = schedule_post_intervention_inspection(intervention) self.assertIsNotNone(insp) self.assertIsInstance(insp.detailed_inspection, HotBoxInspection) - self.assertTrue(insp.is_hotbox_related) + + def test_existing_base_inspection_promotion_and_update(self): + """Vérifie qu'une inspection existante créée comme base Inspection pour un Hot Box est bien promue en HotBoxInspection et que ses choix sont sauvegardés.""" + self.client.force_login(self.user) + intervention = self._create_finished_intervention(sub_type=self.hotbox_subtype) + interv_ct = ContentType.objects.get_for_model(Intervention) + + # Création directe comme base Inspection (simulation d'une inspection créée avant la migration) + base_insp = Inspection.objects.create( + asset_content_type=interv_ct, + asset_object_id=intervention.pk, + nature='post_intervention', + checked_intervention=intervention, + status='scheduled', + result_status='pending', + ) + + # 1. Avant évaluation : get_inspection_detail_api renvoie le message d'attente + detail_url = reverse('inspections:get_inspection_detail_api', kwargs={'inspection_id': base_insp.id}) + resp_detail = self.client.get(detail_url, HTTP_ACCEPT_LANGUAGE='fr') + self.assertEqual(resp_detail.status_code, 200) + detail_data = resp_detail.json() + self.assertTrue(detail_data.get('is_hotbox')) + self.assertIn("non encore renseignés", detail_data.get('details_html', '')) + + # 2. Mise à jour via update_inspection_api (sauvegarde des 4 critères) + update_url = reverse('inspections:update_inspection_api', kwargs={'inspection_id': base_insp.id}) + update_data = { + 'status': 'completed', + 'result_status': 'compliant', + 'joint_level': 'flush', + 'joint_sealing': 'good', + 'cracking': 'none', + 'water_drainage': 'not_checked', + 'notes': 'Test mise à jour inspection Hot Box existante', + } + resp_update = self.client.post(update_url, update_data) + self.assertEqual(resp_update.status_code, 200) + self.assertTrue(resp_update.json()['success']) + + # 3. Vérification que l'inspection est maintenant bien un HotBoxInspection avec ses choix + base_insp.refresh_from_db() + leaf = base_insp.detailed_inspection + self.assertIsInstance(leaf, HotBoxInspection) + self.assertEqual(leaf.joint_level, 'flush') + self.assertEqual(leaf.joint_sealing, 'good') + self.assertEqual(leaf.cracking, 'none') + self.assertEqual(leaf.water_drainage, 'not_checked') + + # 4. Consultation du détail : les badges et choix sont bien présents + resp_detail_after = self.client.get(detail_url, HTTP_ACCEPT_LANGUAGE='fr') + detail_data_after = resp_detail_after.json() + self.assertEqual(detail_data_after['joint_level'], 'flush') + self.assertEqual(detail_data_after['water_drainage'], 'not_checked') + self.assertIn("Bien à niveau / Arasé", detail_data_after['details_html']) + self.assertIn("Non vérifié", detail_data_after['details_html']) + self.assertTrue(base_insp.is_hotbox_related) diff --git a/loko/inspections/views.py b/loko/inspections/views.py index 678bc72..c023b4e 100644 --- a/loko/inspections/views.py +++ b/loko/inspections/views.py @@ -987,6 +987,16 @@ def update_inspection_api(request, inspection_id): inspection_obj = get_object_or_404(Inspection, pk=inspection_id) inspection = inspection_obj.detailed_inspection + if not isinstance(inspection, HotBoxInspection) and (getattr(inspection, 'is_hotbox_related', False) or 'joint_level' in request.POST): + try: + hb = HotBoxInspection(inspection_ptr=inspection) + for f in inspection._meta.fields: + setattr(hb, f.attname, getattr(inspection, f.attname)) + hb.save_base(raw=True) + inspection = hb + except Exception: + pass + if not inspection.can_edit(request.user): return JsonResponse({ 'success': False,