From a4ca20c8be9887cc0ed81ddc27b3b9c05a7fcce4 Mon Sep 17 00:00:00 2001 From: Egor fureunoir Gorbunov Date: Sun, 7 Sep 2025 01:06:36 +0300 Subject: [PATCH] Features: 1) Add `CustomerRelationshipManagementProvider` model with fields for integration details and attributes; 2) Add `OrderCrmLink` model to associate orders with CRM providers; 3) Register both models (`CustomerRelationshipManagementProvider` and `OrderCrmLink`) in the admin interface; Fixes: 1) Correct verbose_name usage for `attributes` field in an existing model; Extra: 1) Adjust admin field grouping and formatting consistency for readability. --- core/admin.py | 51 +++++- ...tionshipmanagementprovider_ordercrmlink.py | 158 ++++++++++++++++++ core/models.py | 2 +- 3 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 core/migrations/0040_customerrelationshipmanagementprovider_ordercrmlink.py diff --git a/core/admin.py b/core/admin.py index 5a2de805..c188b2fa 100644 --- a/core/admin.py +++ b/core/admin.py @@ -33,6 +33,8 @@ from core.models import ( Stock, Vendor, Wishlist, + CustomerRelationshipManagementProvider, + OrderCrmLink, ) from evibes.settings import CONSTANCE_CONFIG @@ -469,7 +471,12 @@ class ProductImageAdmin(FieldsetsMixin, ActivationActionsMixin, ModelAdmin): # readonly_fields = ("uuid", "modified", "created") autocomplete_fields = ("product",) - general_fields = ["is_active", "alt", "priority", "image"] + general_fields = [ + "is_active", + "alt", + "priority", + "image", + ] relation_fields = ["product"] @@ -500,7 +507,47 @@ class AddressAdmin(FieldsetsMixin, GISModelAdmin): "country", "raw_data", ] - relation_fields = ["user", "api_response"] + relation_fields = [ + "user", + "api_response", + ] + + +@register(CustomerRelationshipManagementProvider) +class CustomerRelationshipManagementProviderAdmin(FieldsetsMixin, ModelAdmin): + # noinspection PyClassVar + model = CustomerRelationshipManagementProvider # type: ignore [misc] + list_display = ("name", "default") + search_fields = ("name",) + + general_fields = [ + "is_active", + "name", + "default", + "integration_url", + "integration_location", + "attributes", + "authentication", + ] + relation_fields = [] + + +@register(OrderCrmLink) +class OrderCrmLinkAdmin(FieldsetsMixin, ModelAdmin): + # noinspection PyClassVar + model = OrderCrmLink # type: ignore [misc] + list_display = ("crm_lead_id",) + search_fields = ("crm_lead_id",) + + general_fields = [ + "is_active", + "crm_lead_id", + ] + relation_fields = [ + "order", + "crm", + ] + readonly_fields = ("crm_lead_id",) # Constance configuration diff --git a/core/migrations/0040_customerrelationshipmanagementprovider_ordercrmlink.py b/core/migrations/0040_customerrelationshipmanagementprovider_ordercrmlink.py new file mode 100644 index 00000000..cd240f0f --- /dev/null +++ b/core/migrations/0040_customerrelationshipmanagementprovider_ordercrmlink.py @@ -0,0 +1,158 @@ +# Generated by Django 5.2 on 2025-09-06 22:05 + +import django.db.models.deletion +import django_extensions.db.fields +import django_prometheus.models +import uuid +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("core", "0039_alter_product_sku"), + ] + + operations = [ + migrations.CreateModel( + name="CustomerRelationshipManagementProvider", + fields=[ + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, + help_text="when the object was last modified", + verbose_name="modified", + ), + ), + ( + "name", + models.CharField(max_length=128, unique=True, verbose_name="name"), + ), + ( + "integration_url", + models.URLField( + blank=True, help_text="URL of the integration", null=True + ), + ), + ( + "authentication", + models.JSONField( + blank=True, help_text="authentication credentials", null=True + ), + ), + ( + "attributes", + models.JSONField(blank=True, null=True, verbose_name="attributes"), + ), + ( + "integration_location", + models.CharField(blank=True, max_length=128, null=True), + ), + ("default", models.BooleanField(default=False)), + ], + options={ + "verbose_name": "order CRM link", + "verbose_name_plural": "orders CRM links", + }, + bases=( + django_prometheus.models.ExportModelOperationsMixin("crm_provider"), + models.Model, + ), + ), + migrations.CreateModel( + name="OrderCrmLink", + fields=[ + ( + "uuid", + models.UUIDField( + default=uuid.uuid4, + editable=False, + help_text="unique id is used to surely identify any database object", + primary_key=True, + serialize=False, + verbose_name="unique id", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="if set to false, this object can't be seen by users without needed permission", + verbose_name="is active", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, + help_text="when the object first appeared on the database", + verbose_name="created", + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, + help_text="when the object was last modified", + verbose_name="modified", + ), + ), + ( + "crm_lead_id", + models.CharField(db_index=True, max_length=30, unique=True), + ), + ( + "crm", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="order_links", + to="core.customerrelationshipmanagementprovider", + ), + ), + ( + "order", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="crm_links", + to="core.order", + ), + ), + ], + options={ + "verbose_name": "order CRM link", + "verbose_name_plural": "orders CRM links", + }, + bases=( + django_prometheus.models.ExportModelOperationsMixin("order_crm_link"), + models.Model, + ), + ), + ] diff --git a/core/models.py b/core/models.py index 4f9f321d..757f8d9c 100644 --- a/core/models.py +++ b/core/models.py @@ -1964,7 +1964,7 @@ class CustomerRelationshipManagementProvider(ExportModelOperationsMixin("crm_pro name = CharField(max_length=128, unique=True, verbose_name=_("name")) integration_url = URLField(blank=True, null=True, help_text=_("URL of the integration")) authentication = JSONField(blank=True, null=True, help_text=_("authentication credentials")) - attributes = JSONField(blank=True, null=True, help_name=_("attributes")) + attributes = JSONField(blank=True, null=True, verbose_name=_("attributes")) integration_location = CharField(max_length=128, blank=True, null=True) default = BooleanField(default=False)