diff --git a/core/apps/vendors/models/product_variant.py b/core/apps/vendors/models/product_variant.py index e7c6567..9087768 100644 --- a/core/apps/vendors/models/product_variant.py +++ b/core/apps/vendors/models/product_variant.py @@ -3,6 +3,8 @@ from django.utils.translation import gettext_lazy as _ from django_core.models import AbstractBaseModel + + class ProductVariantModel(AbstractBaseModel): product = models.ForeignKey( "VendorproductModel", diff --git a/core/apps/vendors/serializers/vendor_product/VendorProduct.py b/core/apps/vendors/serializers/vendor_product/VendorProduct.py index 6303dfa..3b6cf91 100644 --- a/core/apps/vendors/serializers/vendor_product/VendorProduct.py +++ b/core/apps/vendors/serializers/vendor_product/VendorProduct.py @@ -1,3 +1,4 @@ +import json from rest_framework import serializers from core.apps.vendors.models import ( @@ -151,14 +152,63 @@ class CreateVendorproductSerializer(BaseVendorproductSerializer): write_only=True, required=False ) + variants = ProductVariantSerializer(many=True, required=False) class Meta(BaseVendorproductSerializer.Meta): fields = BaseVendorproductSerializer.Meta.fields + [ "uploaded_images", + "variants", ] + def to_internal_value(self, data): + # form-data kelsa QueryDict bo'ladi + # getlist() bilan bir xil kalit uchun barcha qiymatlarni olamiz, keyin dict'ga o'tkazamiz + if hasattr(data, "getlist"): + multi_images = data.getlist("uploaded_images") + data = data.dict() + if multi_images: + data["uploaded_images"] = multi_images + + # uploaded_images ichida URL string kelsa — ularni photos_json ga ko'chiramiz, + # haqiqiy fayllarni uploaded_images da qoldiramiz + raw_images = data.get("uploaded_images") + if raw_images: + if isinstance(raw_images, str): + try: + raw_images = json.loads(raw_images) + except (json.JSONDecodeError, TypeError): + raw_images = [raw_images] + + if isinstance(raw_images, list): + url_list = [v for v in raw_images if isinstance(v, str)] + file_list = [v for v in raw_images if not isinstance(v, str)] + + if url_list: + existing = data.get("photos_json") or [] + if isinstance(existing, str): + try: + existing = json.loads(existing) + except Exception: + existing = [] + data["photos_json"] = existing + url_list + + data["uploaded_images"] = file_list if file_list else [] + + json_fields = ["variants", "product_specification", "photos_json"] + for field in json_fields: + value = data.get(field) + if value and isinstance(value, str): + try: + data[field] = json.loads(value) + except (json.JSONDecodeError, TypeError): + pass + + return super().to_internal_value(data) + def create(self, validated_data): uploaded_images = validated_data.pop("uploaded_images", []) + variants_data = validated_data.pop("variants", []) + instance = super().create(validated_data) # Save additional gallery images @@ -168,19 +218,52 @@ class CreateVendorproductSerializer(BaseVendorproductSerializer): image=img, order=i ) + + # Save variants + for variant_data in variants_data: + ProductVariantModel.objects.create( + product=instance, + **variant_data + ) + return instance def update(self, instance, validated_data): uploaded_images = validated_data.pop("uploaded_images", []) + variants_data = validated_data.pop("variants", None) + instance = super().update(instance, validated_data) if uploaded_images: - # Optionally clear existing gallery or append? - # I'll append for now based on user's "how to upload multiple" for i, img in enumerate(uploaded_images): ProductimageModel.objects.create( product=instance, image=img, order=instance.images.count() + i ) + + if variants_data is not None: + # Simple approach: clear and recreation or matching by firestore_id/SKU + # For now, I'll update variants if they have an ID or firestore_id, otherwise create + + # To keep it robust, let's track current variants + current_variants = {v.firestore_id: v for v in instance.variants.all() if v.firestore_id} + + new_variants = [] + for v_data in variants_data: + v_fid = v_data.get("firestore_id") + if v_fid and v_fid in current_variants: + # Update existing + v_instance = current_variants.pop(v_fid) + for attr, value in v_data.items(): + setattr(v_instance, attr, value) + v_instance.save() + else: + # Create new + ProductVariantModel.objects.create(product=instance, **v_data) + + # Optional: delete variants that are not in the new data + # for v in current_variants.values(): + # v.delete() + return instance