# Generated by Django 5.0.10 on 2024-12-16 15:32

from django.db import migrations, models
import django.db.models.deletion
from datetime import date

from django.db.models import Exists


def migrate_path(apps, schema_editor):
    Product = apps.get_model("wbportfolio", "Product")
    Index = apps.get_model("wbportfolio", "Index")
    for product in Product.objects.filter(price_computation__import_path="restbench.price.peers"):
        product.custom_net_asset_value_computation_method_path = "restbench.price.peers" + ".get_estimate_net_value"
        product.save()
    for index in Index.objects.filter(price_computation__import_path="restbench.price.peers"):
        index.custom_net_asset_value_computation_method_path = "restbench.price.peers" + ".get_estimate_net_value"
        index.save()


def migrate_data(apps, schema_editor):
    Portfolio = apps.get_model("wbportfolio", "Portfolio")
    RebalancingModel = apps.get_model("wbportfolio", "RebalancingModel")
    PortfolioPortfolioThroughModel = apps.get_model("wbportfolio", "PortfolioPortfolioThroughModel")
    Rebalancer = apps.get_model("wbportfolio", "Rebalancer")
    equally_weighted_model, _ = RebalancingModel.objects.get_or_create(
        class_path="wbportfolio.rebalancing.models.equally_weighted.EquallyWeightedRebalancing",
        defaults={"name": "Equally Weighted Rebalancing"},
    )
    composite_model, _ = RebalancingModel.objects.get_or_create(
        class_path="wbportfolio.rebalancing.models.composite.CompositeRebalancing",
        defaults={"name": "Composite Rebalancing"},
    )
    PortfolioPortfolioThroughModel.objects.filter(portfolio=models.F("dependency_portfolio")).delete()
    Portfolio.objects.annotate(has_primary=Exists(PortfolioPortfolioThroughModel.objects.filter(portfolio=models.OuterRef("pk"), type="PRIMARY"))).filter(has_primary=True, portfolio_synchronization__name="Default Portfolio Synchronization").update(
        is_lookthrough=True
    )
    for portfolio in Portfolio.objects.filter(portfolio_synchronization__name="Composite synchronization"):
        try:
            activation_date = portfolio.assets.earliest("date").date
        except Exception:
            activation_date = date.today()
        Rebalancer.objects.create(
            portfolio=portfolio,
            rebalancing_model=composite_model,
            approve_trade_proposal_automatically=True,
            frequency="RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=1",
            activation_date=activation_date,
        )
    for portfolio in Portfolio.objects.filter(portfolio_synchronization__name="Equally-weighted Synchronization"):
        try:
            activation_date = portfolio.assets.earliest("date").date
        except Exception:
            activation_date = date.today()
        Rebalancer.objects.create(
            portfolio=portfolio,
            rebalancing_model=equally_weighted_model,
            approve_trade_proposal_automatically=True,
            frequency="RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=1",
            activation_date=activation_date,
        )

def set_composition(apps, schema_editor):
    Portfolio = apps.get_model("wbportfolio", "Portfolio")
    for portfolio in Portfolio.objects.all():
        if portfolio.assets.filter(underlying_instrument__instrument_type__key__in=["index", "product", "product_group"]).exists():
            portfolio.is_composition = True
            portfolio.save()

