From cd00ad53ee48cd4777f53fc1d73b648054e74c89 Mon Sep 17 00:00:00 2001
From: Baptiste Lefeuvre
Date: Tue, 23 Jun 2026 14:46:33 +0200
Subject: [PATCH 1/3] Fix #64 : Add defects severity
---
main/admin.py | 1 +
main/fixtures/main/initial_data.json | 6 +++---
main/migrations/0015_defect_severity.py | 24 +++++++++++++++++++++++
main/models.py | 7 +++++++
main/static/css/main.css | 26 +++++++++++++++++++++++++
main/templates/main/vehicle_detail.html | 22 +++++++++++++++------
main/views.py | 4 ++++
7 files changed, 81 insertions(+), 9 deletions(-)
create mode 100644 main/migrations/0015_defect_severity.py
diff --git a/main/admin.py b/main/admin.py
index 6da2ba2..129098c 100644
--- a/main/admin.py
+++ b/main/admin.py
@@ -46,6 +46,7 @@ class DefectInline(admin.TabularInline):
"solution_date",
"reporter_name",
"status",
+ "severity",
)
readonly_fields = ["creation_date", "solution_date"]
diff --git a/main/fixtures/main/initial_data.json b/main/fixtures/main/initial_data.json
index be7b76c..1c9ba92 100644
--- a/main/fixtures/main/initial_data.json
+++ b/main/fixtures/main/initial_data.json
@@ -93,11 +93,11 @@
"pk": 2,
"fields": {
"vehicle": "3a8798e8-c193-4e75-868c-982e2f24b576",
- "type": "bulb",
- "status": "OPEN",
+ "status": "CONFIRMED",
"creation_date": "2024-05-28",
"solution_date": null,
- "comment": "Clignotant AVG",
+ "comment": "Clignotant AVG non fonctionnel",
+ "severity": "MAJOR",
"reporter_name": "Baptiste"
}
},
diff --git a/main/migrations/0015_defect_severity.py b/main/migrations/0015_defect_severity.py
new file mode 100644
index 0000000..fda275d
--- /dev/null
+++ b/main/migrations/0015_defect_severity.py
@@ -0,0 +1,24 @@
+# Generated by Django 5.2.8 on 2026-06-23 13:12
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("main", "0014_remove_defect_type"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="defect",
+ name="severity",
+ field=models.CharField(
+ blank=True,
+ choices=[("MAJOR", "Majeure"), ("MINOR", "Mineure")],
+ max_length=255,
+ null=True,
+ verbose_name="gravité",
+ ),
+ ),
+ ]
diff --git a/main/models.py b/main/models.py
index 40f6fc8..5c0445e 100644
--- a/main/models.py
+++ b/main/models.py
@@ -98,10 +98,17 @@ class DefectStatus(models.TextChoices):
SOLVED = "SOLVED", _("Résolu")
CANCELLED = "CANCELLED", _("Annulé")
+ class DefectSeverity(models.TextChoices):
+ MAJOR = "MAJOR", _("Majeure")
+ MINOR = "MINOR", _("Mineure")
+
vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE)
status = models.CharField(
_("statut"), max_length=255, choices=DefectStatus, default=DefectStatus.OPEN
)
+ severity = models.CharField(
+ _("gravité"), max_length=255, choices=DefectSeverity, null=True, blank=True
+ )
creation_date = models.DateField(_("date de création"), auto_now_add=True)
solution_date = models.DateField(
_("date de résolution"), null=True, blank=True, editable=False
diff --git a/main/static/css/main.css b/main/static/css/main.css
index a2dfbcd..050715a 100644
--- a/main/static/css/main.css
+++ b/main/static/css/main.css
@@ -33,4 +33,30 @@ input:not([type=submit], [type=button], [type=reset])[readonly] {
a {
margin-top: var(--spacing);
margin-bottom: var(--spacing);
+}
+
+.status-tag {
+ padding: 5px 20px;
+ border-radius: 20px;
+ white-space: nowrap;
+ font-size: 20px;
+ font-weight: var(--font-weight);
+ line-height: var(--line-height);
+ color: var(--contrast);
+ margin-left: var(--spacing);
+}
+
+.status-operational {
+ color: #1bc5bd;
+ background-color: #c9f7f5;
+}
+
+.status-in_repair {
+ color: #f64e60;
+ background-color: #ffe2e5;
+}
+
+.status-out_of_order {
+ color: #f64e60;
+ background-color: #ffe2e5;
}
\ No newline at end of file
diff --git a/main/templates/main/vehicle_detail.html b/main/templates/main/vehicle_detail.html
index 795f36b..27fef78 100644
--- a/main/templates/main/vehicle_detail.html
+++ b/main/templates/main/vehicle_detail.html
@@ -2,12 +2,21 @@
{% block title %}{{ block.super }} - {{ vehicle.name }}{% endblock %}
{% block body %}
- {{ vehicle.name }}
- {% if trip_started %}Un trajet est en cours, pensez à le clôturer avant d'en commencer un nouveau
{% endif %}
+ {{ vehicle.name }} {{ vehicle.get_status_display }}
{% if messages %}
- {% for message in messages %}
- {{ message }}
- {% endfor %}
+ {% for message in messages %}
+ {{ message }}
+ {% endfor %}
+ {% endif %}
+ {% if trip_started %}
+ Un trajet est en cours, pensez à le clôturer avant d'en commencer un nouveau
+ {% endif %}
+ {% if major_defects %}
+ Anomalies connues :
+ {% for defect in major_defects %}
+
⚠️ {{ defect.comment }}
+ {% endfor %}
+
{% endif %}
Détails du véhicule
@@ -78,6 +87,7 @@ {{ vehicle.name }}
| Commentaire |
Statut |
+ Gravité |
Date |
@@ -86,11 +96,11 @@ {{ vehicle.name }}
| {{ defect.comment }} |
{{ defect.get_status_display }} |
+ {{ defect.get_severity_display|default_if_none:"-"}} |
{{ defect.creation_date }} |
{% endfor %}
-
diff --git a/main/views.py b/main/views.py
index dad4292..593be89 100644
--- a/main/views.py
+++ b/main/views.py
@@ -35,6 +35,10 @@ def get_context_data(self, **kwargs):
Q(status=models.Defect.DefectStatus.OPEN)
| Q(status=models.Defect.DefectStatus.CONFIRMED)
)
+ context["major_defects"] = context["vehicle"].defect_set.filter(
+ Q(status=models.Defect.DefectStatus.CONFIRMED)
+ & Q(severity=models.Defect.DefectSeverity.MAJOR)
+ )
delegated_forms: dict[str, type[ModelForm]] = {
"defect_form": forms.DefectForm,
From aacd0b875b54cf6c97208c4b19a2a21b61cf68c5 Mon Sep 17 00:00:00 2001
From: Rowin
Date: Tue, 23 Jun 2026 23:26:21 +0200
Subject: [PATCH 2/3] =?UTF-8?q?Mutaliser=20l'utilisation=20des=20d=C3=A9fa?=
=?UTF-8?q?uts=20dans=20le=20contexte?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
main/admin.py | 2 +-
main/fixtures/main/initial_data.json | 2 --
main/models.py | 7 +++++++
main/templates/main/vehicle_detail.html | 12 ++++++------
main/views.py | 24 ++++++++++++------------
5 files changed, 26 insertions(+), 21 deletions(-)
diff --git a/main/admin.py b/main/admin.py
index 129098c..6cd7a41 100644
--- a/main/admin.py
+++ b/main/admin.py
@@ -53,7 +53,7 @@ class DefectInline(admin.TabularInline):
@admin.display(description="Nombre d'anomalies ouvertes")
def open_defect_count(obj: Vehicle):
- return obj.defect_set.filter(status=Defect.DefectStatus.OPEN).count()
+ return obj.open_defects.count()
@admin.register(Vehicle)
diff --git a/main/fixtures/main/initial_data.json b/main/fixtures/main/initial_data.json
index 1c9ba92..0ebe18d 100644
--- a/main/fixtures/main/initial_data.json
+++ b/main/fixtures/main/initial_data.json
@@ -80,7 +80,6 @@
"pk": 1,
"fields": {
"vehicle": "94deae57-cbac-4911-bcdf-14aa4b10448d",
- "type": "engine",
"status": "OPEN",
"creation_date": "2024-05-28",
"solution_date": null,
@@ -106,7 +105,6 @@
"pk": 3,
"fields": {
"vehicle": "3a8798e8-c193-4e75-868c-982e2f24b576",
- "type": "bulb",
"status": "SOLVED",
"creation_date": "2024-05-28",
"solution_date": null,
diff --git a/main/models.py b/main/models.py
index 5c0445e..8455cf8 100644
--- a/main/models.py
+++ b/main/models.py
@@ -87,6 +87,13 @@ def public_url(self) -> str:
def __str__(self):
return self.name
+ @property
+ def open_defects(self) -> models.QuerySet[Defect]:
+ return self.defect_set.filter(
+ models.Q(status=Defect.DefectStatus.OPEN)
+ | models.Q(status=Defect.DefectStatus.CONFIRMED)
+ )
+
class Defect(models.Model):
class Meta:
diff --git a/main/templates/main/vehicle_detail.html b/main/templates/main/vehicle_detail.html
index 27fef78..b20badd 100644
--- a/main/templates/main/vehicle_detail.html
+++ b/main/templates/main/vehicle_detail.html
@@ -11,13 +11,13 @@ {{ vehicle.name }} Un trajet est en cours, pensez à le clôturer avant d'en commencer un nouveau
{% endif %}
- {% if major_defects %}
- Anomalies connues :
- {% for defect in major_defects %}
+ {% for defect in open_defects %}
+ {% if defect.severity == "MAJOR" %}
+
Anomalie connue :
⚠️ {{ defect.comment }}
- {% endfor %}
-
- {% endif %}
+
+ {% endif %}
+ {% endfor %}
Détails du véhicule
diff --git a/main/views.py b/main/views.py
index 593be89..cbf7c3a 100644
--- a/main/views.py
+++ b/main/views.py
@@ -9,7 +9,6 @@
from django.utils.translation import gettext as _
import django.shortcuts
from django.forms import BooleanField, HiddenInput, ModelForm
-from django.db.models import Q
from django.views.generic import CreateView, DetailView, ListView, UpdateView
from . import forms, models
@@ -31,14 +30,7 @@ def get_context_data(self, **kwargs):
self.object: models.Vehicle
context = super().get_context_data(**kwargs)
- context["open_defects"] = context["vehicle"].defect_set.filter(
- Q(status=models.Defect.DefectStatus.OPEN)
- | Q(status=models.Defect.DefectStatus.CONFIRMED)
- )
- context["major_defects"] = context["vehicle"].defect_set.filter(
- Q(status=models.Defect.DefectStatus.CONFIRMED)
- & Q(severity=models.Defect.DefectSeverity.MAJOR)
- )
+ context["open_defects"] = context["vehicle"].open_defects()
delegated_forms: dict[str, type[ModelForm]] = {
"defect_form": forms.DefectForm,
@@ -80,10 +72,18 @@ def get_context_data(self, **kwargs):
context["trip_started"] = False
except models.Trip.MultipleObjectsReturned:
- raise models.Trip.MultipleObjectsReturned(_("Corruption de la base de données : plusieurs trajets sont en cours !"))
-
+ raise models.Trip.MultipleObjectsReturned(
+ _(
+ "Corruption de la base de données : plusieurs trajets sont en cours !"
+ )
+ )
+
try:
- context["last_trip_distance"] = self.object.trip_set.filter(finished=True).latest("ending_time").distance
+ context["last_trip_distance"] = (
+ self.object.trip_set.filter(finished=True)
+ .latest("ending_time")
+ .distance
+ )
except models.Trip.DoesNotExist:
pass
From 5ce8bf07e76ee2671f4d615a1cf0de0674778883 Mon Sep 17 00:00:00 2001
From: Baptiste Lefeuvre
Date: Wed, 24 Jun 2026 10:18:17 +0200
Subject: [PATCH 3/3] Fix open_defects property usage on vehicles
---
main/templates/main/vehicle_detail.html | 2 +-
main/views.py | 5 ++---
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/main/templates/main/vehicle_detail.html b/main/templates/main/vehicle_detail.html
index b20badd..99572a7 100644
--- a/main/templates/main/vehicle_detail.html
+++ b/main/templates/main/vehicle_detail.html
@@ -96,7 +96,7 @@ {{ vehicle.name }} | {{ defect.get_severity_display|default:"-"}} |
{{ defect.creation_date }} |
{% endfor %}
diff --git a/main/views.py b/main/views.py
index d8e7052..b7d952c 100644
--- a/main/views.py
+++ b/main/views.py
@@ -6,9 +6,8 @@
import django.urls
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
-from django.utils.translation import gettext as _
-import django.shortcuts
from django.forms import BooleanField, HiddenInput, ModelForm
+from django.utils.translation import gettext as _
from django.views.generic import CreateView, DetailView, ListView, UpdateView
from . import forms, models
@@ -30,7 +29,7 @@ def get_context_data(self, **kwargs):
self.object: models.Vehicle
context = super().get_context_data(**kwargs)
- context["open_defects"] = context["vehicle"].open_defects()
+ context["open_defects"] = context["vehicle"].open_defects.all()
delegated_forms: dict[str, type[ModelForm]] = {
"defect_form": forms.DefectForm,