from rest_framework import serializers from ..models import ( InventoryItem, InventoryStock, InventoryLocation, PurchaseOrder, PurchaseOrderItem, Supplier ) class BaseSerializer(serializers.ModelSerializer): """Base serializer with common functionality""" class Meta: fields = ['id'] read_only_fields = ['created_at', 'updated_at'] class SupplierSerializer(serializers.ModelSerializer): """Serializer for Supplier model""" class Meta: model = Supplier fields = [ 'supplier_id', 'name', 'contact_person', 'email', 'phone', 'address', 'city', 'state', 'zip_code', 'country', 'tax_id', 'payment_terms', 'credit_limit', 'is_active', 'created_at', 'updated_at' ] read_only_fields = ['supplier_id', 'created_at', 'updated_at'] class InventoryLocationSerializer(serializers.ModelSerializer): """Serializer for InventoryLocation model""" class Meta: model = InventoryLocation fields = [ 'location_id', 'name', 'description', 'location_type', 'building', 'floor', 'room', 'zone', 'capacity', 'temperature_controlled', 'security_level', 'is_active', 'created_at', 'updated_at' ] read_only_fields = ['location_id', 'created_at', 'updated_at'] class InventoryItemSerializer(serializers.ModelSerializer): """Serializer for InventoryItem model""" category_display = serializers.CharField(source='get_category_display', read_only=True) unit_display = serializers.CharField(source='get_unit_display', read_only=True) class Meta: model = InventoryItem fields = [ 'item_id', 'name', 'description', 'category', 'category_display', 'sku', 'barcode', 'manufacturer', 'model_number', 'unit', 'unit_display', 'unit_cost', 'reorder_level', 'reorder_quantity', 'max_stock_level', 'is_active', 'requires_expiry_tracking', 'requires_lot_tracking', 'is_controlled_substance', 'storage_requirements', 'created_at', 'updated_at' ] read_only_fields = ['item_id', 'created_at', 'updated_at'] class InventoryStockSerializer(serializers.ModelSerializer): """Serializer for InventoryStock model""" item_name = serializers.CharField(source='item.name', read_only=True) location_name = serializers.CharField(source='location.name', read_only=True) is_low_stock = serializers.BooleanField(read_only=True) is_expired = serializers.BooleanField(read_only=True) days_until_expiry = serializers.IntegerField(read_only=True) class Meta: model = InventoryStock fields = [ 'stock_id', 'item', 'item_name', 'location', 'location_name', 'quantity_on_hand', 'quantity_allocated', 'quantity_available', 'lot_number', 'expiration_date', 'unit_cost', 'total_cost', 'last_counted', 'is_low_stock', 'is_expired', 'days_until_expiry', 'created_at', 'updated_at' ] read_only_fields = [ 'stock_id', 'quantity_available', 'total_cost', 'is_low_stock', 'is_expired', 'days_until_expiry', 'created_at', 'updated_at' ] class PurchaseOrderSerializer(serializers.ModelSerializer): """Serializer for PurchaseOrder model""" supplier_name = serializers.CharField(source='supplier.name', read_only=True) status_display = serializers.CharField(source='get_status_display', read_only=True) created_by_name = serializers.CharField(source='created_by.get_full_name', read_only=True) class Meta: model = PurchaseOrder fields = [ 'order_id', 'order_number', 'supplier', 'supplier_name', 'order_date', 'expected_delivery_date', 'actual_delivery_date', 'status', 'status_display', 'total_amount', 'tax_amount', 'shipping_cost', 'grand_total', 'notes', 'created_by', 'created_by_name', 'created_at', 'updated_at' ] read_only_fields = [ 'order_id', 'order_number', 'total_amount', 'grand_total', 'created_at', 'updated_at' ] class PurchaseOrderItemSerializer(serializers.ModelSerializer): """Serializer for PurchaseOrderItem model""" item_name = serializers.CharField(source='item.name', read_only=True) item_sku = serializers.CharField(source='item.sku', read_only=True) line_total = serializers.DecimalField(max_digits=12, decimal_places=2, read_only=True) class Meta: model = PurchaseOrderItem fields = [ 'item_id', 'purchase_order', 'item', 'item_name', 'item_sku', 'quantity_ordered', 'quantity_received', 'unit_cost', 'line_total', 'notes', 'created_at', 'updated_at' ] read_only_fields = ['item_id', 'line_total', 'created_at', 'updated_at'] class InventoryStatsSerializer(serializers.Serializer): """Serializer for inventory statistics""" total_items = serializers.IntegerField() low_stock_items = serializers.IntegerField() expired_items = serializers.IntegerField() expiring_soon = serializers.IntegerField() total_value = serializers.DecimalField(max_digits=15, decimal_places=2) pending_orders = serializers.IntegerField() received_today = serializers.IntegerField() category_breakdown = serializers.DictField() location_utilization = serializers.DictField() class StockAdjustmentSerializer(serializers.Serializer): """Serializer for stock adjustments""" stock_id = serializers.IntegerField() adjustment_type = serializers.ChoiceField(choices=['ADD', 'SUBTRACT', 'SET']) quantity = serializers.IntegerField() reason = serializers.CharField() notes = serializers.CharField(required=False, allow_blank=True) def validate_quantity(self, value): """Validate adjustment quantity""" if value <= 0: raise serializers.ValidationError("Quantity must be greater than 0.") return value class StockTransferSerializer(serializers.Serializer): """Serializer for stock transfers""" from_stock_id = serializers.IntegerField() to_location_id = serializers.IntegerField() quantity = serializers.IntegerField() reason = serializers.CharField() notes = serializers.CharField(required=False, allow_blank=True) def validate_quantity(self, value): """Validate transfer quantity""" if value <= 0: raise serializers.ValidationError("Quantity must be greater than 0.") return value class PurchaseOrderCreateSerializer(serializers.Serializer): """Serializer for creating purchase orders""" supplier_id = serializers.IntegerField() expected_delivery_date = serializers.DateField() items = serializers.ListField( child=serializers.DictField(), min_length=1 ) notes = serializers.CharField(required=False, allow_blank=True) def validate_items(self, value): """Validate purchase order items""" for item in value: if 'item_id' not in item or 'quantity' not in item or 'unit_cost' not in item: raise serializers.ValidationError( "Each item must have item_id, quantity, and unit_cost." ) if item['quantity'] <= 0: raise serializers.ValidationError("Item quantity must be greater than 0.") if item['unit_cost'] < 0: raise serializers.ValidationError("Unit cost cannot be negative.") return value class ReceiveOrderSerializer(serializers.Serializer): """Serializer for receiving purchase orders""" order_id = serializers.IntegerField() items = serializers.ListField( child=serializers.DictField(), min_length=1 ) notes = serializers.CharField(required=False, allow_blank=True) def validate_items(self, value): """Validate received items""" for item in value: if 'item_id' not in item or 'quantity_received' not in item: raise serializers.ValidationError( "Each item must have item_id and quantity_received." ) if item['quantity_received'] < 0: raise serializers.ValidationError("Quantity received cannot be negative.") return value