# Generated by Django 6.0 on 2026-02-23 16:12

import django.core.validators
import django.db.models.deletion
import django.utils.timezone
from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
        ('academics', '0001_initial'),
        ('people', '0001_initial'),
    ]

    operations = [
        migrations.CreateModel(
            name='FeeCategory',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=100)),
                ('description', models.TextField(blank=True, null=True)),
                ('is_active', models.BooleanField(default=True)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
            ],
            options={
                'verbose_name_plural': 'Fee Categories',
                'ordering': ['name'],
            },
        ),
        migrations.CreateModel(
            name='FeeComponent',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=100)),
                ('code', models.CharField(max_length=30, unique=True)),
                ('description', models.TextField(blank=True, null=True)),
                ('calculation_type', models.CharField(choices=[('fixed', 'Fixed Amount'), ('per_term', 'Per Term'), ('monthly', 'Monthly'), ('yearly', 'Yearly')], default='fixed', max_length=20)),
                ('is_mandatory', models.BooleanField(default=True)),
                ('is_recurring', models.BooleanField(default=True)),
                ('late_fee_applicable', models.BooleanField(default=False)),
                ('late_fee_type', models.CharField(blank=True, choices=[('fixed', 'Fixed Amount'), ('percentage', 'Percentage of Fee')], max_length=20, null=True)),
                ('late_fee_value', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, validators=[django.core.validators.MinValueValidator(0)])),
                ('grace_days', models.IntegerField(default=0, validators=[django.core.validators.MinValueValidator(0)])),
                ('is_active', models.BooleanField(default=True)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('category', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='fee_components', to='fee.feecategory')),
            ],
            options={
                'ordering': ['category', 'name'],
            },
        ),
        migrations.CreateModel(
            name='ClassFeeStructure',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('amount', models.DecimalField(decimal_places=2, max_digits=10, validators=[django.core.validators.MinValueValidator(0)])),
                ('due_date', models.DateField()),
                ('late_fee_applicable', models.BooleanField(default=False)),
                ('notes', models.TextField(blank=True, null=True)),
                ('is_active', models.BooleanField(default=True)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('academic_class', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='fee_structures', to='academics.academicclass')),
                ('academic_term', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='fee_structures', to='academics.academicterm')),
                ('fee_component', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='class_fee_structures', to='fee.feecomponent')),
            ],
            options={
                'ordering': ['academic_class', 'fee_component'],
                'unique_together': {('academic_class', 'fee_component', 'academic_term')},
            },
        ),
        migrations.CreateModel(
            name='OutstandingBalance',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('total_fees', models.DecimalField(decimal_places=2, default=0, max_digits=10, validators=[django.core.validators.MinValueValidator(0)])),
                ('total_paid', models.DecimalField(decimal_places=2, default=0, max_digits=10, validators=[django.core.validators.MinValueValidator(0)])),
                ('balance_due', models.DecimalField(decimal_places=2, default=0, max_digits=10, validators=[django.core.validators.MinValueValidator(0)])),
                ('overdue_amount', models.DecimalField(decimal_places=2, default=0, max_digits=10, validators=[django.core.validators.MinValueValidator(0)])),
                ('days_overdue', models.IntegerField(default=0)),
                ('total_late_fees', models.DecimalField(decimal_places=2, default=0, max_digits=10, validators=[django.core.validators.MinValueValidator(0)])),
                ('last_calculated', models.DateTimeField(auto_now=True)),
                ('student_enrollment', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='outstanding_balance', to='academics.studentenrollment')),
            ],
            options={
                'ordering': ['-balance_due'],
            },
        ),
        migrations.CreateModel(
            name='StudentFeeAssignment',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('discount_type', models.CharField(blank=True, choices=[('percentage', 'Percentage Discount'), ('amount', 'Fixed Amount Discount'), ('waiver', 'Full Waiver')], max_length=20, null=True)),
                ('discount_value', models.DecimalField(blank=True, decimal_places=2, help_text='Percentage or amount based on discount_type', max_digits=10, null=True, validators=[django.core.validators.MinValueValidator(0)])),
                ('due_date_override', models.DateField(blank=True, null=True)),
                ('reason', models.TextField(blank=True, null=True)),
                ('is_active', models.BooleanField(default=True)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('class_fee_structure', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='student_assignments', to='fee.classfeestructure')),
                ('enrollment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='fee_assignments', to='academics.studentenrollment')),
                ('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='fee_assignments', to='people.student')),
            ],
            options={
                'ordering': ['student', 'class_fee_structure'],
                'unique_together': {('enrollment', 'class_fee_structure')},
            },
        ),
        migrations.CreateModel(
            name='FeePayment',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('receipt_number', models.CharField(max_length=50, unique=True)),
                ('amount_paid', models.DecimalField(decimal_places=2, max_digits=10, validators=[django.core.validators.MinValueValidator(0)])),
                ('payment_date', models.DateField(default=django.utils.timezone.now)),
                ('payment_method', models.CharField(choices=[('cash', 'Cash'), ('bank_transfer', 'Bank Transfer'), ('cheque', 'Cheque'), ('credit_card', 'Credit Card'), ('debit_card', 'Debit Card'), ('mobile_money', 'Mobile Money'), ('online', 'Online Payment'), ('other', 'Other')], default='cash', max_length=20)),
                ('status', models.CharField(choices=[('pending', 'Pending'), ('completed', 'Completed'), ('failed', 'Failed'), ('refunded', 'Refunded'), ('cancelled', 'Cancelled'), ('bounced', 'Bounced')], default='pending', max_length=20)),
                ('transaction_reference', models.CharField(blank=True, help_text='External transaction ID/reference', max_length=100, null=True)),
                ('cheque_number', models.CharField(blank=True, help_text='Cheque number if payment method is cheque', max_length=50, null=True)),
                ('bank_name', models.CharField(blank=True, help_text='Bank name for cheque/bank transfer', max_length=100, null=True)),
                ('principal_amount', models.DecimalField(decimal_places=2, help_text='Amount towards actual fees', max_digits=10, validators=[django.core.validators.MinValueValidator(0)])),
                ('late_fee_amount', models.DecimalField(decimal_places=2, default=0, help_text='Late payment penalty charged', max_digits=10, validators=[django.core.validators.MinValueValidator(0)])),
                ('balance_before', models.DecimalField(decimal_places=2, help_text='Balance before this payment', max_digits=10, validators=[django.core.validators.MinValueValidator(0)])),
                ('balance_after', models.DecimalField(decimal_places=2, help_text='Balance after this payment', max_digits=10, validators=[django.core.validators.MinValueValidator(0)])),
                ('is_bounced', models.BooleanField(default=False)),
                ('bounce_date', models.DateField(blank=True, null=True)),
                ('bounce_reason', models.TextField(blank=True, null=True)),
                ('bounce_charge_amount', models.DecimalField(decimal_places=2, default=0, help_text='Bank charges for bounced cheque', max_digits=10, validators=[django.core.validators.MinValueValidator(0)])),
                ('bounce_charge_paid', models.BooleanField(default=False)),
                ('bounce_charge_paid_date', models.DateField(blank=True, null=True)),
                ('eft_reference', models.CharField(blank=True, help_text='EFT reference number', max_length=100, null=True)),
                ('eft_initiation_date', models.DateField(blank=True, null=True)),
                ('eft_settlement_date', models.DateField(blank=True, null=True)),
                ('eft_bank_name', models.CharField(blank=True, help_text='Bank name for EFT', max_length=100, null=True)),
                ('eft_account_number', models.CharField(blank=True, help_text='Last 4 digits of account number for reference', max_length=50, null=True)),
                ('notes', models.TextField(blank=True, null=True)),
                ('recorded_by_name', models.CharField(blank=True, help_text='Name of person who recorded the payment', max_length=100, null=True)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='fee_payments', to='people.student')),
                ('student_enrollment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='fee_payments', to='academics.studentenrollment')),
                ('fee_assignments', models.ManyToManyField(blank=True, help_text='Specific fee assignments this payment covers', related_name='payments', to='fee.studentfeeassignment')),
            ],
            options={
                'ordering': ['-payment_date', '-created_at'],
            },
        ),
        migrations.CreateModel(
            name='PaymentAllocation',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('amount_allocated', models.DecimalField(decimal_places=2, max_digits=10, validators=[django.core.validators.MinValueValidator(0)])),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('academic_term', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='payment_allocations', to='academics.academicterm')),
                ('payment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='allocations', to='fee.feepayment')),
                ('fee_assignment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='payment_allocations', to='fee.studentfeeassignment')),
            ],
            options={
                'ordering': ['payment', '-created_at'],
                'unique_together': {('payment', 'fee_assignment')},
            },
        ),
        migrations.AddIndex(
            model_name='feepayment',
            index=models.Index(fields=['receipt_number'], name='fee_feepaym_receipt_8ffc7d_idx'),
        ),
        migrations.AddIndex(
            model_name='feepayment',
            index=models.Index(fields=['student_enrollment', 'status'], name='fee_feepaym_student_2854d2_idx'),
        ),
        migrations.AddIndex(
            model_name='feepayment',
            index=models.Index(fields=['payment_date'], name='fee_feepaym_payment_a6894b_idx'),
        ),
        migrations.AddIndex(
            model_name='feepayment',
            index=models.Index(fields=['is_bounced'], name='fee_feepaym_is_boun_c249ac_idx'),
        ),
    ]
