From 201d9dc48fa75c896d9dde8cf117c78b096700d8 Mon Sep 17 00:00:00 2001 From: Amir Date: Thu, 9 Oct 2025 19:40:34 +0200 Subject: [PATCH] Dodat je update content button, nakon sto se manuelno selektuju rizici --- backend/core/admin.py | 57 ++++++++++++++++++- .../admin/core/document/change_form.html | 1 + 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/backend/core/admin.py b/backend/core/admin.py index 90f8b3e..b9186b5 100644 --- a/backend/core/admin.py +++ b/backend/core/admin.py @@ -95,12 +95,12 @@ class DocumentAdmin(admin.ModelAdmin): search_fields = ['organization__name', 'organization__email'] readonly_fields = ( 'created_at', 'modified_at', 'regen_note_action', - 'regen_document_action', 'regen_top_risks_action', 'regen_controls_action', 'regen_keyfindings_action', 'regen_recommendations_action', + 'regen_document_action', 'regen_top_risks_action','update_risk_content_action', 'regen_controls_action', 'regen_keyfindings_action', 'regen_recommendations_action', ) fieldsets = ( ('Organization & Risks', { - 'fields': ('organization', 'regen_note_action', 'regen_document_action', 'organization_risks', 'risk_explanations', 'regen_top_risks_action') + 'fields': ('organization', 'regen_note_action', 'regen_document_action', 'organization_risks','update_risk_content_action', 'risk_explanations', 'regen_top_risks_action') }), ('Key Findings', { 'fields': ('key_findings', 'regen_keyfindings_action') @@ -157,6 +157,16 @@ class DocumentAdmin(admin.ModelAdmin): ) regen_document_action.short_description = '' + def update_risk_content_action(self, obj): + return format_html( + '
' + '🔁 Update existing content: synchronize risks, controls, and explanations without regenerating everything from scratch.' + '
' + '
' + '' + ) + update_risk_content_action.short_description = '' + def save_model(self, request, obj, form, change): super().save_model(request, obj, form, change) org_risks = form.cleaned_data.get('organization_risks') @@ -298,7 +308,7 @@ class DocumentAdmin(admin.ModelAdmin): return False def changeform_view(self, request, object_id=None, form_url='', extra_context=None): - if request.method == 'POST' and any(k in request.POST for k in ("_regen_controls", "_regen_key_findings", "_regen_recommendations", "_regen_top_risks", "_regen_document")): + if request.method == 'POST' and any(k in request.POST for k in ("_regen_controls", "_regen_key_findings", "_regen_recommendations", "_regen_top_risks", "_regen_document", "_update_risk_content")): obj = self.get_object(request, object_id) if obj is None: return super().changeform_view(request, object_id, form_url, extra_context) @@ -312,6 +322,13 @@ class DocumentAdmin(admin.ModelAdmin): self.message_user(request, "Top risks regenerated and risk segment updated.") else: self.message_user(request, "Top risks could not be generated.", level=messages.WARNING) + elif "_update_risk_content" in request.POST: + try: + self._update_risk_content(obj) + self.message_user(request, "Risk content successfully synchronized (kept existing explanations and controls).") + except Exception as e: + logger.exception("Update risk content failed") + self.message_user(request, f"Risk content update failed: {e}", level=messages.ERROR) elif "_regen_controls" in request.POST: self._regen_controls(obj) self.message_user(request, "Risks and controls regenerated successfully.") @@ -402,6 +419,40 @@ class DocumentAdmin(admin.ModelAdmin): self._refresh_segments_from_current_mappings(obj) except Exception: logger.exception("Failed to refresh segments from current mappings for document %s", getattr(obj, 'pk', None)) + + def _update_risk_content(self, obj): + """ + Synchronizes the document risks and explanations with the organization's current risks. + Keeps existing explanations for unchanged risks, adds blanks for new ones, + and removes explanations + controls for deleted risks. + Does NOT auto-generate new controls for added risks. + """ + org = obj.organization + if not org: + raise ValueError("Organization not set for this document.") + + existing_explanations = obj.risk_explanations or {} + existing_risk_ids = set(map(int, existing_explanations.keys())) + actual_risk_ids = set(org.risks.values_list('pk', flat=True)) + removed_risks = existing_risk_ids - actual_risk_ids + added_risks = actual_risk_ids - existing_risk_ids + new_explanations = {} + + for risk_id in actual_risk_ids & existing_risk_ids: + new_explanations[str(risk_id)] = existing_explanations.get(str(risk_id), "") + + for risk_id in added_risks: + new_explanations[str(risk_id)] = "" + + obj.risk_explanations = new_explanations + obj.save(update_fields=["risk_explanations", "modified_at"]) + + if removed_risks: + control = DocumentRiskControl.objects.filter(document=obj, risk_id__in=removed_risks) + for c in control: + c.risk = None + + self._refresh_segments_from_current_mappings(obj) class DocumentTemplateAdmin(admin.ModelAdmin): list_display = ['name', 'created_at', 'updated_at', 'preview_button'] diff --git a/backend/core/templates/admin/core/document/change_form.html b/backend/core/templates/admin/core/document/change_form.html index 6fd51f3..f0d64aa 100644 --- a/backend/core/templates/admin/core/document/change_form.html +++ b/backend/core/templates/admin/core/document/change_form.html @@ -24,6 +24,7 @@ .form-row.field-regen_keyfindings_action label, .form-row.field-regen_document_action label, .form-row.field-regen_note_action label, + .form-row.field-update_risk_content_action label, .form-row.field-regen_recommendations_action label { display: none; } .form-row.field-regen_top_risks_action label { display: none; } .form-row.field-regen_controls_action { display: none !important; }