Skip to content

Commit

Permalink
Add documentation score (#1339)
Browse files Browse the repository at this point in the history
* Add documentation score

* Handle null score

* style: improve score display

* locale: add french translation

* chore: remove comment

* fix migration conflict

* ruff

* update ruff version

* Lean down Score component

* Add 'change' event dispatcher to Checkbox component

* Adapt table mode and requirement assessment edit to new Score component

* chore: Remove dead code

* chore: ruff format

* Uncomment cache decorators

* Fix migration conflicts

* chore: ruff format

* fix: display default score label when no documentation score

* feat: update documentation score if null

---------

Co-authored-by: Mohamed-Hacene <[email protected]>
Co-authored-by: eric-intuitem <[email protected]>
Co-authored-by: Nassim Tabchiche <[email protected]>
  • Loading branch information
4 people authored Jan 13, 2025
1 parent d9cbf97 commit 4a9cf29
Show file tree
Hide file tree
Showing 34 changed files with 354 additions and 180 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/backend-linters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Install ruff
working-directory: ${{env.working-directory}}
run: |
python -m pip install ruff==0.9.0
python -m pip install ruff==0.9.1
- name: Run ruff format check
working-directory: ${{env.working-directory}}
run: ruff format --check .
Expand Down
4 changes: 4 additions & 0 deletions backend/core/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ def get_sorted_requirement_nodes_rec(start: list) -> dict:
"result": req_as.result if req_as else None,
"is_scored": req_as.is_scored if req_as else None,
"score": req_as.score if req_as else None,
"documentation_score": req_as.documentation_score if req_as else None,
"max_score": max_score if req_as else None,
"question": req_as.answer if req_as else node.question,
"mapping_inference": req_as.mapping_inference if req_as else None,
Expand Down Expand Up @@ -324,6 +325,9 @@ def get_sorted_requirement_nodes_rec(start: list) -> dict:
"status": child_req_as.status if child_req_as else None,
"is_scored": child_req_as.is_scored if child_req_as else None,
"score": child_req_as.score if child_req_as else None,
"documentation_score": child_req_as.documentation_score
if child_req_as
else None,
"max_score": max_score if child_req_as else None,
"question": child_req_as.answer if child_req_as else child.question,
"mapping_inference": child_req_as.mapping_inference
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 5.1.4 on 2025-01-13 09:51

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("core", "0048_alter_asset_security_objectives"),
]

operations = [
migrations.AddField(
model_name="complianceassessment",
name="show_documentation_score",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="requirementassessment",
name="documentation_score",
field=models.IntegerField(
blank=True, null=True, verbose_name="Documentation Score"
),
),
]
21 changes: 15 additions & 6 deletions backend/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2732,6 +2732,7 @@ class ComplianceAssessment(Assessment):
scores_definition = models.JSONField(
blank=True, null=True, verbose_name=_("Score definition")
)
show_documentation_score = models.BooleanField(default=False)

class Meta:
verbose_name = _("Compliance assessment")
Expand Down Expand Up @@ -2808,7 +2809,6 @@ def create_requirement_assessments(
def get_global_score(self):
requirement_assessments_scored = (
RequirementAssessment.objects.filter(compliance_assessment=self)
.exclude(score=None)
.exclude(status=RequirementAssessment.Result.NOT_APPLICABLE)
.exclude(is_scored=False)
.exclude(requirement__assessable=False)
Expand All @@ -2820,12 +2820,18 @@ def get_global_score(self):
)
score = 0
n = 0

for ras in requirement_assessments_scored:
if not (ig) or (ig & set(ras.requirement.implementation_groups)):
score += ras.score
score += ras.score or 0
n += 1
if self.show_documentation_score:
score += ras.documentation_score or 0
n += 1
if n > 0:
return round(score / n, 1)
global_score = score / n
# We use this instead of using the python round function so that the python backend outputs the same result as the javascript frontend.
return int(global_score * 10) / 10
else:
return -1

Expand Down Expand Up @@ -3250,14 +3256,17 @@ class Result(models.TextChoices):
verbose_name=_("Result"),
default=Result.NOT_ASSESSED,
)
is_scored = models.BooleanField(
default=False,
verbose_name=_("Is scored"),
)
score = models.IntegerField(
blank=True,
null=True,
verbose_name=_("Score"),
)
is_scored = models.BooleanField(
default=False,
verbose_name=_("Is scored"),
documentation_score = models.IntegerField(
blank=True, null=True, verbose_name=_("Documentation Score")
)
evidences = models.ManyToManyField(
Evidence,
Expand Down
13 changes: 13 additions & 0 deletions backend/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2526,6 +2526,18 @@ def perform_create(self, serializer):
for requirement_assessment in instance.requirement_assessments.all():
requirement_assessment.create_applied_controls_from_suggestions()

def perform_update(self, serializer):
compliance_assessment = serializer.save()
if compliance_assessment.show_documentation_score:
ra_null_documentation_score = RequirementAssessment.objects.filter(
compliance_assessment=compliance_assessment,
is_scored=True,
documentation_score__isnull=True,
)
ra_null_documentation_score.update(
documentation_score=compliance_assessment.min_score
)

@action(detail=False, name="Compliance assessments per status")
def per_status(self, request):
data = assessment_per_status(request.user, ComplianceAssessment)
Expand Down Expand Up @@ -2564,6 +2576,7 @@ def global_score(self, request, pk):
"scores_definition": get_referential_translation(
compliance_assessment.framework, "scores_definition", get_language()
),
"show_documentation_score": compliance_assessment.show_documentation_score,
}
)

