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.
This commit is contained in:
Egor Pavlovich Gorbunov 2025-11-12 15:29:08 +03:00
parent d91a979e25
commit 0abcb50e60
4 changed files with 142 additions and 11 deletions

View file

@ -1,25 +1,156 @@
import logging import logging
from typing import Any from typing import Any
from django.contrib.auth.models import Permission
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from engine.core.models import Vendor from engine.core.models import Vendor
from engine.vibes_auth.models import Group from engine.vibes_auth.models import Group
from django.contrib.auth.models import Permission
logger = logging.getLogger(__name__) 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): class Command(BaseCommand):
def handle(self, *args: list[Any], **options: dict[Any, Any]) -> None: def handle(self, *args: list[Any], **options: dict[Any, Any]) -> None:
self.stdout.write("Initializing must-have instances...") self.stdout.write("Initializing must-have instances...")
Vendor.objects.get_or_create(name="INNER") 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!")) self.stdout.write(self.style.SUCCESS("Successfully initialized must-have instances!"))

View file

@ -424,7 +424,7 @@ class Category(ExportModelOperationsMixin("category"), NiceModel, MPTTModel): #
def image_url(self) -> str: def image_url(self) -> str:
with suppress(ValueError): with suppress(ValueError):
url = str(self.image.url) 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 "" return ""
class Meta: class Meta:
@ -854,7 +854,7 @@ class ProductImage(ExportModelOperationsMixin("product_image"), NiceModel): # t
def image_url(self) -> str: def image_url(self) -> str:
with suppress(ValueError): with suppress(ValueError):
url = str(self.image.url) 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 "" return ""
class Meta: class Meta:

View file

@ -48,7 +48,7 @@ class Transaction(NiceModel):
def save(self, **kwargs): def save(self, **kwargs):
if len(str(self.amount).split(".")[1]) > 2: if len(str(self.amount).split(".")[1]) > 2:
self.amount = round(self.amount, 2) self.amount = round(self.amount, 2)
super().save(**kwargs) super().save(**kwargs)
return self return self

View file

@ -73,7 +73,7 @@ class StaffInboxEventSerializer(Serializer):
"""A flexible event serializer for staff inbox messages over WS.""" """A flexible event serializer for staff inbox messages over WS."""
type = CharField(required=True) type = CharField(required=True)
# Optional fields depending on event type # Optional fields depending on the event type
threads = ListField(child=InboxThreadItemSerializer(), required=False) threads = ListField(child=InboxThreadItemSerializer(), required=False)
thread_id = CharField(required=False) thread_id = CharField(required=False)
user = CharField(required=False) user = CharField(required=False)