2025-08-12 13:33:25 +03:00

210 lines
8.3 KiB
Python

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