Files
ibapp-backend/core/apps/orders/serializers/party.py
2025-11-01 08:45:57 +05:00

515 lines
20 KiB
Python

from django.db import transaction
from rest_framework import serializers
from core.apps.accounts.models import User
from core.apps.counterparty.models import Counterparty
from core.apps.counterparty.serializers.counterparty import CounterpartySerializer
from core.apps.finance.models import Expence
from core.apps.orders.models import DeletedParty, Order, Party, PartyAmount
from core.apps.orders.serializers.order import (
MultipleOrderAddSerializer,
OrderListSerializer,
)
from core.apps.orders.tasks.order import create_inventory
from core.apps.products.models import Product, Unity
from core.apps.projects.models import Project, ProjectFolder
from core.apps.shared.models import UsdCourse
from core.apps.wherehouse.models import WhereHouse
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"),
type="party"
)
)
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,
payment_amount=total_price - validated_data.get("discount", 0),
cost_amount=total_price - validated_data.get("discount", 0),
)
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")
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",
"payment_percentage",
"process",
"confirmation",
"comment",
"audit",
"audit_comment",
"orders",
"party_amount",
"mediator",
"currency",
"counterparty",
"discount",
]
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 CounterpartySerializer(counterparties, many=True).data
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",
"payment_percentage",
"process",
"confirmation",
"comment",
"audit",
"audit_comment",
"party_amount",
"mediator",
"counterparty",
"currency",
"discount",
]
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 CounterpartySerializer(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):
total_price = 0
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"]
total_price += order.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",
],
)
party_amount = PartyAmount.objects.get(party=instance)
party_amount.total_price = total_price
party_amount.cost_amount = (
total_price - instance.discount if instance.discount else 0
)
party_amount.payment_amount = (
total_price - instance.discount if instance.discount else 0
)
party_amount.save()
return instance
class PartyExpenceCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Expence
fields = [
"cash_transaction",
"payment_type",
"project_folder",
"project",
"counterparty",
"price",
"exchange_rate",
"currency",
"date",
"comment",
"party",
]
def validate(self, data):
price = data.get('price')
exchange_rate = data.get('exchange_rate')
party = data.get('party')
currency = data.get('currency', 'uzs').lower()
if price and price < 0:
raise serializers.ValidationError("Narxi manfiy bo'lishi mumkin emas")
if exchange_rate and exchange_rate < 0:
raise serializers.ValidationError("Kurs manfiy bo'lishi mumkin emas")
if not party:
raise serializers.ValidationError("Party talab qilinadi")
try:
usd_course = UsdCourse.objects.first()
if not usd_course or not usd_course.value:
raise serializers.ValidationError("USD kursi topilmadi")
except UsdCourse.DoesNotExist:
raise serializers.ValidationError("USD kursi topilmadi")
return data
def create(self, validated_data):
with transaction.atomic():
usd_course = UsdCourse.objects.first()
if not usd_course:
raise serializers.ValidationError("USD kursi topilmadi")
usd_value = usd_course.value
exchange_rate = validated_data.get("exchange_rate") or 1
final_price = validated_data.get("price")
currency = validated_data.get("currency", "uzs").lower()
expence = Expence.objects.create(
cash_transaction=validated_data.get("cash_transaction"),
payment_type=validated_data.get("payment_type"),
project_folder=validated_data.get("project_folder"),
project=validated_data.get("project"),
counterparty=validated_data.get("counterparty"),
price=final_price,
exchange_rate=exchange_rate,
currency=currency,
date=validated_data.get("date"),
comment=validated_data.get("comment"),
party=validated_data.get("party"),
user=self.context.get('user'),
)
cash_transaction = expence.cash_transaction
payment_type = expence.payment_type
party = expence.party
if currency == "uzs":
cash_transaction.expence_balance_uzs += expence.price
cash_transaction.total_balance_uzs = (
cash_transaction.income_balance_uzs
- cash_transaction.expence_balance_uzs
)
if payment_type.total_uzs > expence.price:
payment_type.total_uzs -= expence.price
if expence.counterparty:
if expence.counterparty.kredit_uzs > 0:
expence.counterparty.kredit_uzs -= expence.price
expence.counterparty.total_kredit -= expence.price
expence.counterparty.debit_uzs += expence.price
expence.counterparty.total_debit += expence.price
else:
expence.counterparty.debit_uzs += expence.price
expence.counterparty.total_debit += expence.price
expence.counterparty.save()
if party:
if party.currency == "uzs":
party.party_amount.payment_amount -= expence.price
party.party_amount.paid_amount += expence.price
party.party_amount.save()
elif party.currency == 'usd':
converted_price = round(expence.price / usd_value)
party.party_amount.payment_amount -= converted_price
party.party_amount.paid_amount += converted_price
party.party_amount.save()
party.save()
elif currency == "usd":
cash_transaction.expence_balance_usd += expence.price
cash_transaction.total_balance_usd = (
cash_transaction.income_balance_usd
- cash_transaction.expence_balance_usd
)
if payment_type.total_usd > expence.price:
payment_type.total_usd -= expence.price
if expence.counterparty:
if expence.counterparty.kredit_usd > 0:
expence.counterparty.kredit_usd -= expence.price
expence.counterparty.total_kredit -= expence.price
expence.counterparty.debit_usd += expence.price
expence.counterparty.total_debit += expence.price
else:
expence.counterparty.debit_usd += expence.price
expence.counterparty.total_debit += expence.price
expence.counterparty.save()
if party:
if party.currency == "usd":
party.party_amount.payment_amount -= expence.price
party.party_amount.paid_amount += expence.price
party.party_amount.save()
elif party.currency == "uzs":
converted_price = expence.price * usd_value
party.party_amount.payment_amount -= converted_price
party.party_amount.paid_amount += converted_price
party.party_amount.save()
party.save()
cash_transaction.save()
payment_type.save()
return expence