diff --git a/.gitignore b/.gitignore index e1ed042..226a212 100644 --- a/.gitignore +++ b/.gitignore @@ -90,8 +90,5 @@ secrets.json *.db *.sql -# App migrations (generated by makemigrations) -src/*/migrations/ - # Cloud .cloud diff --git a/src/accounts/migrations/0001_initial.py b/src/accounts/migrations/0001_initial.py new file mode 100644 index 0000000..7ee2987 --- /dev/null +++ b/src/accounts/migrations/0001_initial.py @@ -0,0 +1,98 @@ +# Generated by Django 6.0.6 on 2026-06-28 12:27 + +import django.contrib.auth.models +import django.contrib.auth.validators +import django.db.models.deletion +import django.utils.timezone +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='SiteBranding', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('favicon', models.FileField(blank=True, help_text='Favicon file (.ico, .png)', null=True, upload_to='branding/')), + ('logo', models.ImageField(blank=True, help_text='Main logo image', null=True, upload_to='branding/')), + ('logo_small', models.ImageField(blank=True, help_text='Small logo for collapsed sidebar', null=True, upload_to='branding/')), + ('brand_name', models.CharField(default='Project Management', max_length=100)), + ('copyright_name', models.CharField(default='Project Management', max_length=200)), + ('is_active', models.BooleanField(default=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + options={ + 'verbose_name': 'Site Branding', + 'verbose_name_plural': 'Site Branding', + 'db_table': 'site_branding', + }, + ), + migrations.CreateModel( + name='User', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), + ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), + ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('role', models.CharField(choices=[('superadmin', 'Superadmin'), ('manager', 'Manager'), ('member', 'Member'), ('guest', 'Guest')], default='member', max_length=20)), + ('google_id', models.CharField(blank=True, max_length=255, null=True, unique=True)), + ('profile_image', models.ImageField(blank=True, null=True, upload_to='profiles/')), + ('receive_deadline_emails', models.BooleanField(default=True, help_text='Receive email reminders when ticket deadlines are approaching')), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')), + ], + options={ + 'verbose_name': 'User', + 'verbose_name_plural': 'Users', + 'db_table': 'users', + }, + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.CreateModel( + name='Setting', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('group', models.CharField(blank=True, max_length=255, null=True)), + ('key', models.CharField(max_length=255)), + ('value', models.TextField(blank=True, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='settings', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Setting', + 'verbose_name_plural': 'Settings', + 'db_table': 'settings', + }, + ), + migrations.AddIndex( + model_name='user', + index=models.Index(fields=['role'], name='users_role_0ace22_idx'), + ), + migrations.AddIndex( + model_name='setting', + index=models.Index(fields=['user', 'group'], name='settings_user_id_ab191f_idx'), + ), + migrations.AddConstraint( + model_name='setting', + constraint=models.UniqueConstraint(fields=('user', 'key'), name='unique_user_setting'), + ), + ] diff --git a/src/accounts/migrations/__init__.py b/src/accounts/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/epics/migrations/0001_initial.py b/src/epics/migrations/0001_initial.py new file mode 100644 index 0000000..929ce82 --- /dev/null +++ b/src/epics/migrations/0001_initial.py @@ -0,0 +1,37 @@ +# Generated by Django 6.0.6 on 2026-06-28 12:27 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('projects', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Epic', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('description', models.TextField(blank=True, null=True)), + ('start_date', models.DateField(blank=True, null=True)), + ('end_date', models.DateField(blank=True, null=True)), + ('sort_order', models.IntegerField(default=0)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='epics', to='projects.project')), + ], + options={ + 'verbose_name': 'Epic', + 'verbose_name_plural': 'Epics', + 'db_table': 'epics', + 'ordering': ('sort_order',), + 'indexes': [models.Index(fields=['project', 'sort_order'], name='epics_project_eeb4de_idx')], + }, + ), + ] diff --git a/src/epics/migrations/__init__.py b/src/epics/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/external/migrations/0001_initial.py b/src/external/migrations/0001_initial.py new file mode 100644 index 0000000..f2572de --- /dev/null +++ b/src/external/migrations/0001_initial.py @@ -0,0 +1,36 @@ +# Generated by Django 6.0.6 on 2026-06-28 12:27 + +import django.db.models.deletion +import src.external.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('projects', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='ExternalAccess', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('access_token', models.CharField(default=src.external.models.generate_access_token, max_length=255, unique=True)), + ('password', models.CharField(default=src.external.models.generate_access_password, max_length=255)), + ('is_active', models.BooleanField(default=True)), + ('last_accessed_at', models.DateTimeField(blank=True, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='external_accesses', to='projects.project')), + ], + options={ + 'verbose_name': 'External Access', + 'verbose_name_plural': 'External Accesses', + 'db_table': 'external_access', + 'indexes': [models.Index(fields=['project', 'is_active'], name='external_ac_project_d7e6b3_idx')], + }, + ), + ] diff --git a/src/external/migrations/__init__.py b/src/external/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/notes/migrations/0001_initial.py b/src/notes/migrations/0001_initial.py new file mode 100644 index 0000000..f57cac4 --- /dev/null +++ b/src/notes/migrations/0001_initial.py @@ -0,0 +1,37 @@ +# Generated by Django 6.0.6 on 2026-06-28 12:27 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('projects', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='ProjectNote', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=255)), + ('content', models.TextField(blank=True, null=True)), + ('note_date', models.DateField()), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='project_notes', to=settings.AUTH_USER_MODEL)), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='projects.project')), + ], + options={ + 'verbose_name': 'Project Note', + 'verbose_name_plural': 'Project Notes', + 'db_table': 'project_notes', + 'indexes': [models.Index(fields=['project', 'note_date'], name='project_not_project_833ff9_idx')], + }, + ), + ] diff --git a/src/notes/migrations/__init__.py b/src/notes/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/notifications/migrations/0001_initial.py b/src/notifications/migrations/0001_initial.py new file mode 100644 index 0000000..3eb3dde --- /dev/null +++ b/src/notifications/migrations/0001_initial.py @@ -0,0 +1,56 @@ +# Generated by Django 6.0.6 on 2026-06-28 12:27 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('tickets', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='DeadlineReminderLog', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('days_before', models.IntegerField(help_text='How many days before the deadline this reminder was sent')), + ('sent_at', models.DateTimeField(auto_now_add=True)), + ('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='deadline_reminders', to='tickets.ticket')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='deadline_reminders', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Deadline Reminder Log', + 'verbose_name_plural': 'Deadline Reminder Logs', + 'db_table': 'deadline_reminder_log', + 'indexes': [models.Index(fields=['ticket', 'user'], name='deadline_re_ticket__850437_idx')], + 'constraints': [models.UniqueConstraint(fields=('ticket', 'user', 'days_before'), name='unique_ticket_user_days_reminder')], + }, + ), + migrations.CreateModel( + name='Notification', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('type', models.CharField(help_text='e.g. comment_added, project_assigned', max_length=255)), + ('title', models.CharField(max_length=255)), + ('message', models.TextField(blank=True, null=True)), + ('data', models.JSONField(blank=True, help_text='Arbitrary payload e.g. ticket_id, comment_id', null=True)), + ('read_at', models.DateTimeField(blank=True, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notifications', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Notification', + 'verbose_name_plural': 'Notifications', + 'db_table': 'notifications', + 'ordering': ('-created_at',), + 'indexes': [models.Index(fields=['user', 'read_at'], name='notificatio_user_id_6c7360_idx'), models.Index(fields=['user', 'created_at'], name='notificatio_user_id_7336fd_idx')], + }, + ), + ] diff --git a/src/notifications/migrations/__init__.py b/src/notifications/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/projects/migrations/0001_initial.py b/src/projects/migrations/0001_initial.py new file mode 100644 index 0000000..b1be45c --- /dev/null +++ b/src/projects/migrations/0001_initial.py @@ -0,0 +1,73 @@ +# Generated by Django 6.0.6 on 2026-06-28 12:27 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Project', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('description', models.TextField(blank=True, null=True)), + ('ticket_prefix', models.CharField(max_length=255)), + ('color', models.CharField(blank=True, help_text='Hex color e.g. #3B82F6', max_length=7, null=True)), + ('start_date', models.DateField(blank=True, null=True)), + ('end_date', models.DateField(blank=True, null=True)), + ('pinned_date', models.DateTimeField(blank=True, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + options={ + 'verbose_name': 'Project', + 'verbose_name_plural': 'Projects', + 'db_table': 'projects', + }, + ), + migrations.CreateModel( + name='ProjectMember', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='project_members', to='projects.project')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='project_memberships', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Project Member', + 'verbose_name_plural': 'Project Members', + 'db_table': 'project_members', + }, + ), + migrations.AddField( + model_name='project', + name='members', + field=models.ManyToManyField(related_name='projects', through='projects.ProjectMember', to=settings.AUTH_USER_MODEL), + ), + migrations.AddIndex( + model_name='projectmember', + index=models.Index(fields=['user', 'project'], name='project_mem_user_id_6b0bb0_idx'), + ), + migrations.AddConstraint( + model_name='projectmember', + constraint=models.UniqueConstraint(fields=('project', 'user'), name='unique_project_member'), + ), + migrations.AddIndex( + model_name='project', + index=models.Index(fields=['pinned_date'], name='projects_pinned__118cce_idx'), + ), + migrations.AddIndex( + model_name='project', + index=models.Index(fields=['start_date', 'end_date'], name='projects_start_d_cb24a6_idx'), + ), + ] diff --git a/src/projects/migrations/__init__.py b/src/projects/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/tickets/migrations/0001_initial.py b/src/tickets/migrations/0001_initial.py new file mode 100644 index 0000000..ad618aa --- /dev/null +++ b/src/tickets/migrations/0001_initial.py @@ -0,0 +1,193 @@ +# Generated by Django 6.0.6 on 2026-06-28 12:27 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('epics', '0001_initial'), + ('projects', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='TicketPriority', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, unique=True)), + ('color', models.CharField(default='#6B7280', max_length=7)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + options={ + 'verbose_name': 'Ticket Priority', + 'verbose_name_plural': 'Ticket Priorities', + 'db_table': 'ticket_priorities', + }, + ), + migrations.CreateModel( + name='Ticket', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('description', models.TextField(blank=True, null=True)), + ('uuid', models.CharField(editable=False, max_length=255, unique=True)), + ('start_date', models.DateField(blank=True, null=True)), + ('due_date', models.DateField(blank=True, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_tickets', to=settings.AUTH_USER_MODEL)), + ('epic', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets', to='epics.epic')), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tickets', to='projects.project')), + ('priority', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets', to='tickets.ticketpriority')), + ], + options={ + 'verbose_name': 'Ticket', + 'verbose_name_plural': 'Tickets', + 'db_table': 'tickets', + }, + ), + migrations.CreateModel( + name='TicketStatus', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('color', models.CharField(default='#10B981', max_length=7)), + ('sort_order', models.IntegerField(default=0)), + ('is_completed', models.BooleanField(default=False)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_statuses', to='projects.project')), + ], + options={ + 'verbose_name': 'Ticket Status', + 'verbose_name_plural': 'Ticket Statuses', + 'db_table': 'ticket_statuses', + }, + ), + migrations.CreateModel( + name='TicketHistory', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='histories', to='tickets.ticket')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_histories', to=settings.AUTH_USER_MODEL)), + ('status', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='histories', to='tickets.ticketstatus')), + ], + options={ + 'verbose_name': 'Ticket History', + 'verbose_name_plural': 'Ticket Histories', + 'db_table': 'ticket_histories', + }, + ), + migrations.AddField( + model_name='ticket', + name='status', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tickets', to='tickets.ticketstatus'), + ), + migrations.CreateModel( + name='TicketUser', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_assignees', to='tickets.ticket')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Ticket Assignee', + 'verbose_name_plural': 'Ticket Assignees', + 'db_table': 'ticket_users', + }, + ), + migrations.AddField( + model_name='ticket', + name='assignees', + field=models.ManyToManyField(related_name='assigned_tickets', through='tickets.TicketUser', to=settings.AUTH_USER_MODEL), + ), + migrations.CreateModel( + name='TicketComment', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('comment', models.TextField(help_text='Rich text HTML content')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='replies', to='tickets.ticketcomment')), + ('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='tickets.ticket')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_comments', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Ticket Comment', + 'verbose_name_plural': 'Ticket Comments', + 'db_table': 'ticket_comments', + 'indexes': [models.Index(fields=['ticket', 'created_at'], name='ticket_comm_ticket__5ef05d_idx')], + }, + ), + migrations.AddIndex( + model_name='ticketstatus', + index=models.Index(fields=['project', 'sort_order'], name='ticket_stat_project_262e3f_idx'), + ), + migrations.AddIndex( + model_name='ticketstatus', + index=models.Index(fields=['project', 'is_completed'], name='ticket_stat_project_283078_idx'), + ), + migrations.AddIndex( + model_name='ticketstatus', + index=models.Index(fields=['project', 'name'], name='ticket_stat_project_1d8cf1_idx'), + ), + migrations.AddIndex( + model_name='tickethistory', + index=models.Index(fields=['ticket', 'created_at'], name='ticket_hist_ticket__e81360_idx'), + ), + migrations.AddIndex( + model_name='tickethistory', + index=models.Index(fields=['user', 'created_at'], name='ticket_hist_user_id_116996_idx'), + ), + migrations.AddIndex( + model_name='ticketuser', + index=models.Index(fields=['ticket', 'user'], name='ticket_user_ticket__0340c3_idx'), + ), + migrations.AddIndex( + model_name='ticketuser', + index=models.Index(fields=['user'], name='ticket_user_user_id_437f9e_idx'), + ), + migrations.AddConstraint( + model_name='ticketuser', + constraint=models.UniqueConstraint(fields=('ticket', 'user'), name='unique_ticket_user'), + ), + migrations.AddIndex( + model_name='ticket', + index=models.Index(fields=['project', 'status'], name='tickets_project_3ab72a_idx'), + ), + migrations.AddIndex( + model_name='ticket', + index=models.Index(fields=['status', 'created_at'], name='tickets_status__3a7341_idx'), + ), + migrations.AddIndex( + model_name='ticket', + index=models.Index(fields=['project', 'created_at'], name='tickets_project_5cdbb2_idx'), + ), + migrations.AddIndex( + model_name='ticket', + index=models.Index(fields=['project', 'updated_at'], name='tickets_project_4298d2_idx'), + ), + migrations.AddIndex( + model_name='ticket', + index=models.Index(fields=['due_date'], name='tickets_due_dat_c75c11_idx'), + ), + migrations.AddIndex( + model_name='ticket', + index=models.Index(fields=['priority'], name='tickets_priorit_1ce021_idx'), + ), + migrations.AddIndex( + model_name='ticket', + index=models.Index(fields=['created_by'], name='tickets_created_b5c671_idx'), + ), + ] diff --git a/src/tickets/migrations/__init__.py b/src/tickets/migrations/__init__.py new file mode 100644 index 0000000..e69de29