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.herd.pos.api.v1.serializers import RancherSerializer from apps.warehouse import models as warehouse_models 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'] # 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, **item_data ) total_price += item.total_price transaction.transaction_price = total_price transaction.save() return transaction def validate(self, attrs): """ validate total inventory sale should be fewer than inventory entry from distribution """ if 'quota_distribution' in attrs.keys(): distribution = attrs['quota_distribution'] total_sale_weight = distribution.inventory_sales.aggregate( total=models.Sum('weight') )['total'] or 0 if total_sale_weight + attrs['weight'] > distribution.warehouse_balance: raise TotalInventorySaleException() 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", ]