From 6436649488bb6d62f000a6492fdd0ecfcbc1912c Mon Sep 17 00:00:00 2001 From: ismail Date: Mon, 30 Jun 2025 13:56:23 +0300 Subject: [PATCH] update permission --- inventory/forms.py | 149 +++++++++++--- inventory/templatetags/custom_filters.py | 9 +- inventory/views.py | 104 ++++++---- .../groups/group_permission_form-copy.html | 45 +++++ templates/groups/group_permission_form.html | 182 ++++++++++++++---- 5 files changed, 391 insertions(+), 98 deletions(-) create mode 100644 templates/groups/group_permission_form-copy.html diff --git a/inventory/forms.py b/inventory/forms.py index 39158b24..35f15024 100644 --- a/inventory/forms.py +++ b/inventory/forms.py @@ -1528,44 +1528,139 @@ class GroupForm(forms.ModelForm): fields = ["name"] +# class PermissionForm(forms.ModelForm): +# """ +# Represents a form for managing permissions using a multiple-choice field. + +# This class is a Django ModelForm that is used to handle permission +# assignments. It provides a multiple selection widget pre-populated with +# permissions based on specific app labels. The form offers a way to submit +# and validate permission data for further processing. + +# :ivar name: A multiple-choice field that allows users to select permissions +# related to specific app labels (`inventory` and `django_ledger`). +# :type name: ModelMultipleChoiceField +# """ + +# name = forms.ModelMultipleChoiceField( +# queryset=cache.get( +# "permissions_queryset", +# Permission.objects.filter( +# content_type__app_label__in=["inventory", "django_ledger"] +# ), +# ), +# widget=forms.CheckboxSelectMultiple(), +# required=True, +# ) + +# def __init__(self, *args, **kwargs): +# super().__init__(*args, **kwargs) +# cache.set( +# "permissions_queryset", +# Permission.objects.filter( +# content_type__app_label__in=["inventory", "django_ledger"] +# ), +# 60 * 60, +# ) + +# class Meta: +# model = Permission +# fields = ["name"] class PermissionForm(forms.ModelForm): """ - Represents a form for managing permissions using a multiple-choice field. - - This class is a Django ModelForm that is used to handle permission - assignments. It provides a multiple selection widget pre-populated with - permissions based on specific app labels. The form offers a way to submit - and validate permission data for further processing. - - :ivar name: A multiple-choice field that allows users to select permissions - related to specific app labels (`inventory` and `django_ledger`). - :type name: ModelMultipleChoiceField + Form for managing permissions with grouped checkboxes by app and model. """ - - name = forms.ModelMultipleChoiceField( - queryset=cache.get( - "permissions_queryset", - Permission.objects.filter( - content_type__app_label__in=["inventory", "django_ledger"] - ), - ), - widget=forms.CheckboxSelectMultiple(), - required=True, - ) - def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - cache.set( + EXCLUDED_MODELS = [ + "inventory.car", + "inventory.carfinance", + "inventory.carlocation", + "inventory.customcard", + "inventory.cartransfer", + "inventory.carcolors", + "inventory.carequipment", + "inventory.interiorcolors", + "inventory.exteriorcolors", + "inventory.carreservation", + "inventory.lead", + "inventory.customgroup", + "inventory.saleorder", + "inventory.payment", + "inventory.staff", + "inventory.schedule", + "inventory.activity", + "inventory.opportunity", + "django_ledger.estimatemodel", + "django_ledger.invoicemodel", + "django_ledger.accountmodel", + "django_ledger.chartofaccountmodel", + "django_ledger.customermodel", + "django_ledger.billmodel" + "inventory.car", + "inventory.carequipment", + "inventory.interiorcolors", + "inventory.exteriorcolors", + "inventory.carcolors", + "inventory.carlocation", + "inventory.customcard", + "inventory.carreservation" + "django_ledger.estimatemodel", + "django_ledger.invoicemodel", + "django_ledger.customermodel", + "inventory.saleorder", + "inventory.payment", + "inventory.staff", + "inventory.schedule", + "inventory.activity", + "inventory.opportunity", + "inventory.customer", + "inventory.organization", + "inventory.lead", + "inventory.salequotation", + "inventory.salequotationcar" + "inventory.carfinance", + "django_ledger.bankaccountmodel", + "django_ledger.accountmodel", + "django_ledger.chartofaccountmodel", + "django_ledger.customcard", + "django_ledger.billmodel", + "django_ledger.itemmodel", + "django_ledger.invoicemodel", + "django_ledger.vendormodel", + "django_ledger.journalentrymodel" + ] + + permissions = cache.get( "permissions_queryset", Permission.objects.filter( - content_type__app_label__in=["inventory", "django_ledger"] - ), - 60 * 60, + content_type__app_label__in=[m.split('.')[0] for m in EXCLUDED_MODELS], + content_type__model__in=[m.split('.')[1] for m in EXCLUDED_MODELS] + ).select_related('content_type') + ) + + # Group permissions by app_label and model + self.grouped_permissions = {} + for perm in permissions: + app_label = perm.content_type.app_label + model = perm.content_type.model + if app_label not in self.grouped_permissions: + self.grouped_permissions[app_label] = {} + if model not in self.grouped_permissions[app_label]: + self.grouped_permissions[app_label][model] = [] + self.grouped_permissions[app_label][model].append(perm) + + # Create a multiple choice field (hidden, will use custom rendering) + self.fields['permissions'] = forms.ModelMultipleChoiceField( + queryset=permissions, + widget=forms.MultipleHiddenInput(), + required=False, + initial=self.instance.permissions.all() if self.instance.pk else [] ) class Meta: model = Permission - fields = ["name"] + fields = [] class UserGroupForm(forms.ModelForm): diff --git a/inventory/templatetags/custom_filters.py b/inventory/templatetags/custom_filters.py index f8cbea70..b5adad28 100644 --- a/inventory/templatetags/custom_filters.py +++ b/inventory/templatetags/custom_filters.py @@ -644,4 +644,11 @@ def inventory_table(context, queryset): "inventory_list": queryset, } ctx.update(queryset.aggregate(inventory_total_value=Sum("total_value"))) - return ctx \ No newline at end of file + return ctx + + +@register.filter +def count_checked(permissions): + """Count how many permissions are marked as checked""" + print(permissions) + return sum(1 for perm in permissions if getattr(perm, 'is_checked', False)) \ No newline at end of file diff --git a/inventory/views.py b/inventory/views.py index 9ec86ae9..1f458881 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -2757,42 +2757,78 @@ def GroupDeleteview(request, dealer_slug,pk): @login_required -def GroupPermissionView(request, dealer_slug,pk): - """ - Handles the view for adding or modifying permissions of a specific group. This view - fetches the group based on the primary key passed as a parameter, and either displays - a form for editing permissions or processes the submitted permissions. +def GroupPermissionView(request, dealer_slug, pk): + # Verify dealer and group exist + get_object_or_404(models.Dealer, slug=dealer_slug) + customgroup = get_object_or_404(models.CustomGroup, pk=pk) - If the request method is POST, the permissions of the group are cleared and updated - based on the submitted data. A success message is displayed upon completion, and - the user is redirected to the group's detail page. - - In case of a GET request, the view renders the form pre-filled with the group's - current permissions. - - :param request: The HTTP request object. - :type request: HttpRequest - :param pk: The primary key of the group whose permissions are being modified. - :type pk: int - :return: The HTTP response depending on the request type. For GET requests, renders - the permission form for the specified group. For POST requests, clears and updates - the group's permissions and redirects to the group's detail page. - :rtype: HttpResponse - """ - get_object_or_404(models.Dealer,slug=dealer_slug) - group = get_object_or_404(models.CustomGroup, pk=pk) if request.method == "POST": - form = forms.PermissionForm(request.POST) - group.clear_permissions() - permissions = request.POST.getlist("name") - for i in permissions: - group.add_permission(Permission.objects.get(id=int(i))) - messages.success(request, _("Permission added successfully")) - return redirect("group_detail", dealer_slug=dealer_slug,pk=group.pk) - form = forms.PermissionForm(initial={"name": group.permissions}) - return render( - request, "groups/group_permission_form.html", {"group": group, "form": form} - ) + form = forms.PermissionForm(request.POST, instance=customgroup) + if form.is_valid(): + # Clear existing permissions + customgroup.clear_permissions() + + # Add new permissions from form + permissions = form.cleaned_data.get('permissions', []) + for permission in permissions: + customgroup.add_permission(permission) + + messages.success(request, _("Permissions updated successfully")) + return redirect("group_detail", dealer_slug=dealer_slug, pk=customgroup.pk) + else: + # Initial form with current permissions + form = forms.PermissionForm(instance=customgroup) + + group_permission_ids = set(customgroup.permissions.values_list('id', flat=True)) + + # Mark permissions as checked in the form data + for app_label, model in form.grouped_permissions.items(): + for mo, perms in model.items(): + for perm in perms: + perm.is_checked = perm.id in group_permission_ids + + return render(request,"groups/group_permission_form.html", { + "group": customgroup, + "form": form, + "group_permission_apps": set(customgroup.group.permissions.values_list('content_type__app_label', flat=True)), + "group_permission_models": set(customgroup.group.permissions.values_list('content_type__model', flat=True)) + }) +# def GroupPermissionView(request, dealer_slug,pk): +# """ +# Handles the view for adding or modifying permissions of a specific group. This view +# fetches the group based on the primary key passed as a parameter, and either displays +# a form for editing permissions or processes the submitted permissions. + +# If the request method is POST, the permissions of the group are cleared and updated +# based on the submitted data. A success message is displayed upon completion, and +# the user is redirected to the group's detail page. + +# In case of a GET request, the view renders the form pre-filled with the group's +# current permissions. + +# :param request: The HTTP request object. +# :type request: HttpRequest +# :param pk: The primary key of the group whose permissions are being modified. +# :type pk: int +# :return: The HTTP response depending on the request type. For GET requests, renders +# the permission form for the specified group. For POST requests, clears and updates +# the group's permissions and redirects to the group's detail page. +# :rtype: HttpResponse +# """ +# get_object_or_404(models.Dealer,slug=dealer_slug) +# group = get_object_or_404(models.CustomGroup, pk=pk) +# if request.method == "POST": +# form = forms.PermissionForm(request.POST) +# group.clear_permissions() +# permissions = request.POST.getlist("name") +# for i in permissions: +# group.add_permission(Permission.objects.get(id=int(i))) +# messages.success(request, _("Permission added successfully")) +# return redirect("group_detail", dealer_slug=dealer_slug,pk=group.pk) +# form = forms.PermissionForm(initial={"name": group.permissions}) +# return render( +# request, "groups/group_permission_form.html", {"group": group, "form": form} +# ) # Users diff --git a/templates/groups/group_permission_form-copy.html b/templates/groups/group_permission_form-copy.html new file mode 100644 index 00000000..cf14458d --- /dev/null +++ b/templates/groups/group_permission_form-copy.html @@ -0,0 +1,45 @@ +{% extends "base.html" %} +{% load i18n %} +{% load crispy_forms_filters %} +{% block title %}{% trans "Permission" %}{% endblock title %} + +{% block content %} + + +
+
+
+
+ +