Expand Down
5 changes: 4 additions & 1 deletion frontend/messages/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -862,9 +862,12 @@
"addTag": "إضافة علامة",
"tagsHelpText": "تُستخدم العلامات لتصنيف العناصر وتصفيتها. يمكنك إضافة علامات في قسم \"إضافي\"",
"forgotPassword": "هل نسيت كلمة السر",
"scoreSemiColon": "نتيجة:",
"score": "نتيجة",
"mappingInferenceHelpText": "هذه المتغيرات ثابتة ولن تتغير اعتمادًا على المصدر.",
"bringTheEvidences": "أحضر الأدلة",
"bringTheEvidencesHelpText": "في حالة التعطيل، سيتم تكرار الكائن بدون أدلته",
"documentationScore": "درجة التوثيق",
"useDocumentationScore": "استخدام درجة التوثيق",
"useDocumentationScoreHelpText": "ستتوفر درجة ثانية (درجة التوثيق) لتقييم المتطلبات.",
"publicationDate": "تاريخ النشر"
}
4 changes: 4 additions & 0 deletions frontend/messages/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,7 @@
"youCanSetNewPassword": "Zde si můžete nastavit nové heslo",
"userWillBeDisconnected": "Uživatel bude odpojen a bude se muset znovu přihlásit",
"scoresDefinition": "Definice skóre",
"score": "Skóre",
"selectedImplementationGroups": "Vybrané implementační skupiny",
"implementationGroupsDefinition": "Definice implementačních skupin",
"threatRadarChart": "Radarový graf hrozeb",
Expand Down Expand Up @@ -855,5 +856,8 @@
"tagsHelpText": "Štítky pomáhají kategorizovat a filtrovat více objektů. Můžete je spravovat v menu Extra.",
"bringTheEvidences": "Přineste důkazy",
"bringTheEvidencesHelpText": "Pokud je zakázáno, objekt bude duplikován bez jeho důkazů",
"documentationScore": "Skóre dokumentace",
"useDocumentationScore": "Použití skóre dokumentace",
"useDocumentationScoreHelpText": "Pro posouzení požadavků bude k dispozici druhé bodové skóre (skóre dokumentace).",
"publicationDate": "Datum zveřejnění"
}
5 changes: 4 additions & 1 deletion frontend/messages/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -861,9 +861,12 @@
"addTag": "Tag hinzufügen",
"tagsHelpText": "Tags werden zum Kategorisieren und Filtern der Elemente verwendet. Sie können Tags im Abschnitt Extra hinzufügen",
"forgotPassword": "Passwort vergessen",
"scoreSemiColon": "Punktzahl:",
"score": "Punktzahl",
"mappingInferenceHelpText": "Diese Variablen sind fest und ändern sich je nach Quelle nicht.",
"bringTheEvidences": "Bringen Sie die Beweise",
"bringTheEvidencesHelpText": "Wenn deaktiviert, wird das Objekt ohne seine Beweise dupliziert",
"documentationScore": "Bewertung der Dokumentation",
"useDocumentationScore": "Dokumentationsnote verwenden",
"useDocumentationScoreHelpText": "Eine zweite Punktzahl (Dokumentationspunktzahl) wird verfügbar sein, um die Anforderungen zu bewerten.",
"publicationDate": "Veröffentlichungsdatum"
}
8 changes: 6 additions & 2 deletions frontend/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,7 @@
"youCanSetPasswordHere": "You can set your password here",
"forgotPassword": "Forgot password",
"ssoSettingsUpdated": "SSO settings updated",
"scoreSemiColon": "Score:",
"score": "Score",
"mappingInferenceHelpText": "These variables are fixed and will not change depending on the source.",
"priority": "Priority",
"p1": "P1",
Expand Down Expand Up @@ -1083,5 +1083,9 @@
"missionsAndOrganizationalServices": "Missions and organizational services",
"human": "Human",
"material": "Material",
"environmental": "Environmental"
"environmental": "Environmental",
"documentationScore": "Documentation score",
"implementationScore": "Implementation score",
"useDocumentationScore": "Use documentation score",
"useDocumentationScoreHelpText": "A second score (the documentation score) will be available for scoring the requirements."
}
5 changes: 4 additions & 1 deletion frontend/messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -861,9 +861,12 @@
"addTag": "Agregar etiqueta",
"tagsHelpText": "Las etiquetas se utilizan para categorizar y filtrar los elementos. Puedes agregar etiquetas en la sección Extra",
"forgotPassword": "Has olvidado tu contraseña",
"scoreSemiColon": "Puntaje:",
"score": "Puntaje",
"mappingInferenceHelpText": "Estas variables son fijas y no cambiarán dependiendo de la fuente.",
"bringTheEvidences": "Traer las evidencias",
"bringTheEvidencesHelpText": "Si está deshabilitado, el objeto se duplicará sin sus evidencias.",
"documentationScore": "Puntuación de la documentación",
"useDocumentationScore": "Utilizar la puntuación de la documentación",
"useDocumentationScoreHelpText": "Se dispondrá de una segunda puntuación (puntuación de la documentación) para evaluar los requisitos.",
"publicationDate": "Fecha de publicación"
}
8 changes: 6 additions & 2 deletions frontend/messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,7 @@
"youCanSetPasswordHere": "Vous pouvez définir votre mot de passe ici",
"forgotPassword": "Mot de passe oublié",
"ssoSettingsUpdated": "Paramètres SSO mis à jour",
"scoreSemiColon": "Score:",
"score": "Score",
"mappingInferenceHelpText": "Ces variables sont fixes et ne changeront pas en fonction de la source.",
"priority": "Priorité",
"p1": "P1",
Expand Down Expand Up @@ -1083,5 +1083,9 @@
"missionsAndOrganizationalServices": "Missions et service de l'organisation",
"human": "Humain",
"material": "Matériel",
"environmental": "Environnemental"
"environmental": "Environnemental",
"documentationScore": "Score de documentation",
"implementationScore": "Score d'implémentation",
"useDocumentationScore": "Utiliser le score de documentation",
"useDocumentationScoreHelpText": "Un deuxième score (le score de documentation) sera disponible pour évaluer les exigences."
}
5 changes: 4 additions & 1 deletion frontend/messages/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -861,9 +861,12 @@
"addTag": "टैग जोड़ें",
"tagsHelpText": "टैग का उपयोग आइटम को वर्गीकृत और फ़िल्टर करने के लिए किया जाता है। आप अतिरिक्त अनुभाग में टैग जोड़ सकते हैं",
"forgotPassword": "पासवर्ड भूल गए",
"scoreSemiColon": "अंक:",
"score": "अंक",
"mappingInferenceHelpText": "ये चर निश्चित हैं और स्रोत के आधार पर परिवर्तित नहीं होंगे।",
"bringTheEvidences": "सबूत लाओ",
"bringTheEvidencesHelpText": "यदि अक्षम किया गया है, तो ऑब्जेक्ट को उसके साक्ष्य के बिना डुप्लिकेट किया जाएगा",
"documentationScore": "दस्तावेज़ीकरण स्कोर",
"useDocumentationScore": "दस्तावेज़ स्कोर का उपयोग करें",
"useDocumentationScoreHelpText": "आवश्यकताओं का आकलन करने के लिए दूसरी रेटिंग (दस्तावेज़ीकरण स्कोर) उपलब्ध होगी।",
"publicationDate": "प्रकाशन की तिथि"
}
7 changes: 5 additions & 2 deletions frontend/messages/id.json
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,7 @@
"youCanSetPasswordHere": "Anda dapat mengatur kata sandi Anda di sini",
"forgotPassword": "Lupa kata sandi",
"ssoSettingsUpdated": "Pengaturan SSO diperbarui",
"scoreSemiColon": "Skor:",
"score": "Skor",
"mappingInferenceHelpText": "Variabel-variabel ini tetap dan tidak akan berubah tergantung pada sumber.",
"priority": "Prioritas",
"p1": "P1",
Expand Down Expand Up @@ -1083,5 +1083,8 @@
"missionsAndOrganizationalServices": "Misi dan layanan organisasi",
"human": "Manusia",
"material": "Materi",
"environmental": "Lingkungan"
"environmental": "Lingkungan",
"documentationScore": "Skor dokumentasi",
"useDocumentationScore": "Gunakan skor dokumentasi",
"useDocumentationScoreHelpText": "Skor kedua (skor dokumentasi) akan tersedia untuk menilai persyaratan."
}
5 changes: 4 additions & 1 deletion frontend/messages/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -861,9 +861,12 @@
"addTag": "Aggiungi tag",
"tagsHelpText": "I tag vengono utilizzati per categorizzare e filtrare gli elementi. Puoi aggiungere tag nella sezione Extra",
"forgotPassword": "Ha dimenticato la password",
"scoreSemiColon": "Punto:",
"score": "Punto",
"mappingInferenceHelpText": "Queste variabili sono fisse e non cambiano a seconda della fonte.",
"bringTheEvidences": "Portare le prove",
"bringTheEvidencesHelpText": "Se disabilitato, l'oggetto verrà duplicato senza le sue prove",
"documentationScore": "Punteggio della documentazione",
"useDocumentationScore": "Utilizzare il punteggio della documentazione",
"useDocumentationScoreHelpText": "Un secondo punteggio (punteggio di documentazione) sarà disponibile per valutare i requisiti.",
"publicationDate": "Data di pubblicazione"
}
5 changes: 4 additions & 1 deletion frontend/messages/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -861,9 +861,12 @@
"addTag": "Tag toevoegen",
"tagsHelpText": "Tags worden gebruikt om de items te categoriseren en te filteren. U kunt tags toevoegen in de sectie Extra",
"forgotPassword": "Wachtwoord vergeten",
"scoreSemiColon": "Punt:",
"score": "Punt",
"mappingInferenceHelpText": "Deze variabelen zijn vast en veranderen niet, afhankelijk van de bron.",
"bringTheEvidences": "Breng de bewijzen",
"bringTheEvidencesHelpText": "Als dit is uitgeschakeld, wordt het object gedupliceerd zonder de bijbehorende bewijzen",
"documentationScore": "Documentatie score",
"useDocumentationScore": "Documentatiescore gebruiken",
"useDocumentationScoreHelpText": "Een tweede score (documentatiescore) zal beschikbaar zijn om de vereisten te beoordelen.",
"publicationDate": "Publicatiedatum"
}
5 changes: 4 additions & 1 deletion frontend/messages/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -861,9 +861,12 @@
"addTag": "Dodaj tag",
"tagsHelpText": "Tagi służą do kategoryzowania i filtrowania elementów. Możesz dodać tagi w sekcji Extra",
"forgotPassword": "Zapomniałem hasła",
"scoreSemiColon": "Wynik:",
"score": "Wynik",
"mappingInferenceHelpText": "Te zmienne są stałe i nie zmieniają się w zależności od źródła.",
"bringTheEvidences": "Przynieś dowody",
"bringTheEvidencesHelpText": "Jeśli wyłączone, obiekt zostanie zduplikowany bez dowodów",
"documentationScore": "Wynik dokumentacji",
"useDocumentationScore": "Korzystanie z punktacji dokumentacji",
"useDocumentationScoreHelpText": "Drugi wynik (wynik dokumentacji) będzie dostępny do oceny wymagań.",
"publicationDate": "Data publikacji"
}
5 changes: 4 additions & 1 deletion frontend/messages/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -861,9 +861,12 @@
"addTag": "Adicionar etiqueta",
"tagsHelpText": "As tags são usadas para categorizar e filtrar os itens. Você pode adicionar tags na seção Extra",
"forgotPassword": "Esqueceu sua senha",
"scoreSemiColon": "Pontuação:",
"score": "Pontuação",
"mappingInferenceHelpText": "Essas variáveis são fixas e não mudarão dependendo da fonte.",
"bringTheEvidences": "Traga as evidências",
"bringTheEvidencesHelpText": "Se desabilitado, o objeto será duplicado sem suas evidências",
"documentationScore": "Pontuação da documentação",
"useDocumentationScore": "Utilizar a pontuação da documentação",
"useDocumentationScoreHelpText": "Uma segunda pontuação (a pontuação da documentação) estará disponível para avaliar os requisitos.",
"publicationDate": "Data de publicação"
}
5 changes: 4 additions & 1 deletion frontend/messages/ro.json
Original file line number Diff line number Diff line change
Expand Up @@ -861,9 +861,12 @@
"addTag": "Adăugați etichetă",
"tagsHelpText": "Etichetele sunt folosite pentru a clasifica și filtra articolele. Puteți adăuga etichete în secțiunea Extra",
"forgotPassword": "Aţi uitat parola",
"scoreSemiColon": "Scor:",
"score": "Scor",
"mappingInferenceHelpText": "Aceste variabile sunt fixe și nu se vor modifica în funcție de sursă.",
"bringTheEvidences": "Aduceți dovezile",
"bringTheEvidencesHelpText": "Dacă este dezactivat, obiectul va fi duplicat fără dovezile sale",
"documentationScore": "Punctajul documentației",
"useDocumentationScore": "Utilizați punctajul documentației",
"useDocumentationScoreHelpText": "Un al doilea punctaj (punctajul pentru documentație) va fi disponibil pentru evaluarea cerințelor.",
"publicationDate": "Data publicării"
}
5 changes: 4 additions & 1 deletion frontend/messages/sv.json
Original file line number Diff line number Diff line change
Expand Up @@ -861,9 +861,12 @@
"youCanSetPasswordHere": "Du kan ställa in ditt lösenord här.",
"forgotPassword": "Glömt lösenord",
"ssoSettingsUpdated": "SSO-inställningar uppdaterade",
"scoreSemiColon": "Göra:",
"score": "Göra",
"mappingInferenceHelpText": "Dessa variabler är fasta och kommer inte att ändras beroende på källan.",
"bringTheEvidences": "Kom med bevisen",
"bringTheEvidencesHelpText": "Om det är inaktiverat kommer objektet att dupliceras utan dess bevis",
"documentationScore": "Poäng för dokumentation",
"useDocumentationScore": "Använd poängsättning av dokumentation",
"useDocumentationScoreHelpText": "En andra poäng (dokumentationspoängen) kommer att finnas tillgänglig för att bedöma kraven.",
"publicationDate": "Publiceringsdatum"
}
5 changes: 4 additions & 1 deletion frontend/messages/ur.json
Original file line number Diff line number Diff line change
Expand Up @@ -861,9 +861,12 @@
"addTag": "ٹیگ شامل کریں۔",
"tagsHelpText": "ٹیگز اشیاء کی درجہ بندی اور فلٹر کرنے کے لیے استعمال ہوتے ہیں۔ آپ اضافی سیکشن میں ٹیگ شامل کر سکتے ہیں۔",
"forgotPassword": "پاس ورڈ بھول گئے۔",
"scoreSemiColon": "سکور:",
"score": "سکور",
"mappingInferenceHelpText": "یہ متغیرات طے شدہ ہیں اور ماخذ کے لحاظ سے تبدیل نہیں ہوں گے۔",
"bringTheEvidences": "ثبوت لے کر آئیں",
"bringTheEvidencesHelpText": "اگر غیر فعال ہو تو، اعتراض کو اس کے ثبوت کے بغیر نقل کر دیا جائے گا۔",
"documentationScore": "دستاویزی سکور",
"useDocumentationScore": "دستاویزی سکور استعمال کریں۔",
"useDocumentationScoreHelpText": "ضروریات کو پورا کرنے کے لیے دوسرا سکور (دستاویزی سکور) دستیاب ہوگا۔",
"publicationDate": "اشاعت کی تاریخ"
}
Loading

0 comments on commit 4a9cf29

Please sign in to comment.