feat: add controller model name display to traffic light intersection details

This commit is contained in:
kdeterme 2026-08-19 11:02:54 +02:00
parent 46f1d0d384
commit 80cbb80d06
9 changed files with 125 additions and 0 deletions

View file

@ -7366,6 +7366,10 @@ msgstr "GIEP zones"
msgid "Aucune localisation GIEP trouvée à proximité" msgid "Aucune localisation GIEP trouvée à proximité"
msgstr "No location found" msgstr "No location found"
#: assets/templates/assets/trafficlights_intersection_detail.html:52
msgid "Modèle du contrôleur"
msgstr "Controller model"
#~ msgid "StreetUp" #~ msgid "StreetUp"
#~ msgstr "StreetUp" #~ msgstr "StreetUp"

View file

@ -7417,6 +7417,10 @@ msgstr "Zones GIEP"
msgid "Aucune localisation GIEP trouvée à proximité" msgid "Aucune localisation GIEP trouvée à proximité"
msgstr "Aucune localisation GIEP trouvée à proximité" msgstr "Aucune localisation GIEP trouvée à proximité"
#: assets/templates/assets/trafficlights_intersection_detail.html:52
msgid "Modèle du contrôleur"
msgstr "Modèle du contrôleur"
#~ msgid "StreetUp" #~ msgid "StreetUp"
#~ msgstr "StreetUp" #~ msgstr "StreetUp"

View file

@ -7360,6 +7360,10 @@ msgstr "GIEP-zones"
msgid "Aucune localisation GIEP trouvée à proximité" msgid "Aucune localisation GIEP trouvée à proximité"
msgstr "Geen locatie gevonden." msgstr "Geen locatie gevonden."
#: assets/templates/assets/trafficlights_intersection_detail.html:52
msgid "Modèle du contrôleur"
msgstr "Controllermodel"
#~ msgid "StreetUp" #~ msgid "StreetUp"
#~ msgstr "StraatUp" #~ msgstr "StraatUp"

View file

@ -192,6 +192,18 @@ class TrafficLightIntersection(AbstractLocation):
latest_controller = self.controllers.filter(status='active').order_by('-installation_date').first() latest_controller = self.controllers.filter(status='active').order_by('-installation_date').first()
return latest_controller.connected_to_control_center if latest_controller else None return latest_controller.connected_to_control_center if latest_controller else None
@property
def controller_model_name(self):
"""
Get the model name of the active controller (or most recently installed controller).
"""
latest_controller = self.controllers.filter(status='active').order_by('-installation_date').first()
if not latest_controller:
latest_controller = self.controllers.order_by('-installation_date').first()
if latest_controller and latest_controller.model:
return latest_controller.model.get_name() or latest_controller.model.code
return None
def get_absolute_url(self): def get_absolute_url(self):
return reverse("assets:trafficlights_intersections_detail", kwargs={"intersection_id": self.id}) return reverse("assets:trafficlights_intersections_detail", kwargs={"intersection_id": self.id})

View file

@ -48,6 +48,8 @@
{% endif %} {% endif %}
<br> <br>
<label class="mx-2">{% translate "Index" %}:</label>{{ intersection.current_index|default:""}} <label class="mx-2">{% translate "Index" %}:</label>{{ intersection.current_index|default:""}}
<br>
<label class="mx-2">{% translate "Modèle du contrôleur" %}:</label>{{ intersection.controller_model_name|default:""}}
{% if intersection.master %} {% if intersection.master %}
<br> <br>
<label class="mx-2">{% translate "Carrefour principal" %}:</label><a href="{% url 'assets:trafficlights_intersections_detail' intersection.master.id %}">{{ intersection.master.code|default:"/" }}</a> <label class="mx-2">{% translate "Carrefour principal" %}:</label><a href="{% url 'assets:trafficlights_intersections_detail' intersection.master.id %}">{{ intersection.master.code|default:"/" }}</a>

View file

@ -3235,3 +3235,102 @@ class CreateInterventionForAssetWorkflowTest(TestCase):
self.assertEqual(first_event.event_user, self.user) self.assertEqual(first_event.event_user, self.user)
class TrafficLightIntersectionControllerModelTest(TestCase):
def setUp(self):
self.thematic, _ = Thematic.objects.get_or_create(
code="trafficlights",
defaults={
"name_fr": "Feux de signalisation",
"name_nl": "Verkeerslichten"
}
)
self.user, _ = User.objects.get_or_create(username="tl_ctrl_testuser")
self.user.set_password("password123")
self.user.save()
self.config, _ = UserConfig.objects.get_or_create(user=self.user, defaults={"limit_assets_to_contracts": False})
self.config.limit_assets_to_contracts = False
self.config.save()
UserThematics.objects.get_or_create(
user_config=self.config,
thematic=self.thematic,
defaults={"can_view_assets": True}
)
from django.contrib.gis.geos import Point
geom_intersection = Point(648000, 670000, srid=3812)
self.intersection = TrafficLightIntersection.objects.create(
code="TL_INT_001",
name_fr="Carrefour Test",
geom=geom_intersection,
lon=4.3508,
lat=50.8465,
current_index="IDX-12345"
)
self.category, _ = AssetCategory.objects.get_or_create(
code="TL_CONTROLLER_CAT",
defaults={
"name_fr": "Contrôleur de trafic",
"name_nl": "Verkeersregelaar",
"thematic": self.thematic
}
)
from assets.models import TrafficLightControllerModel, TrafficLightController
self.controller_model = TrafficLightControllerModel.objects.create(
code="CTRL_MOD_01",
name_fr="Siemens Sitraffic C1000",
name_nl="Siemens Sitraffic C1000 NL",
category=self.category
)
self.controller = TrafficLightController.objects.create(
code="CTRL_001",
intersection=self.intersection,
model=self.controller_model,
geom=geom_intersection,
lon=4.3508,
lat=50.8465,
status="active"
)
def test_controller_model_name_property(self):
self.assertEqual(self.intersection.controller_model_name, "Siemens Sitraffic C1000")
def test_controller_model_name_none_when_no_controller(self):
from django.contrib.gis.geos import Point
empty_intersection = TrafficLightIntersection.objects.create(
code="TL_INT_EMPTY",
name_fr="Carrefour Sans Contrôleur",
geom=Point(648000, 670000, srid=3812)
)
self.assertIsNone(empty_intersection.controller_model_name)
def test_detail_view_renders_controller_model_name(self):
self.client.force_login(self.user)
# Test French
response_fr = self.client.get(
reverse("assets:trafficlights_intersections_detail", args=[self.intersection.id]),
HTTP_HOST="localhost",
HTTP_ACCEPT_LANGUAGE="fr"
)
self.assertEqual(response_fr.status_code, 200)
content_fr = response_fr.content.decode("utf-8")
self.assertIn("Modèle du contrôleur", content_fr)
self.assertIn("Siemens Sitraffic C1000", content_fr)
self.assertIn("IDX-12345", content_fr)
# Test Dutch
response_nl = self.client.get(
reverse("assets:trafficlights_intersections_detail", args=[self.intersection.id]),
HTTP_HOST="localhost",
HTTP_ACCEPT_LANGUAGE="nl"
)
self.assertEqual(response_nl.status_code, 200)
content_nl = response_nl.content.decode("utf-8")
self.assertIn("Controllermodel", content_nl)
self.assertIn("Siemens Sitraffic C1000 NL", content_nl)