class Migration(migrations.Migration):
    dependencies = [
        ('directory', '0009_remove_entry_external_identfier_and_more'),
        ('io', '0007_alter_exportsource_query_params'),
        ('wbfdm', '0028_instrumentprice_annualized_daily_volatility'),
        ("wbportfolio", "0072_trade_diff_shares"),
    ]

    operations = [
        migrations.AddField(
            model_name="index",
            name="custom_net_asset_value_computation_method_path",
            field=models.CharField(blank=True, null=True, verbose_name="Custom NAV Computation Method"),
        ),
        migrations.AddField(
            model_name="product",
            name="custom_net_asset_value_computation_method_path",
            field=models.CharField(blank=True, null=True, verbose_name="Custom NAV Computation Method"),
        ),
        migrations.RunSQL(
            sql="SET CONSTRAINTS ALL IMMEDIATE;",
        ),
        migrations.RunPython(migrate_path),
        migrations.RunSQL(
            sql="SET CONSTRAINTS ALL DEFERRED;",
        ),
        migrations.RemoveField(
            model_name="product",
            name="price_computation",
        ),
        migrations.RemoveField(
            model_name="index",
            name="price_computation",
        ),
        migrations.DeleteModel(
            name="PriceComputation",
        ),
        migrations.CreateModel(
            name="RebalancingModel",
            fields=[
                ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
                ("name", models.CharField(max_length=64, verbose_name="Name")),
                ("class_path", models.CharField(max_length=512, verbose_name="Class path")),
            ],
            options={
                "verbose_name": "Rebalancing Model",
                "verbose_name_plural": "Rebalancing Models",
            },
        ),
        migrations.RenameField(
            model_name="portfolio",
            old_name="last_synchronization",
            new_name="updated_at",
        ),
        migrations.AddField(
            model_name="portfolio",
            name="is_lookthrough",
            field=models.BooleanField(
                default=False, help_text="Indicates that this portfolio is a look-through portfolio"
            ),
        ),
        migrations.AddField(
            model_name="tradeproposal",
            name="rebalancing_model",
            field=models.ForeignKey(
                blank=True,
                help_text="Rebalancing Model to use to generate the target portfolio",
                null=True,
                on_delete=django.db.models.deletion.SET_NULL,
                related_name="trade_proposals",
                to="wbportfolio.rebalancingmodel",
                verbose_name="Rebalancing Model",
            ),
        ),
        migrations.CreateModel(
            name="Rebalancer",
            fields=[
                ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
                ("parameters", models.JSONField(default=dict, verbose_name="Parameters")),
                (
                    "approve_trade_proposal_automatically",
                    models.BooleanField(default=False, verbose_name="Apply Trade Proposal Automatically"),
                ),
                ("activation_date", models.DateField(verbose_name="Activation Date")),
                (
                    "frequency",
                    models.CharField(
                        default="RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=1",
                        help_text="The Evaluation Frequency in RRULE format",
                        max_length=56,
                        verbose_name="Evaluation Frequency",
                    ),
                ),
                (
                    "portfolio",
                    models.OneToOneField(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="automatic_rebalancer",
                        to="wbportfolio.portfolio",
                    ),
                ),
                (
                    "rebalancing_model",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.PROTECT,
                        related_name="rebalancers",
                        to="wbportfolio.rebalancingmodel",
                        verbose_name="Rebalancing Model",
                    ),
                ),
                ("computed_str", models.CharField(blank=True, max_length=512, null=True, verbose_name="Name")),
            ],
            options={
                "verbose_name": "Rebalancer",
                "verbose_name_plural": "Rebalancers",
            },
        ),
        migrations.RunSQL(
            sql="SET CONSTRAINTS ALL IMMEDIATE;",
        ),
        migrations.RunPython(migrate_data),
        migrations.RunSQL(
            sql="SET CONSTRAINTS ALL DEFERRED;",
        ),
        migrations.RemoveField(
            model_name="tradeproposal",
            name="model_portfolio",
        ),
        migrations.RemoveField(
            model_name="portfolio",
            name="portfolio_synchronization",
        ),
        migrations.RemoveField(
            model_name="synchronizationtask",
            name="dependent_task",
        ),
        migrations.RemoveField(
            model_name="synchronizationtask",
            name="periodictask_ptr",
        ),
        migrations.DeleteModel(
            name="PortfolioSynchronization",
        ),
        migrations.DeleteModel(
            name="SynchronizationTask",
        ),
        migrations.AlterUniqueTogether(
            name='adjustment',
            unique_together=set(),
        ),
        migrations.AlterUniqueTogether(
            name='instrumentportfoliothroughmodel',
            unique_together=set(),
        ),
        migrations.AlterUniqueTogether(
            name='portfolioinstrumentpreferredclassificationthroughmodel',
            unique_together=set(),
        ),
        migrations.AlterUniqueTogether(
            name='tradeproposal',
            unique_together=set(),
        ),
        migrations.RemoveField(
            model_name='index',
            name='custom_net_asset_value_computation_method_path',
        ),
        migrations.RemoveField(
            model_name='product',
            name='custom_net_asset_value_computation_method_path',
        ),
        migrations.AddField(
            model_name='index',
            name='net_asset_value_computation_method_path',
            field=models.CharField(blank=True, default='wbportfolio.models.portfolio.default_estimate_net_value',
                                   null=True, verbose_name='NAV Computation Method'),
        ),
        migrations.AddField(
            model_name='product',
            name='net_asset_value_computation_method_path',
            field=models.CharField(blank=True, default='wbportfolio.models.portfolio.default_estimate_net_value',
                                   null=True, verbose_name='NAV Computation Method'),
        ),
        migrations.AlterField(
            model_name='portfolio',
            name='is_tracked',
            field=models.BooleanField(default=True,
                                      help_text='True if the internal updating mechanism (e.g., Next weights or Look-Through computation, rebalancing etc...) needs to apply to this portfolio'),
        ),
        migrations.AlterField(
            model_name='portfolio',
            name='updated_at',
            field=models.DateTimeField(blank=True, null=True, verbose_name='Updated At'),
        ),
        migrations.AlterField(
            model_name='tradeproposal',
            name='rebalancing_model',
            field=models.ForeignKey(blank=True, help_text='Rebalancing Model that generates the target portfolio',
                                    null=True, on_delete=django.db.models.deletion.SET_NULL,
                                    related_name='trade_proposals', to='wbportfolio.rebalancingmodel',
                                    verbose_name='Rebalancing Model'),
        ),
        migrations.AddConstraint(
            model_name='adjustment',
            constraint=models.UniqueConstraint(fields=('date', 'instrument'), name='unique_date_instrument'),
        ),
        migrations.AddConstraint(
            model_name='portfolioinstrumentpreferredclassificationthroughmodel',
            constraint=models.UniqueConstraint(fields=('portfolio', 'instrument', 'classification_group'),
                                               name='unique_prefered_classification_relationship'),
        ),
        migrations.AddConstraint(
            model_name='tradeproposal',
            constraint=models.UniqueConstraint(fields=('portfolio', 'trade_date'), name='unique_trade_proposal'),
        ),
        migrations.AddField(
            model_name='productgroup',
            name='net_asset_value_computation_method_path',
            field=models.CharField(blank=True, default='wbportfolio.models.portfolio.default_estimate_net_value',
                                   null=True, verbose_name='NAV Computation Method'),
        ),
        migrations.AddField(
            model_name='productgroup',
            name='risk_scale',
            field=models.IntegerField(default=4, validators=[django.core.validators.MinValueValidator(1),
                                                             django.core.validators.MaxValueValidator(7)],
                                      verbose_name='Risk Scale'),
        ),
        migrations.AlterField(
            model_name='index',
            name='risk_scale',
            field=models.IntegerField(default=4, validators=[django.core.validators.MinValueValidator(1),
                                                             django.core.validators.MaxValueValidator(7)],
                                      verbose_name='Risk Scale'),
        ),
        migrations.AlterField(
            model_name='index',
            name='net_asset_value_computation_method_path',
            field=models.CharField(blank=True, default='wbportfolio.models.portfolio.default_estimate_net_value',
                                   null=True, verbose_name='NAV Computation Method'),
        ),
        migrations.AlterField(
            model_name='product',
            name='net_asset_value_computation_method_path',
            field=models.CharField(blank=True, default='wbportfolio.models.portfolio.default_estimate_net_value',
                                   null=True, verbose_name='NAV Computation Method'),
        ),
        migrations.AlterField(
            model_name='productgroup',
            name='net_asset_value_computation_method_path',
            field=models.CharField(blank=True, default='wbportfolio.models.portfolio.default_estimate_net_value',
                                   null=True, verbose_name='NAV Computation Method'),
        ),
        migrations.RemoveConstraint(
            model_name='assetposition',
            name='wbportfolio_assetposition_weekday_constraint',
        ),
        migrations.RemoveConstraint(
            model_name='assetposition',
            name='unique_asset_position',
        ),
        migrations.RemoveIndex(
            model_name='assetposition',
            name='wbportfolio_date_0a7c0a_idx',
        ),
        migrations.RemoveIndex(
            model_name='assetposition',
            name='wbportfolio_date_da82d2_idx',
        ),
        migrations.AddField(
            model_name='assetposition',
            name='underlying_quote',
            field=models.ForeignKey(blank=True, help_text='The quote that is this asset.',
                                    limit_choices_to=models.Q(('children__isnull', True)), null=True,
                                    on_delete=django.db.models.deletion.PROTECT, related_name='assets',
                                    to='wbfdm.instrument', verbose_name='Underlying Quote'),
        ),
        migrations.AlterField(
            model_name='assetposition',
            name='underlying_instrument',
            field=models.ForeignKey(help_text='The instrument that is this asset.',
                                    on_delete=django.db.models.deletion.PROTECT, related_name='instrument_assets',
                                    to='wbfdm.instrument', verbose_name='Underlying Instrument'),
        ),
        migrations.RunSQL(
            sql="UPDATE wbportfolio_assetposition SET underlying_quote_id = underlying_instrument_id",
            reverse_sql=migrations.RunSQL.noop
        ),
        migrations.AlterField(
            model_name='assetposition',
            name='underlying_quote',
            field=models.ForeignKey(help_text='The quote that is this asset.',
                                    limit_choices_to=models.Q(('children__isnull', True)),
                                    on_delete=django.db.models.deletion.PROTECT, related_name='assets',
                                    to='wbfdm.instrument', verbose_name='Underlying Quote'),
        ),
        migrations.AddIndex(
            model_name='assetposition',
            index=models.Index(fields=['date', 'underlying_instrument', 'portfolio'],
                               name='wbportfolio_date_0a7c0a_idx'),
        ),
        migrations.AddIndex(
            model_name='assetposition',
            index=models.Index(fields=['date', 'underlying_instrument'], name='wbportfolio_date_da82d2_idx'),
        ),
        migrations.AddConstraint(
            model_name='assetposition',
            constraint=models.CheckConstraint(check=models.Q(('date__week_day__in', [1, 7]), _negated=True),
                                              name='wbportfolio_assetposition_weekday_constraint'),
        ),
        migrations.AddConstraint(
            model_name='assetposition',
            constraint=models.UniqueConstraint(fields=('portfolio', 'date', 'underlying_quote', 'portfolio_created'),
                                               name='unique_asset_position', nulls_distinct=False),
        ),
        migrations.RenameField(
            model_name='assetposition',
            old_name='underlying_instrument_price',
            new_name='underlying_quote_price',
        ),
        migrations.AlterField(
            model_name='portfolioportfoliothroughmodel',
            name='type',
            field=models.CharField(choices=[('PRIMARY', 'Primary'), ('MODEL', 'Model'), ('CUSTODIAN', 'Custodian')],
                                   default='PRIMARY', verbose_name='Type'),
        ),
        migrations.AlterField(
            model_name='rebalancer',
            name='parameters',
            field=models.JSONField(blank=True, default=dict, verbose_name='Parameters'),
        ),
        migrations.AddField(
            model_name='portfolio',
            name='is_composition',
            field=models.BooleanField(default=False,
                                      help_text='If true, this portfolio is a composition of other portfolio'),
        ),
        migrations.RunPython(set_composition)
    ]
