""" DRF Serializers for Finance app. """ from rest_framework import serializers from .models import Invoice, InvoiceLineItem, Payment, Service, Package, PackagePurchase, Payer from core.serializers import PatientListSerializer class ServiceSerializer(serializers.ModelSerializer): """Serializer for Service model.""" clinic_name = serializers.CharField(source='clinic.name_en', read_only=True) class Meta: model = Service fields = [ 'id', 'code', 'name_en', 'name_ar', 'clinic', 'clinic_name', 'base_price', 'duration_minutes', 'is_active' ] read_only_fields = ['id'] class PackageSerializer(serializers.ModelSerializer): """Serializer for Package model.""" services_display = serializers.SerializerMethodField() class Meta: model = Package fields = [ 'id', 'name_en', 'name_ar', 'services', 'services_display', 'total_sessions', 'price', 'validity_days', 'is_active' ] read_only_fields = ['id'] def get_services_display(self, obj): """Return list of service names.""" return [service.name_en for service in obj.services.all()] class PayerSerializer(serializers.ModelSerializer): """Serializer for Payer model.""" patient_name = serializers.CharField(source='patient.get_full_name', read_only=True) type_display = serializers.CharField(source='get_type_display', read_only=True) class Meta: model = Payer fields = [ 'id', 'patient', 'patient_name', 'name', 'type', 'type_display', 'policy_number', 'coverage_percentage', 'is_active' ] read_only_fields = ['id'] class InvoiceLineItemSerializer(serializers.ModelSerializer): """Serializer for InvoiceLineItem model.""" service_name = serializers.CharField(source='service.name_en', read_only=True) package_name = serializers.CharField(source='package.name_en', read_only=True) class Meta: model = InvoiceLineItem fields = [ 'id', 'service', 'service_name', 'package', 'package_name', 'description', 'quantity', 'unit_price', 'total' ] read_only_fields = ['id', 'total'] def validate(self, data): """Calculate total.""" quantity = data.get('quantity', 1) unit_price = data.get('unit_price', 0) data['total'] = quantity * unit_price return data class InvoiceListSerializer(serializers.ModelSerializer): """Lightweight serializer for invoice lists.""" patient_name = serializers.CharField(source='patient.get_full_name', read_only=True) status_display = serializers.CharField(source='get_status_display', read_only=True) class Meta: model = Invoice fields = [ 'id', 'invoice_number', 'patient', 'patient_name', 'issue_date', 'due_date', 'total', 'status', 'status_display' ] read_only_fields = ['id', 'invoice_number'] class InvoiceDetailSerializer(serializers.ModelSerializer): """Detailed serializer for invoice detail views.""" patient = PatientListSerializer(read_only=True) line_items = InvoiceLineItemSerializer(many=True, read_only=True) status_display = serializers.CharField(source='get_status_display', read_only=True) amount_paid = serializers.SerializerMethodField() amount_due = serializers.SerializerMethodField() class Meta: model = Invoice fields = [ 'id', 'invoice_number', 'patient', 'appointment', 'issue_date', 'due_date', 'subtotal', 'tax', 'discount', 'total', 'status', 'status_display', 'amount_paid', 'amount_due', 'line_items', 'notes', 'created_at', 'updated_at' ] read_only_fields = ['id', 'invoice_number', 'created_at', 'updated_at'] def get_amount_paid(self, obj): """Calculate total amount paid.""" return sum(payment.amount for payment in obj.payments.filter(status='COMPLETED')) def get_amount_due(self, obj): """Calculate amount due.""" amount_paid = self.get_amount_paid(obj) return obj.total - amount_paid class InvoiceCreateSerializer(serializers.ModelSerializer): """Serializer for creating invoices.""" line_items = InvoiceLineItemSerializer(many=True) class Meta: model = Invoice fields = [ 'patient', 'appointment', 'issue_date', 'due_date', 'subtotal', 'tax', 'discount', 'notes', 'line_items' ] def create(self, validated_data): """Create invoice with line items.""" line_items_data = validated_data.pop('line_items') # Calculate total subtotal = validated_data.get('subtotal', 0) tax = validated_data.get('tax', 0) discount = validated_data.get('discount', 0) total = subtotal + tax - discount validated_data['total'] = total validated_data['status'] = 'DRAFT' invoice = Invoice.objects.create(**validated_data) # Create line items for item_data in line_items_data: InvoiceLineItem.objects.create(invoice=invoice, **item_data) return invoice class PaymentSerializer(serializers.ModelSerializer): """Serializer for Payment model.""" invoice_number = serializers.CharField(source='invoice.invoice_number', read_only=True) patient_name = serializers.CharField(source='invoice.patient.get_full_name', read_only=True) method_display = serializers.CharField(source='get_method_display', read_only=True) status_display = serializers.CharField(source='get_status_display', read_only=True) processed_by_name = serializers.CharField(source='processed_by.get_full_name', read_only=True) class Meta: model = Payment fields = [ 'id', 'invoice', 'invoice_number', 'patient_name', 'payment_date', 'amount', 'method', 'method_display', 'transaction_id', 'reference', 'status', 'status_display', 'processed_by', 'processed_by_name', 'created_at' ] read_only_fields = ['id', 'created_at'] class PackagePurchaseSerializer(serializers.ModelSerializer): """Serializer for PackagePurchase model.""" patient_name = serializers.CharField(source='patient.get_full_name', read_only=True) package_name = serializers.CharField(source='package.name_en', read_only=True) invoice_number = serializers.CharField(source='invoice.invoice_number', read_only=True) class Meta: model = PackagePurchase fields = [ 'id', 'patient', 'patient_name', 'package', 'package_name', 'invoice', 'invoice_number', 'purchase_date', 'expiry_date', 'total_sessions', 'used_sessions', 'remaining_sessions', 'is_active' ] read_only_fields = ['id', 'remaining_sessions']