Files
RasadDam_Backend/apps/warehouse/pos/api/v1/serializers.py
2025-09-20 16:58:24 +03:30

211 lines
7.8 KiB
Python

from apps.herd.services.services import get_rancher_statistics, rancher_quota_weight
from apps.product.services.services import (
quota_live_stock_allocation_info,
quota_incentive_plans_info,
quota_brokers_value,
quota_attribute_value
)
from apps.pos_device.services.services import pos_organizations_sharing_information
from apps.pos_device.pos.api.v1.serializers.device import DeviceSerializer
from apps.product.exceptions import DistributionWeightException
from apps.warehouse.services.services import create_extra_sale
from apps.herd.pos.api.v1.serializers import RancherSerializer
from apps.product.models import QuotaDistribution, Product
from apps.warehouse import models as warehouse_models
from apps.core.models import SystemConfig
from django.db.transaction import atomic
from apps.warehouse.exceptions import (
TotalInventorySaleException
)
from rest_framework import serializers
from apps.herd.models import Rancher
from django.db import models
class InventoryEntrySerializer(serializers.ModelSerializer):
class Meta:
model = warehouse_models.InventoryEntry
fields = [
"id",
"entry_identity",
"create_date",
"modify_date",
"organization",
"distribution",
"weight",
"balance",
"lading_number",
"delivery_address",
"is_confirmed",
"notes",
]
def to_representation(self, instance):
""" custom output of inventory entry serializer """
representation = super().to_representation(instance)
if instance.document:
representation['document'] = instance.document
if instance.distribution:
# distribution data
representation['distribution'] = {
'distribution_identity': instance.distribution.distribution_id,
'sale_unit': instance.distribution.quota.sale_unit.unit,
'id': instance.distribution.id
}
representation['quota'] = {
'quota_identity': instance.distribution.quota.quota_id,
'quota_weight': instance.distribution.quota.quota_weight,
'quota_livestock_allocations': quota_live_stock_allocation_info(
instance.distribution.quota
),
'quota_incentive_plans': quota_incentive_plans_info(instance.distribution.quota)
}
representation['product'] = {
'image': instance.distribution.quota.product.img,
'name': instance.distribution.quota.product.name,
'id': instance.distribution.quota.product.id,
}
representation['pricing'] = {
'pricing_attributes': quota_attribute_value(instance.distribution.quota),
'sharing': pos_organizations_sharing_information(
self.context['device'],
instance.distribution.quota,
instance.distribution
),
'base_prices': [
{
"text": "قیمت درب کارخانه", # noqa
"name": "base_price_factory",
"value": instance.distribution.quota.base_price_factory
},
{
"text": "قیمت درب اتحادیه", # noqa
"name": "base_price_cooperative",
"value": instance.distribution.quota.base_price_cooperative
}
]
}
if 'rancher' in self.context.keys():
# rancher herd & live stock statistics
representation['rancher_statistics'] = get_rancher_statistics(self.context['rancher'])
# rancher live stock statistics by inventory entry
representation['rancher_quota_weight_statistics'] = rancher_quota_weight(
self.context['rancher'], instance
)
return representation
class InventoryQuotaSaleTransactionSerializer(serializers.ModelSerializer):
rancher_national_code = serializers.CharField(max_length=50, required=False)
class Meta: # noqa
model = warehouse_models.InventoryQuotaSaleTransaction
fields = '__all__'
depth = 0
def create(self, validated_data):
items_data = self.context['request'].data['items']
with atomic():
# get rancher with national code
rancher = Rancher.objects.get(national_code=validated_data.pop('rancher_national_code'))
validated_data.update({'rancher': rancher})
# if transaction exists, update transaction status
transaction = self.Meta.model.objects.filter(
transaction_id=validated_data.get('transaction_id')
)
if transaction.exists():
obj = transaction.first()
obj.transaction_status = validated_data.get('transaction_status')
obj.save(update_fields=['transaction_status'])
return obj
# create transaction record
transaction = warehouse_models.InventoryQuotaSaleTransaction.objects.create(
**validated_data
)
# calculate total price of product items in shopping cart
total_price = 0
for item_data in items_data:
item = warehouse_models.InventoryQuotaSaleItem.objects.create(
transaction=transaction,
quota_distribution=QuotaDistribution.objects.get(
id=item_data.pop('quota_distribution')
),
product=Product.objects.get(
id=item_data.pop('product')
),
**item_data
)
total_price += item.total_price
# create extra sale
create_extra_sale(transaction=transaction, sale_item=item)
transaction.transaction_price = total_price
transaction.save()
return transaction
def validate(self, attrs):
"""
validate total inventory sale should be fewer than
distribution weight
"""
items = self.context['request'].data['items']
for item in items:
if 'quota_distribution' in item.keys():
distribution = QuotaDistribution.objects.get(id=item.get('quota_distribution'))
total_sale_weight = distribution.sale_items.aggregate(
total=models.Sum('weight')
)['total'] or 0
if total_sale_weight + attrs['weight'] > distribution.weight:
raise DistributionWeightException()
return attrs
def to_representation(self, instance):
""" customize output of transactions serializer """
representation = super().to_representation(instance)
if instance.rancher:
representation['rancher'] = RancherSerializer(instance.rancher).data
representation['pos_device'] = DeviceSerializer(instance.pos_device).data
if instance.seller_organization:
representation['seller_organization'] = instance.seller_organization.name
return representation
class InventoryQuotaSaleItemSerializer(serializers.ModelSerializer):
product_name = serializers.CharField(source='product.name', read_only=True)
class Meta:
model = warehouse_models.InventoryQuotaSaleItem
fields = [
'id',
"transaction",
"product",
"product_name",
"weight",
"unit_price",
"total_price",
]
class QuotaPreSaleItemSerializer(serializers.ModelSerializer):
class Meta:
model = warehouse_models.QuotaPreSaleItem
fields = '__all__'