diff --git a/backend/sellers/models.py b/backend/sellers/models.py
index 65ac8042..72ed8624 100644
--- a/backend/sellers/models.py
+++ b/backend/sellers/models.py
@@ -42,6 +42,11 @@ class SupplierProfile(models.Model):
bank_name = models.CharField(max_length=255, blank=True, null=True)
is_bank_verified = models.BooleanField(default=False)
tax_mode = models.CharField(max_length=20, default='gstin')
+ gi_seller_type = models.CharField(max_length=50, default='non_gi')
+ is_exclusive_gi = models.BooleanField(default=False)
+ gi_certificate_number = models.CharField(max_length=100, blank=True, null=True)
+ guild_status = models.CharField(max_length=255, blank=True, null=True)
+ gi_registry_verified = models.BooleanField(default=False)
class Meta:
managed = False
diff --git a/backend/sellers/serializers.py b/backend/sellers/serializers.py
index 63cc23f0..bea60dee 100644
--- a/backend/sellers/serializers.py
+++ b/backend/sellers/serializers.py
@@ -191,6 +191,11 @@ class SupplierProfileDetailSerializer(serializers.ModelSerializer):
"bank_name",
"is_bank_verified",
"tax_mode",
+ "gi_seller_type",
+ "is_exclusive_gi",
+ "gi_certificate_number",
+ "guild_status",
+ "gi_registry_verified",
"date_joined",
"metrics",
"products",
diff --git a/backend/sellers/views.py b/backend/sellers/views.py
index 41be93a7..b5e3df7c 100644
--- a/backend/sellers/views.py
+++ b/backend/sellers/views.py
@@ -20,6 +20,96 @@ from .serializers import (
BulkUploadLogSerializer,
SellerOrderSerializer,
)
+import logging
+
+logger = logging.getLogger(__name__)
+
+
+def sync_seller_gi_profile(pk=None, product=None):
+ """
+ Synchronizes the seller's GI accreditation in seller_db (api_supplierprofile).
+ By default, a seller is categorized under Non-GI Craft ('non_gi').
+ If the seller applied for any GI tag and it has been approved through the CRM,
+ their profile is updated to 'exclusive' (all active products are GI-certified)
+ or 'mixed' (carries certified GI along with general crafts).
+ """
+ try:
+ seller = None
+ if pk:
+ seller = SupplierProfile.objects.filter(models.Q(pk=pk) | models.Q(id=pk) | models.Q(user_id=pk)).first()
+ if not seller and product and hasattr(product, 'supplier_id'):
+ seller = SupplierProfile.objects.filter(
+ models.Q(pk=product.supplier_id) | models.Q(user_id=product.supplier_id)
+ ).first()
+
+ if not seller:
+ return
+
+ approved_prods = Product.objects.using("product_db").filter(
+ models.Q(supplier_id=seller.id) | models.Q(supplier_id=seller.user_id),
+ status="approved",
+ is_active=True
+ )
+ total_approved = approved_prods.count()
+ gi_approved = approved_prods.filter(is_gi_tagged=True)
+ gi_count = gi_approved.count()
+
+ if gi_count > 0:
+ first_gi = gi_approved.first()
+ gi_name = (
+ getattr(first_gi, "gi_tag_name", None)
+ or getattr(first_gi, "statutory_certifications", None)
+ or "Govt. of India GI Registry Verified"
+ )
+ if gi_count == total_approved and total_approved > 0:
+ seller.gi_seller_type = "exclusive"
+ seller.is_exclusive_gi = True
+ else:
+ seller.gi_seller_type = "mixed"
+ seller.is_exclusive_gi = False
+
+ seller.gi_registry_verified = True
+ if not getattr(seller, "gi_certificate_number", None):
+ seller.gi_certificate_number = gi_name
+ if not getattr(seller, "guild_status", None):
+ seller.guild_status = getattr(first_gi, "geographical_origin", None) or "Certified GI Artisan Maker"
+ else:
+ # Default to Non-GI Craft
+ seller.gi_seller_type = "non_gi"
+ seller.is_exclusive_gi = False
+ seller.gi_registry_verified = False
+
+ try:
+ seller.save()
+ except Exception as save_err:
+ logger.warning("Standard seller save failed, ensuring columns: %s", save_err)
+ with connections["seller_db"].cursor() as cursor:
+ cursor.execute("""
+ ALTER TABLE api_supplierprofile
+ ADD COLUMN IF NOT EXISTS gi_seller_type VARCHAR(50) DEFAULT 'non_gi',
+ ADD COLUMN IF NOT EXISTS is_exclusive_gi BOOLEAN DEFAULT FALSE,
+ ADD COLUMN IF NOT EXISTS gi_certificate_number VARCHAR(100),
+ ADD COLUMN IF NOT EXISTS guild_status VARCHAR(255),
+ ADD COLUMN IF NOT EXISTS gi_registry_verified BOOLEAN DEFAULT FALSE;
+ """)
+ cursor.execute("""
+ UPDATE api_supplierprofile
+ SET gi_seller_type = %s,
+ is_exclusive_gi = %s,
+ gi_certificate_number = %s,
+ guild_status = %s,
+ gi_registry_verified = %s
+ WHERE id = %s;
+ """, [
+ seller.gi_seller_type,
+ seller.is_exclusive_gi,
+ seller.gi_certificate_number,
+ seller.guild_status,
+ seller.gi_registry_verified,
+ seller.id
+ ])
+ except Exception as e:
+ logger.error("Error syncing seller GI accreditation profile: %s", e)
class SellerListView(APIView):
@@ -104,6 +194,11 @@ class SellerDetailView(APIView):
"account_number",
"ifsc_code",
"bank_name",
+ "gi_seller_type",
+ "is_exclusive_gi",
+ "gi_certificate_number",
+ "guild_status",
+ "gi_registry_verified",
]
for field in allowed_fields:
if field in request.data:
@@ -304,6 +399,9 @@ class SellerProductApproveView(APIView):
product.rejection_reason = None
product.save(using="product_db")
+ # Automatically update seller GI accreditation profile based on approved product catalog
+ sync_seller_gi_profile(pk=pk, product=product)
+
return Response({
"message": f"Product '{product.title}' has been approved and published to website.",
"product": ProductSerializer(product).data
@@ -324,6 +422,9 @@ class SellerProductRejectView(APIView):
product.rejection_reason = reason
product.save(using="product_db")
+ # Synchronize GI status in case all approved GI products were revoked
+ sync_seller_gi_profile(pk=pk, product=product)
+
return Response({
"message": f"Product '{product.title}' was rejected.",
"product": ProductSerializer(product).data,
@@ -377,6 +478,8 @@ class SellerProductDetailView(APIView):
setattr(product, field, request.data[field])
product.save(using="product_db")
+ sync_seller_gi_profile(pk=pk, product=product)
+
return Response({
"message": f"Product '{product.title}' content updated successfully.",
"product": ProductSerializer(product).data
@@ -398,6 +501,8 @@ class SellerProductToggleView(APIView):
product.status = request.data["status"]
product.save(using="product_db")
+ sync_seller_gi_profile(pk=pk, product=product)
+
return Response({
"message": f"Product '{product.title}' updated.",
"product": ProductSerializer(product).data
diff --git a/frontend/src/routes/(app)/sellers/[id]/+page.svelte b/frontend/src/routes/(app)/sellers/[id]/+page.svelte
index a1053db5..d97896c2 100644
--- a/frontend/src/routes/(app)/sellers/[id]/+page.svelte
+++ b/frontend/src/routes/(app)/sellers/[id]/+page.svelte
@@ -206,6 +206,14 @@
{seller.status}
+ {#if seller.gi_seller_type === 'exclusive'}
+