from django.db import transaction from rest_framework import serializers from core.apps.products.models import Product, Unity from core.apps.projects.models import Project, ProjectFolder from core.apps.wherehouse.models import ( Inventory, StockMovemend, StockMovmendProduct, WhereHouse, ) from core.apps.accounts.models import User class StockMovmendProductSerializer(serializers.Serializer): inventory_id = serializers.UUIDField() quantity = serializers.IntegerField() def validate(self, data): inventory = Inventory.objects.filter(id=data["inventory_id"]).first() if not inventory: raise serializers.ValidationError("Inventory not found") data["inventory"] = inventory return data class StockMovmendCreateSerializer(serializers.Serializer): products = StockMovmendProductSerializer(many=True) project_folder_id = serializers.UUIDField(required=False) project_id = serializers.UUIDField(required=False) wherehouse_to_id = serializers.UUIDField() wherehouse_from_id = serializers.UUIDField() date = serializers.DateField(required=False) comment = serializers.CharField(required=False) recipient_id = serializers.UUIDField(required=False) def validate(self, data): if data.get("project_folder_id"): project_folder = ProjectFolder.objects.filter( id=data["project_folder_id"] ).first() if not project_folder: raise serializers.ValidationError("Project Folder not found") data["project_folder"] = project_folder if data.get("project_id"): project = Project.objects.filter(id=data["project_id"]).first() if not project: raise serializers.ValidationError("Project not found") data["project"] = project wherehouse_to = WhereHouse.objects.filter(id=data["wherehouse_to_id"]).first() if not wherehouse_to: raise serializers.ValidationError("WhereHouse to not found") wherehouse_from = WhereHouse.objects.filter( id=data["wherehouse_from_id"] ).first() if not wherehouse_from: raise serializers.ValidationError("WhereHouse from not found") if data.get('recipient_id'): recipient = User.objects.filter(id=data.get('recipient_id')).first() if not recipient: raise serializers.ValidationError("Recipient not found") data['recipient'] = recipient data["wherehouse_to"] = wherehouse_to data["wherehouse_from"] = wherehouse_from return data def create(self, validated_data): with transaction.atomic(): products = validated_data.pop("products") stock_movemend = StockMovemend.objects.create( project_folder=validated_data.get("project_folder"), project=validated_data.get("project"), date=validated_data.get("date"), comment=validated_data.get("comment"), wherehouse_to=validated_data.get("wherehouse_to"), wherehouse_from=validated_data.get("wherehouse_from"), sender=self.context.get("user"), recipient=validated_data.get('recipient'), ) movmend_products = [] for product in products: movmend_products.append( StockMovmendProduct( inventory=product.get("inventory"), quantity=product.get("quantity"), stock_movemend=stock_movemend, ) ) StockMovmendProduct.objects.bulk_create(movmend_products) return stock_movemend class StockMovemendProductListSerializer(serializers.ModelSerializer): product = serializers.SerializerMethodField(method_name="get_product") unity = serializers.SerializerMethodField(method_name="get_unity") class Meta: model = StockMovmendProduct fields = ["id", "product", "unity", "quantity"] def get_product(self, obj): return ( { "id": obj.inventory.product.id, "type": obj.inventory.product.type, "name": obj.inventory.product.name, } if obj.inventory and obj.inventory.product else None ) def get_unity(self, obj): return ( { "id": obj.inventory.unity.id, "value": obj.inventory.unity.value, } if obj.inventory and obj.inventory.unity else None ) class StockMovemendListSerializer(serializers.ModelSerializer): movemend_products = StockMovemendProductListSerializer(many=True) wherehouse_to = serializers.SerializerMethodField(method_name="get_wherehouse_to") wherehouse_from = serializers.SerializerMethodField( method_name="get_wherehouse_from" ) recipient = serializers.SerializerMethodField(method_name="get_recipient") sender = serializers.SerializerMethodField(method_name="get_sender") project_folder = serializers.SerializerMethodField(method_name="get_project_folder") project = serializers.SerializerMethodField(method_name="get_project") class Meta: model = StockMovemend fields = [ "id", "number", "wherehouse_to", "wherehouse_from", "recipient", "sender", "project_folder", "project", "movemend_type", "date", "comment", "movemend_products", ] def get_wherehouse_to(self, obj): return ( { "id": obj.wherehouse_to.id, "name": obj.wherehouse_to.name, } if obj.wherehouse_to else None ) def get_wherehouse_from(self, obj): return ( { "id": obj.wherehouse_from.id, "name": obj.wherehouse_from.name, } if obj.wherehouse_from else None ) def get_recipient(self, obj): return ( { "id": obj.recipient.id, "full_name": obj.recipient.full_name, } if obj.recipient else None ) def get_sender(self, obj): return ( { "id": obj.sender.id, "full_name": obj.sender.full_name, } if obj.sender else None ) def get_project_folder(self, obj): return ( {"id": obj.project_folder.id, "name": obj.project_folder.name} if obj.project_folder else None ) def get_project(self, obj): return {"id": obj.project.id, "name": obj.project.name} if obj.project else None class StockMovemendProductUpdateSerializer(serializers.Serializer): movemend_product_id = serializers.UUIDField() quantity = serializers.IntegerField() def validate(self, data): movemend_product = StockMovmendProduct.objects.filter( id=data["movemend_product_id"] ).first() if not movemend_product: raise serializers.ValidationError("Stock Movemend Product not found") if movemend_product.inventory.quantity < data["quantity"]: raise serializers.ValidationError( "invalid quantity, quantity must les than product quantity" ) data["movemend_product"] = movemend_product return data class StockMovemendUpdateSerializer(serializers.ModelSerializer): movemend_products = StockMovemendProductUpdateSerializer(many=True, required=False) class Meta: model = StockMovemend fields = [ "wherehouse_to", "project_folder", "project", "date", "comment", "movemend_products", ] extra_kwargs = {"wherehouse_to": {"required": False}} def update(self, instance, validated_data): with transaction.atomic(): instance.wherehouse_to = validated_data.get( "wherehouse_to", instance.wherehouse_to ) instance.project_folder = validated_data.get( "project_folder", instance.project_folder ) instance.project = validated_data.get("project", instance.project) instance.date = validated_data.get("date", instance.date) instance.comment = validated_data.get("comment", instance.comment) instance.save() movemend_products = validated_data.pop("movemend_products", []) if movemend_products: updated_products = [] for product_data in movemend_products: product = product_data["movemend_product"] product.quantity = product_data["quantity"] updated_products.append(product) StockMovmendProduct.objects.bulk_update( updated_products, fields=["quantity"] ) return instance