+ {% if group.created %} + {{ _("Edit Permission") }} + {% else %} + {{ _("Add Permission") }} + {% endif %} +

+
+
+
+
+
+ +
+ {% csrf_token %} + {{ redirect_field }} + {{ form|crispy }} + {% for error in form.errors %} +
{{ error }}
+ {% endfor %} +
+ {% trans "Cancel"|capfirst %} + +
+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/templates/groups/group_permission_form.html b/templates/groups/group_permission_form.html index cf14458d..a9eb8cae 100644 --- a/templates/groups/group_permission_form.html +++ b/templates/groups/group_permission_form.html @@ -1,45 +1,155 @@ {% extends "base.html" %} {% load i18n %} -{% load crispy_forms_filters %} -{% block title %}{% trans "Permission" %}{% endblock title %} +{% load custom_filters %} + +{% block title %}{% trans "Permission Management" %}{% endblock title %} {% block content %} +
+
+
+
+

+ {% if group %} + {{ _("Edit Permissions for") }}: {{ group.name }} + {% else %} + {{ _("Add Permissions") }} + {% endif %} +

- -
-
-
-
- -

- {% if group.created %} - {{ _("Edit Permission") }} - {% else %} - {{ _("Add Permission") }} - {% endif %} -

-
-
-
-
-
- -
- {% csrf_token %} - {{ redirect_field }} - {{ form|crispy }} - {% for error in form.errors %} -
{{ error }}
- {% endfor %} -
- {% trans "Cancel"|capfirst %} - -
-
+ +
+ {% csrf_token %} + + +
+ {% for app_label, models in form.grouped_permissions.items %} +
+
+
+
+
+ + {{ app_label|capfirst }} +
+ + {{ models|length }} {% trans "models" %} + +
+
+
+
+ {% for model, perms in models.items %} +
+
+ +
+
+
+
+ {% for perm in perms %} + + {% endfor %} +
+
+
+
+ {% endfor %} +
+
+
+
+ {% endfor %} +
+ +
+
+
+
+ + {{ group.permissions.count }} {% trans "selected" %} + + + {% trans "Permissions will be updated immediately" %} + +
+
+ + {% trans "Cancel" %} + + +
+
+
+
+
+
+ + + + {% endblock %} \ No newline at end of file