diff --git a/loko/assets/static/assets/asset_add_modal.js b/loko/assets/static/assets/asset_add_modal.js index df3e02a..8f80fbb 100644 --- a/loko/assets/static/assets/asset_add_modal.js +++ b/loko/assets/static/assets/asset_add_modal.js @@ -45,13 +45,15 @@ const thematicCode = form.dataset.thematic || form.querySelector('[name="thematic_code"]')?.value || ''; const locationId = form.querySelector('[name="location_id"]')?.value || ''; const structureId = form.querySelector('[name="structure_id"]')?.value || ''; + const interventionId = form.dataset.interventionId || form.querySelector('[name="intervention_id"]')?.value || ''; if (!thematicCode) return; const params = new URLSearchParams({ thematic_code: thematicCode, location_id: locationId, - structure_id: structureId + structure_id: structureId, + intervention_id: interventionId }); fetch(`/assets/api/suggested-code/?${params.toString()}`) diff --git a/loko/assets/tests.py b/loko/assets/tests.py index 0d86bfa..e9562f8 100644 --- a/loko/assets/tests.py +++ b/loko/assets/tests.py @@ -477,6 +477,33 @@ class StructuresLocationDetailAddAssetModalTest(TestCase): self.assertEqual(page_res.context["suggested_code"], "WTB30-000025") self.assertContains(page_res, 'value="WTB30-000025"') + # Test intervention code suggestion (mobile / desktop intervention) + from interventions.models import Intervention, InterventionLocation + from django.contrib.contenttypes.models import ContentType + + itv = Intervention.objects.create( + code="ITV_TEST_99", + title="Intervention Test Structures", + thematic=self.thematic + ) + loc_ct = ContentType.objects.get_for_model(self.location) + InterventionLocation.objects.create( + intervention=itv, + content_type=loc_ct, + object_id=self.location.id + ) + + itv_suggested = get_suggested_asset_code("structures", intervention_id=itv.id) + self.assertEqual(itv_suggested, "WTB30-000025") + + itv_api_res = self.client.get(reverse("assets:get_suggested_asset_code_api"), { + "thematic_code": "structures", + "intervention_id": itv.id + }) + self.assertEqual(itv_api_res.status_code, 200) + self.assertEqual(itv_api_res.json().get("suggested_code"), "WTB30-000025") + + diff --git a/loko/assets/utils/asset_code_generator.py b/loko/assets/utils/asset_code_generator.py index 0b4f5de..83f29f3 100644 --- a/loko/assets/utils/asset_code_generator.py +++ b/loko/assets/utils/asset_code_generator.py @@ -7,16 +7,54 @@ def get_next_structure_asset_code( structure=None, location=None, structure_id: Optional[int] = None, - location_id: Optional[int] = None + location_id: Optional[int] = None, + intervention=None, + intervention_id: Optional[int] = None ) -> str: """ - Computes the next incremental asset code for a structure / tunnel location. + Computes the next incremental asset code for a structure / tunnel location / intervention. Looks up existing asset codes (e.g. WTB30-000023, WTB30-000412), determines the dominant prefix and maximum integer number, and returns the next code (e.g. WTB30-000413), ensuring it does not collide with existing codes. """ from assets.models.structures import Structure, StructureLocation, StructureGeoAsset + if intervention_id and not intervention: + try: + from interventions.models import Intervention + intervention = Intervention.objects.get(pk=intervention_id) + except Exception: + intervention = None + + if intervention and not location and not structure: + # 1. Look for linked structure locations + for loc_link in intervention.locations.all(): + loc_obj = loc_link.location + if isinstance(loc_obj, StructureLocation) or hasattr(loc_obj, 'structure'): + location = loc_obj + structure = getattr(loc_obj, 'structure', None) + break + + # 2. Look for linked structure assets + if not structure and not location: + for a_link in intervention.interventionasset_set.all(): + asset_obj = a_link.asset + if asset_obj and hasattr(asset_obj, 'structure') and asset_obj.structure: + structure = asset_obj.structure + location = getattr(asset_obj, 'location', None) + break + + # 3. Fallback: match by location_code / address if structure exists + if not structure and not location and intervention.location_code: + loc_match = StructureLocation.objects.filter(code__iexact=intervention.location_code).first() + if loc_match: + location = loc_match + structure = loc_match.structure + else: + struct_match = Structure.objects.filter(code__iexact=intervention.location_code).first() + if struct_match: + structure = struct_match + if location_id and not location: try: location = StructureLocation.objects.select_related('structure').get(pk=location_id) @@ -79,17 +117,21 @@ def get_suggested_asset_code( thematic_code: str, location_id: Optional[int] = None, structure_id: Optional[int] = None, + intervention_id: Optional[int] = None, location=None, - structure=None + structure=None, + intervention=None ) -> str: """ - Returns a suggested asset code based on thematic and context. + Returns a suggested asset code based on thematic and context (location, structure, or intervention). """ if thematic_code == 'structures': return get_next_structure_asset_code( structure=structure, location=location, structure_id=structure_id, - location_id=location_id + location_id=location_id, + intervention=intervention, + intervention_id=intervention_id ) return "" diff --git a/loko/assets/views/asset_editing.py b/loko/assets/views/asset_editing.py index c875dc9..57099dc 100644 --- a/loko/assets/views/asset_editing.py +++ b/loko/assets/views/asset_editing.py @@ -1286,12 +1286,14 @@ def get_suggested_asset_code_api(request): - thematic_code (str) - location_id (int, optional) - structure_id (int, optional) + - intervention_id (int, optional) """ from assets.utils.asset_code_generator import get_suggested_asset_code thematic_code = request.GET.get('thematic_code') or '' location_id = request.GET.get('location_id') structure_id = request.GET.get('structure_id') + intervention_id = request.GET.get('intervention_id') try: loc_id = int(location_id) if location_id else None @@ -1303,10 +1305,16 @@ def get_suggested_asset_code_api(request): except (ValueError, TypeError): struct_id = None + try: + itv_id = int(intervention_id) if intervention_id else None + except (ValueError, TypeError): + itv_id = None + suggested_code = get_suggested_asset_code( thematic_code=thematic_code, location_id=loc_id, - structure_id=struct_id + structure_id=struct_id, + intervention_id=itv_id ) return JsonResponse({ diff --git a/loko/interventions/templates/interventions/detail/right_column.html b/loko/interventions/templates/interventions/detail/right_column.html index b5a5fdd..c796cb2 100644 --- a/loko/interventions/templates/interventions/detail/right_column.html +++ b/loko/interventions/templates/interventions/detail/right_column.html @@ -169,7 +169,7 @@ -
{% translate "Code unique pour identifier l'équipement." %} diff --git a/loko/interventions/templates/interventions/intervention_detail_mobile.html b/loko/interventions/templates/interventions/intervention_detail_mobile.html index 4675c08..9f16c1e 100644 --- a/loko/interventions/templates/interventions/intervention_detail_mobile.html +++ b/loko/interventions/templates/interventions/intervention_detail_mobile.html @@ -1517,7 +1517,7 @@ -