from django.db import transaction from rest_framework import serializers from core.apps.orders.models import Party, PartyAmount, Order, DeletedParty from core.apps.orders.serializers.order import MultipleOrderAddSerializer, OrderListSerializer from core.apps.accounts.models import User from core.apps.counterparty.serializers.counterparty import CounterpartyListPartySerializer from core.apps.shared.models import UsdCourse from core.apps.products.models import Product, Unity from core.apps.projects.models import Project, ProjectFolder from core.apps.wherehouse.models import WhereHouse from core.apps.counterparty.models import Counterparty class PartyCreateSerializer(serializers.Serializer): resources = MultipleOrderAddSerializer(many=True) mediator_id = serializers.UUIDField() delivery_date = serializers.DateField() payment_date = serializers.DateField() comment = serializers.CharField(required=False) discount = serializers.IntegerField(required=False) discount_currency = serializers.ChoiceField(choices=[('uzs', 'uzs'), ('usd', 'usd')], required=False) audit = serializers.ChoiceField( choices=[('CHECKED', 'tekshirildi'),('PROCESS', 'jarayonda')], required=False ) audit_comment = serializers.CharField(required=False) currency = serializers.ChoiceField(choices=[('uzs', 'uzs'), ('usd', 'usd')]) def validate(self, data): user = User.objects.filter(id=data['mediator_id']).first() if not user: raise serializers.ValidationError("User not found") data['user'] = user return data def create(self, validated_data): with transaction.atomic(): resources = validated_data.pop('resources') orders = [] total_price = 0 for resource in resources: orders.append(Order( product=resource['product'], unity=resource['unity'], project_folder=resource.get('project_folder'), project=resource.get('project'), counterparty=resource.get('counterparty'), wherehouse=resource.get('wherehouse'), quantity=resource.get('quantity'), unit_amount=resource.get('unit_amount'), currency=resource.get('currency'), amount=resource.get('amount'), employee=self.context.get('user'), qqs_price=resource.get('qqs_price'), total_price=resource.get('total_price'), qqs=resource.get('qqs'), )) if validated_data.get('currency') == 'uzs': if resource.get('currency') == 'usd': usd_value = UsdCourse.objects.first().value total_price += resource.get('amount') * usd_value else: total_price += resource.get('amount') created_orders = Order.objects.bulk_create(orders) party = Party.objects.create( mediator=validated_data.get('user'), delivery_date=validated_data.get('delivery_date'), payment_date=validated_data.get('payment_date'), comment=validated_data.get('comment'), audit=validated_data.get('audit'), audit_comment=validated_data.get('audit_comment'), discount=validated_data.get('discount'), discount_currency=validated_data.get('discount_currency'), currency=validated_data.get('currency'), ) party.orders.add(*created_orders) party.save() PartyAmount.objects.create( total_price=total_price, party=party, ) return party class PartyAmountSerializer(serializers.ModelSerializer): class Meta: model = PartyAmount fields = [ 'id', 'total_price', 'cost_amount', 'calculated_amount', 'paid_amount', 'payment_amount' ] class PartyDetailSerializer(serializers.ModelSerializer): orders = OrderListSerializer(many=True) party_amount = PartyAmountSerializer() mediator = serializers.SerializerMethodField(method_name='get_mediator') class Meta: model = Party fields = [ 'id', 'number', 'delivery_date', 'closed_date', 'order_date', 'payment_date', 'status', 'payment_status', 'process', 'confirmation', 'comment', 'audit', 'audit_comment', 'orders', 'party_amount', 'mediator', 'currency' ] def get_mediator(self, obj): return { 'id': obj.mediator.id, 'full_name': obj.mediator.full_name } class PartyListSerializer(serializers.ModelSerializer): party_amount = PartyAmountSerializer() mediator = serializers.SerializerMethodField(method_name='get_mediator') counterparty = serializers.SerializerMethodField(method_name='get_counterparty') class Meta: model = Party fields = [ 'id','number', 'delivery_date', 'closed_date', 'order_date', 'payment_date', 'status', 'payment_status', 'process', 'confirmation', 'comment', 'audit', 'audit_comment', 'party_amount', 'mediator', 'counterparty', 'currency' ] def get_mediator(self, obj): return { 'id': obj.mediator.id, 'full_name': obj.mediator.full_name } def get_counterparty(self, obj): counterparties = obj.orders.values("counterparty__id", "counterparty__name").distinct() counterparties = [ {"id": c["counterparty__id"], "name": c["counterparty__name"]} for c in counterparties ] return CounterpartyListPartySerializer(counterparties, many=True).data class DeletedPartyCreateSerializer(serializers.Serializer): comment = serializers.CharField(required=False) def validate(self, data): party = Party.objects.filter(id=self.context.get('party_id')).first() if not party: raise serializers.ValidationError("Party not found") data['party'] = party return data def create(self, validated_data): with transaction.atomic(): return DeletedParty.objects.create( comment=validated_data.get('comment'), party=validated_data.get('party') ) class DeletedPartyListSerializer(serializers.ModelSerializer): party_number = serializers.IntegerField(source='party.number') party_total_price = serializers.IntegerField(source='party.party_amount.total_price') mediator = serializers.SerializerMethodField(method_name='get_mediator') class Meta: model = DeletedParty fields = [ 'id', 'deleted_date', 'party_number', 'party_total_price', 'mediator' ] def get_mediator(self, obj): return { 'id': obj.party.mediator.id, 'name': obj.party.mediator.full_name } class PartyOrderUpdateSerializer(serializers.Serializer): order_id = serializers.UUIDField() product_id = serializers.UUIDField() unity_id = serializers.UUIDField() project_folder_id = serializers.UUIDField(required=False) project_id = serializers.UUIDField(required=False) wherehouse_id = serializers.UUIDField() counterparty_id = serializers.UUIDField() quantity = serializers.IntegerField() unit_amount = serializers.IntegerField() currency = serializers.ChoiceField(choices=[('uzs', 'uzs'), ('usd', 'usd')]) total_price = serializers.IntegerField() def validate(self, data): order = Order.objects.filter(id=data['order_id']).first() if not order: raise serializers.ValidationError("Order not found") product = Product.objects.filter(id=data['product_id']).first() if not product: raise serializers.ValidationError(f"Product not found on {order.id}") unity = Unity.objects.filter(id=data['unity_id']).first() if not unity: raise serializers.ValidationError(f"Unity not found on {order.id}") if data.get('project_folder_id'): project_folder = ProjectFolder.objects.filter(id=data['project_folder_id']).first() if not project_folder: raise serializers.ValidationError(f"Project Folder not found on {order.id}") 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(f"Project not found on {order.id}") data['project'] = project wherehouse = WhereHouse.objects.filter(id=data['wherehouse_id']).first() if not wherehouse: raise serializers.ValidationError(f"WhereHouse not found on {order.id}") counterparty = Counterparty.objects.filter(id=data['counterparty_id']).first() if not counterparty: raise serializers.ValidationError(f"Counterparty not found on {order.id}") data['order'] = order data['product'] = product data['unity'] = unity data['wherehouse'] = wherehouse data['counterparty'] = counterparty return data class PartyUpdateSerializer(serializers.ModelSerializer): orders = PartyOrderUpdateSerializer(many=True, required=False) class Meta: model = Party fields = [ 'mediator', 'delivery_date', 'payment_date', 'orders', 'comment', 'audit', 'audit_comment', 'discount', 'discount_currency', ] extra_kwargs = { 'mediator': {'required': False}, 'delivery_date': {'required': False}, 'payment_date': {'required':False}, 'comment': {'required': False}, 'audit': {'required': False}, 'audit_comment': {'required': False}, 'discount': {'required': False}, 'discount_currency': {'required': False}, } def update(self, instance, validated_data): orders_data = validated_data.pop('orders') update_orders = [] with transaction.atomic(): instance.mediator = validated_data.get('mediator', instance.mediator) instance.delivery_date = validated_data.get('delivery_date', instance.delivery_date) instance.payment_date = validated_data.get('payment_date', instance.payment_date) instance.save() for order_data in orders_data: order = order_data['order'] order.product = order_data['product'] order.unity = order_data['unity'] order.wherehouse = order_data['wherehouse'] order.counterparty = order_data['counterparty'] order.quantity = order_data['quantity'] order.currency = order_data['currency'] order.unit_amount = order_data['unit_amount'] order.total_price = order_data['total_price'] if 'project_folder' in order_data: order.project_folder = order_data['project_folder'] if 'project' in order_data: order.project = order_data['project'] update_orders.append(order) Order.objects.bulk_update( update_orders, fields=[ 'product', 'unity', 'wherehouse', 'counterparty', 'quantity', 'unit_amount', 'currency', 'total_price', 'project_folder', 'project' ] ) return instance