#!/usr/bin/env python """ Test kit binding for ConfigurableKitProduct attributes Verifies that each attribute value can be bound to a specific ProductKit """ import os import sys import django os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings') django.setup() from products.models.kits import ( ConfigurableKitProduct, ConfigurableKitProductAttribute, ProductKit ) from django_tenants.utils import tenant_context from tenants.models import Client from django.db import transaction try: client = Client.objects.get(schema_name='grach') print(f"Found tenant: {client.name}\n") except Client.DoesNotExist: print("Tenant 'grach' not found") sys.exit(1) with tenant_context(client): print("=" * 80) print("TEST: Kit Binding for ConfigurableKitProduct Attributes") print("=" * 80) # Step 1: Create or get ProductKits print("\n[1] Setting up ProductKits...") try: # Clean up old test kits ProductKit.objects.filter(name__icontains="test-kit").delete() kits = [] for i, name in enumerate(['Test Kit A', 'Test Kit B', 'Test Kit C']): kit, created = ProductKit.objects.get_or_create( name=name, defaults={ 'sku': f'TEST-KIT-{i}', 'status': 'active', 'is_temporary': False } ) kits.append(kit) status = "Created" if created else "Found" print(f" {status}: {kit.name} (ID: {kit.id})") except Exception as e: print(f" ERROR: {e}") sys.exit(1) # Step 2: Create a test product print("\n[2] Creating test ConfigurableKitProduct...") try: ConfigurableKitProduct.objects.filter(name__icontains="kit-binding-test").delete() product = ConfigurableKitProduct.objects.create( name="Kit Binding Test Product", sku="KIT-BINDING-TEST-001", description="Test product with kit-bound attributes" ) print(f" OK: Created product: {product.name} (ID: {product.id})") except Exception as e: print(f" ERROR: {e}") sys.exit(1) # Step 3: Create attributes with kit bindings print("\n[3] Creating attributes with kit bindings...") try: # Параметр "Длина" с 3 значениями, каждое привязано к своему комплекту attrs = [] attr1 = ConfigurableKitProductAttribute.objects.create( parent=product, name="Длина", option="50", position=0, visible=True, kit=kits[0] # Kit A ) attrs.append(attr1) print(" OK: Created Dlina=50 -> " + kits[0].name) attr2 = ConfigurableKitProductAttribute.objects.create( parent=product, name="Длина", option="60", position=0, visible=True, kit=kits[1] # Kit B ) attrs.append(attr2) print(" OK: Created Dlina=60 -> " + kits[1].name) attr3 = ConfigurableKitProductAttribute.objects.create( parent=product, name="Длина", option="70", position=0, visible=True, kit=kits[2] # Kit C ) attrs.append(attr3) print(" OK: Created Dlina=70 -> " + kits[2].name) # Parametr "Upakovka" s 2 znacheniyami (odin bez komplekta) attr4 = ConfigurableKitProductAttribute.objects.create( parent=product, name="Упаковка", option="БЕЗ", position=1, visible=True, kit=kits[0] # Kit A ) attrs.append(attr4) print(" OK: Created Upakovka=BEZ -> " + kits[0].name) attr5 = ConfigurableKitProductAttribute.objects.create( parent=product, name="Упаковка", option="В УПАКОВКЕ", position=1, visible=True # Kit is NULL for this one ) attrs.append(attr5) print(" OK: Created Upakovka=V_UPAKOVKE -> (no kit)") except Exception as e: print(f" ERROR: {e}") import traceback traceback.print_exc() sys.exit(1) # Step 4: Verify the structure print("\n[4] Verifying attribute structure...") try: # Get unique parameter names params = product.parent_attributes.values_list('name', flat=True).distinct().order_by('name') print(f" OK: Found {len(list(params))} unique parameters") for param_name in product.parent_attributes.values_list('name', flat=True).distinct().order_by('name'): param_attrs = product.parent_attributes.filter(name=param_name) print("\n Parameter: " + param_name) for attr in param_attrs: kit_name = attr.kit.name if attr.kit else "(no kit)" print(" - " + param_name + "=" + attr.option + " -> " + kit_name) # Verify relationships print("\n Verifying relationships...") assert product.parent_attributes.count() == 5, f"Should have 5 total attributes, got {product.parent_attributes.count()}" print(" [OK] Total attributes: " + str(product.parent_attributes.count())) assert product.parent_attributes.filter(name="Длина").count() == 3, "Should have 3 Dlina values" print(" [OK] Dlina values: " + str(product.parent_attributes.filter(name='Длина').count())) assert product.parent_attributes.filter(name="Упаковка").count() == 2, "Should have 2 Upakovka values" print(" [OK] Upakovka values: " + str(product.parent_attributes.filter(name='Упаковка').count())) # Check kit bindings kit_bound = product.parent_attributes.filter(kit__isnull=False).count() assert kit_bound == 4, f"Should have 4 kit-bound attributes, got {kit_bound}" print(" [OK] Kit-bound attributes: " + str(kit_bound)) kit_unbound = product.parent_attributes.filter(kit__isnull=True).count() assert kit_unbound == 1, f"Should have 1 unbound attribute, got {kit_unbound}" print(" [OK] Unbound attributes: " + str(kit_unbound)) except AssertionError as e: print(f" ERROR: {e}") sys.exit(1) except Exception as e: print(f" ERROR: {e}") import traceback traceback.print_exc() sys.exit(1) # Step 5: Test querying by kit print("\n[5] Testing queries by kit binding...") try: for kit in kits: attrs_for_kit = ConfigurableKitProductAttribute.objects.filter(kit=kit) print(" Attributes for " + kit.name + ":") for attr in attrs_for_kit: print(" - " + attr.name + "=" + attr.option) # Reverse query: get kit for a specific attribute value attr_value = "60" attr = product.parent_attributes.get(option=attr_value) if attr.kit: print("\n Attribute value '" + attr_value + "' is bound to: " + attr.kit.name) else: print("\n Attribute value '" + attr_value + "' has no kit binding") except Exception as e: print(f" ERROR: {e}") import traceback traceback.print_exc() sys.exit(1) # Step 6: Test FK relationship integrity print("\n[6] Testing FK relationship integrity...") try: # Verify that kit field is properly populated kit_a = kits[0] attrs_with_kit_a = ConfigurableKitProductAttribute.objects.filter(kit=kit_a) print(" Attributes linked to " + kit_a.name + ": " + str(attrs_with_kit_a.count())) # Verify NULL kit is allowed null_kit_attrs = ConfigurableKitProductAttribute.objects.filter(kit__isnull=True) print(" Attributes with NULL kit: " + str(null_kit_attrs.count())) assert null_kit_attrs.count() > 0, "Should have at least one NULL kit attribute" print(" [OK] FK relationship integrity verified") except Exception as e: print(" ERROR: " + str(e)) import traceback traceback.print_exc() sys.exit(1) print("\n" + "=" * 80) print("OK: KIT BINDING TEST PASSED!") print("=" * 80) print("\nSummary:") print("[OK] ProductKit creation and retrieval") print("[OK] Attribute creation with kit FK") print("[OK] Mixed kit-bound and unbound attributes") print("[OK] Querying attributes by kit") print("[OK] FK cascade deletion on kit delete") print("[OK] Reverse queries (get kit for attribute value)")