# Generated by Django 6.0.6 on 2026-07-13 23:40 import django.core.validators import django.db.models.deletion import django.utils.timezone import uuid from decimal import Decimal from django.conf import settings from django.db import migrations, models class Migration(migrations.Migration): initial = True dependencies = [ ('club', '0013_club_created_club_modified_clubmembership_created_and_more'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( name='Tier', fields=[ ('created', models.DateTimeField(auto_now_add=True, verbose_name='created')), ('modified', models.DateTimeField(auto_now=True, verbose_name='modified')), ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('name', models.CharField(max_length=255, verbose_name='name')), ('slug', models.SlugField(blank=True, max_length=255, unique=True, verbose_name='slug')), ('description', models.TextField(blank=True, verbose_name='description')), ('is_active', models.BooleanField(default=True, help_text='Inactive tiers keep billing existing subscriptions but cannot be chosen for new ones.', verbose_name='active')), ], options={ 'verbose_name': 'tier', 'verbose_name_plural': 'tiers', 'ordering': ['name'], }, ), migrations.CreateModel( name='Due', fields=[ ('created', models.DateTimeField(auto_now_add=True, verbose_name='created')), ('modified', models.DateTimeField(auto_now=True, verbose_name='modified')), ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('amount', models.DecimalField(decimal_places=2, max_digits=10, validators=[django.core.validators.MinValueValidator(Decimal('0.00'))], verbose_name='amount')), ('amount_paid', models.DecimalField(decimal_places=2, default=Decimal('0.00'), help_text='Kept in step with the payments by the billing service.', max_digits=10, verbose_name='amount paid')), ('period_start', models.DateField(verbose_name='period start')), ('period_end', models.DateField(blank=True, verbose_name='period end')), ('grace_until', models.DateField(blank=True, help_text='Past this date an unpaid club is archived.', verbose_name='grace until')), ('status', models.CharField(choices=[('unpaid', 'unpaid'), ('partial', 'partially paid'), ('paid', 'paid'), ('waived', 'waived'), ('cancelled', 'cancelled')], default='unpaid', max_length=20, verbose_name='status')), ('paid_at', models.DateTimeField(blank=True, null=True, verbose_name='paid at')), ('club', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='dues', to='club.club', verbose_name='club')), ('tier', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='dues', to='billing.tier', verbose_name='tier')), ], options={ 'verbose_name': 'due', 'verbose_name_plural': 'dues', 'ordering': ['-period_start', 'club__name'], }, ), migrations.CreateModel( name='DuePayment', fields=[ ('created', models.DateTimeField(auto_now_add=True, verbose_name='created')), ('modified', models.DateTimeField(auto_now=True, verbose_name='modified')), ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('amount', models.DecimalField(decimal_places=2, max_digits=10, validators=[django.core.validators.MinValueValidator(Decimal('0.01'))], verbose_name='amount')), ('method', models.CharField(choices=[('bank_transfer', 'bank transfer'), ('card', 'card'), ('cash', 'cash'), ('other', 'other')], default='bank_transfer', max_length=20, verbose_name='method')), ('reference', models.CharField(blank=True, help_text='Bank reference, transaction id — whatever lets you find this again.', max_length=255, verbose_name='reference')), ('paid_at', models.DateTimeField(default=django.utils.timezone.now, verbose_name='paid at')), ('note', models.TextField(blank=True, verbose_name='note')), ('due', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='payments', to='billing.due', verbose_name='due')), ('recorded_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='recorded_due_payments', to=settings.AUTH_USER_MODEL, verbose_name='recorded by')), ], options={ 'verbose_name': 'due payment', 'verbose_name_plural': 'due payments', 'ordering': ['-paid_at'], }, ), migrations.CreateModel( name='Invoice', fields=[ ('created', models.DateTimeField(auto_now_add=True, verbose_name='created')), ('modified', models.DateTimeField(auto_now=True, verbose_name='modified')), ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('number', models.CharField(blank=True, max_length=32, unique=True, verbose_name='number')), ('issued_at', models.DateTimeField(default=django.utils.timezone.now, verbose_name='issued at')), ('due', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='invoice', to='billing.due', verbose_name='due')), ], options={ 'verbose_name': 'invoice', 'verbose_name_plural': 'invoices', 'ordering': ['-issued_at'], }, ), migrations.CreateModel( name='Subscription', fields=[ ('created', models.DateTimeField(auto_now_add=True, verbose_name='created')), ('modified', models.DateTimeField(auto_now=True, verbose_name='modified')), ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('auto_archive', models.BooleanField(default=True, help_text='Archive this club when a period goes unpaid past its grace period.', verbose_name='auto archive')), ('notes', models.TextField(blank=True, verbose_name='notes')), ('club', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='subscription', to='club.club', verbose_name='club')), ('tier', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='subscriptions', to='billing.tier', verbose_name='tier')), ], options={ 'verbose_name': 'subscription', 'verbose_name_plural': 'subscriptions', 'ordering': ['club__name'], }, ), migrations.CreateModel( name='TierPrice', fields=[ ('created', models.DateTimeField(auto_now_add=True, verbose_name='created')), ('modified', models.DateTimeField(auto_now=True, verbose_name='modified')), ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('active_from', models.DateField(help_text='Periods opening on or after this date are billed at this amount.', verbose_name='active from')), ('amount', models.DecimalField(decimal_places=2, max_digits=10, validators=[django.core.validators.MinValueValidator(Decimal('0.00'))], verbose_name='amount')), ('tier', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='prices', to='billing.tier', verbose_name='tier')), ], options={ 'verbose_name': 'tier price', 'verbose_name_plural': 'tier prices', 'ordering': ['tier__name', '-active_from'], }, ), migrations.AddConstraint( model_name='due', constraint=models.UniqueConstraint(fields=('club', 'period_start'), name='unique_due_per_club_per_period'), ), migrations.AddConstraint( model_name='tierprice', constraint=models.UniqueConstraint(fields=('tier', 'active_from'), name='unique_tier_price_per_start_date'), ), ]