diff --git a/apiserver/plane/ee/migrations/0021_initiativeepic_and_more.py b/apiserver/plane/ee/migrations/0021_initiativeepic_and_more.py new file mode 100644 index 0000000000..6e6eac6ac9 --- /dev/null +++ b/apiserver/plane/ee/migrations/0021_initiativeepic_and_more.py @@ -0,0 +1,45 @@ +# Generated by Django 4.2.17 on 2025-01-02 08:47 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('db', '0088_sticky_sort_order_workspaceuserlink'), + ('ee', '0020_rename_type_workspaceentityconnection_source_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='InitiativeEpic', + fields=[ + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Last Modified At')), + ('deleted_at', models.DateTimeField(blank=True, null=True, verbose_name='Deleted At')), + ('id', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)), + ('sort_order', models.FloatField(default=65535)), + ('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created_by', to=settings.AUTH_USER_MODEL, verbose_name='Created By')), + ('epic', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='initiative_epics', to='db.issue')), + ('initiative', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='initiative_epics', to='ee.initiative')), + ('updated_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated_by', to=settings.AUTH_USER_MODEL, verbose_name='Last Modified By')), + ('workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='initiative_epics', to='db.workspace')), + ], + options={ + 'verbose_name': 'Initiative Epic', + 'verbose_name_plural': 'Initiative Epics', + 'db_table': 'initiative_epics', + }, + ), + migrations.AddConstraint( + model_name='initiativeepic', + constraint=models.UniqueConstraint(condition=models.Q(('deleted_at__isnull', True)), fields=('initiative', 'epic'), name='initiative_epic_unique_initiative_epic_when_deleted_at_null'), + ), + migrations.AlterUniqueTogether( + name='initiativeepic', + unique_together={('initiative', 'epic', 'deleted_at')}, + ), + ] diff --git a/apiserver/plane/ee/models/initiative.py b/apiserver/plane/ee/models/initiative.py index 7fe5f89978..1e2d78eef6 100644 --- a/apiserver/plane/ee/models/initiative.py +++ b/apiserver/plane/ee/models/initiative.py @@ -309,3 +309,33 @@ class InitiativeUserProperty(BaseModel): def __str__(self): """Return properties status of the initiative""" return str(self.user) + + +class InitiativeEpic(BaseModel): + workspace = models.ForeignKey( + "db.Workspace", on_delete=models.CASCADE, related_name="initiative_epics" + ) + initiative = models.ForeignKey( + "ee.Initiative", on_delete=models.CASCADE, related_name="initiative_epics" + ) + epic = models.ForeignKey( + "db.Issue", on_delete=models.CASCADE, related_name="initiative_epics" + ) + sort_order = models.FloatField(default=65535) + + class Meta: + unique_together = ["initiative", "epic", "deleted_at"] + constraints = [ + models.UniqueConstraint( + fields=["initiative", "epic"], + condition=models.Q(deleted_at__isnull=True), + name="initiative_epic_unique_initiative_epic_when_deleted_at_null", + ) + ] + db_table = "initiative_epics" + verbose_name = "Initiative Epic" + verbose_name_plural = "Initiative Epics" + + def __str__(self): + """Return epic of the initiative""" + return f"{self.initiative.name} {self.epic.name}"