From 0abcb50e60698b7dd3732679e9d3fd9dc4478250 Mon Sep 17 00:00:00 2001 From: Egor fureunoir Gorbunov Date: Wed, 12 Nov 2025 15:29:08 +0300 Subject: [PATCH] Features: 1) Add predefined permission sets and corresponding group initialization in `initialize` command. Fixes: 1) Correct `image_url` return logic in models; 2) Fix indentation in the `save` method of `payments` model; 3) Update a minor comment typo in `serializers.py`. Extra: 1) Minor cleanup of unused imports in `initialize` command. --- engine/core/management/commands/initialize.py | 145 +++++++++++++++++- engine/core/models.py | 4 +- engine/payments/models.py | 2 +- engine/vibes_auth/messaging/serializers.py | 2 +- 4 files changed, 142 insertions(+), 11 deletions(-) diff --git a/engine/core/management/commands/initialize.py b/engine/core/management/commands/initialize.py index 658adb62..bbb3dd8f 100644 --- a/engine/core/management/commands/initialize.py +++ b/engine/core/management/commands/initialize.py @@ -1,25 +1,156 @@ import logging from typing import Any +from django.contrib.auth.models import Permission from django.core.management.base import BaseCommand from engine.core.models import Vendor from engine.vibes_auth.models import Group -from django.contrib.auth.models import Permission logger = logging.getLogger(__name__) +user_support_permissions = [ + "add_chatmessage", + "view_chatmessage", + "change_chatthread", + "view_chatthread", + "view_order", + "view_ordercrmlink", + "view_orderproduct", + "view_address", + "view_user", + "view_wishlist", + "view_balance", + "view_transaction", +] + +stock_manager_permissions = [ + "add_stock", + "change_stock", + "view_stock", + "add_category", + "change_category", + "view_category", + "add_brand", + "change_brand", + "view_brand", + "add_product", + "change_product", + "view_product", + "add_attribute", + "change_attribute", + "view_attribute", + "add_attributevalue", + "change_attributevalue", + "view_attributevalue", + "add_attributegroup", + "change_attributegroup", + "view_attributegroup", + "add_productimage", + "change_productimage", + "view_productimage", +] + +head_stock_manager_permissions = [ + *stock_manager_permissions, + "delete_stock", + "delete_product", + "delete_attribute", + "delete_attributevalue", + "delete_attributegroup", + "delete_productimage", + "add_vendor", + "change_vendor", + "view_vendor", + "view_user", +] + +marketing_admin_permissions = [ + "view_feedback", + "delete_feedback", + "add_producttag", + "change_producttag", + "delete_producttag", + "view_producttag", + "add_categorytag", + "change_categorytag", + "delete_categorytag", + "view_categorytag", + "add_promocode", + "change_promocode", + "delete_promocode", + "view_promocode", + "add_promotion", + "change_promotion", + "delete_promotion", + "view_promotion", + "view_wishlist", + "add_post", + "change_post", + "delete_post", + "view_post", + "add_posttag", + "change_posttag", + "delete_posttag", + "view_posttag", + "add_attachment", + "change_attachment", + "delete_attachment", + "view_attachment", + "add_messageattachment", + "change_messageattachment", + "delete_messageattachment", + "view_messageattachment", +] + +e_commerce_admin_permissions = [ + *user_support_permissions, + *head_stock_manager_permissions, + *marketing_admin_permissions, + "add_constance", + "change_constance", + "delete_constance", + "view_constance", + "add_gateway", + "change_gateway", + "delete_gateway", + "view_gateway", + "view_periodictask", + "view_periodictasks", + "change_user", + "view_group", +] + class Command(BaseCommand): def handle(self, *args: list[Any], **options: dict[Any, Any]) -> None: self.stdout.write("Initializing must-have instances...") Vendor.objects.get_or_create(name="INNER") - Group.objects.get_or_create(name="User Support") - Permission.objects.all() - # TODO get_or_create a group "Product Listing Administrator" with corresponding permissions - # TODO get_or_create a group "Head Product Listing Administrator" with corresponding permissions - # TODO get_or_create a group "E-Commerce Administrator" with corresponding permissions - # maybe use some .json file for future updates?.. Say, use the engine/core/fixtures/initialization.json + user_support, is_user_support_created = Group.objects.get_or_create(name="User Support") + if not is_user_support_created: + perms = Permission.objects.filter(codename__in=user_support_permissions) + user_support.permissions.add(*perms) + + stock_manager, is_stock_manager_created = Group.objects.get_or_create(name="Stock Manager") + if not is_stock_manager_created: + perms = Permission.objects.filter(codename__in=stock_manager_permissions) + stock_manager.permissions.add(*perms) + + head_stock_manager, is_head_stock_manager_created = Group.objects.get_or_create(name="Head Stock Manager") + if not is_head_stock_manager_created: + perms = Permission.objects.filter(codename__in=head_stock_manager_permissions) + head_stock_manager.permissions.add(*perms) + + marketing_admin, is_marketing_admin_created = Group.objects.get_or_create(name="Marketing Admin") + if not is_marketing_admin_created: + perms = Permission.objects.filter(codename__in=marketing_admin_permissions) + marketing_admin.permissions.add(*perms) + + e_commerce_admin, is_e_commerce_admin_created = Group.objects.get_or_create(name="E-Commerce Admin") + if not is_e_commerce_admin_created: + perms = Permission.objects.filter(codename__in=e_commerce_admin_permissions) + e_commerce_admin.permissions.add(*perms) + self.stdout.write(self.style.SUCCESS("Successfully initialized must-have instances!")) diff --git a/engine/core/models.py b/engine/core/models.py index 5df02d7b..57aa654b 100644 --- a/engine/core/models.py +++ b/engine/core/models.py @@ -424,7 +424,7 @@ class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): # def image_url(self) -> str: with suppress(ValueError): url = str(self.image.url) - url = url if "http" in url else f"https://api.{settings.BASE_DOMAIN}{url}" + return url if "http" in url else f"https://api.{settings.BASE_DOMAIN}{url}" return "" class Meta: @@ -854,7 +854,7 @@ class ProductImage(ExportModelOperationsMixin("product_image"), NiceModel): # t def image_url(self) -> str: with suppress(ValueError): url = str(self.image.url) - url = url if "http" in url else f"https://api.{settings.BASE_DOMAIN}{url}" + return url if "http" in url else f"https://api.{settings.BASE_DOMAIN}{url}" return "" class Meta: diff --git a/engine/payments/models.py b/engine/payments/models.py index 50b71961..e7ba8c6b 100644 --- a/engine/payments/models.py +++ b/engine/payments/models.py @@ -48,7 +48,7 @@ class Transaction(NiceModel): def save(self, **kwargs): if len(str(self.amount).split(".")[1]) > 2: - self.amount = round(self.amount, 2) + self.amount = round(self.amount, 2) super().save(**kwargs) return self diff --git a/engine/vibes_auth/messaging/serializers.py b/engine/vibes_auth/messaging/serializers.py index ac2c9384..543b4393 100644 --- a/engine/vibes_auth/messaging/serializers.py +++ b/engine/vibes_auth/messaging/serializers.py @@ -73,7 +73,7 @@ class StaffInboxEventSerializer(Serializer): """A flexible event serializer for staff inbox messages over WS.""" type = CharField(required=True) - # Optional fields depending on event type + # Optional fields depending on the event type threads = ListField(child=InboxThreadItemSerializer(), required=False) thread_id = CharField(required=False) user = CharField(required=False)