# Generated by Pi coding agent from django.conf import settings from django.db import migrations, models import django.db.models.deletion def forwards(apps, schema_editor): User = apps.get_model(*settings.AUTH_USER_MODEL.split('.')) Workspace = apps.get_model('core', 'Workspace') WorkspaceMembership = apps.get_model('core', 'WorkspaceMembership') Tag = apps.get_model('core', 'Tag') Team = apps.get_model('core', 'Team') Item = apps.get_model('core', 'Item') Collection = apps.get_model('core', 'Collection') Kanban = apps.get_model('core', 'Kanban') ApiKey = apps.get_model('core', 'ApiKey') personal = {} for user in User.objects.all(): full_name = f'{getattr(user, "first_name", "")} {getattr(user, "last_name", "")}'.strip() name = full_name or getattr(user, 'username', '') or f'User {user.pk}' workspace, _ = Workspace.objects.get_or_create(slug=f'user-{user.pk}', defaults={'name': name, 'owner_id': user.pk}) WorkspaceMembership.objects.get_or_create(workspace=workspace, user=user, defaults={'role': 'owner'}) personal[user.pk] = workspace def workspace_for_user(user_id): if user_id not in personal: user = User.objects.get(pk=user_id) workspace, _ = Workspace.objects.get_or_create(slug=f'user-{user.pk}', defaults={'name': getattr(user, 'username', '') or f'User {user.pk}', 'owner_id': user.pk}) WorkspaceMembership.objects.get_or_create(workspace=workspace, user=user, defaults={'role': 'owner'}) personal[user_id] = workspace return personal[user_id] for team in Team.objects.select_related('owner'): team.workspace = workspace_for_user(team.owner_id) team.save(update_fields=['workspace']) for item in Item.objects.select_related('owner', 'team'): item.workspace = item.team.workspace if item.team_id and item.team.workspace_id else workspace_for_user(item.owner_id) item.save(update_fields=['workspace']) for collection in Collection.objects.select_related('owner', 'team'): collection.workspace = collection.team.workspace if collection.team_id and collection.team.workspace_id else workspace_for_user(collection.owner_id) collection.save(update_fields=['workspace']) for kanban in Kanban.objects.select_related('owner'): kanban.workspace = workspace_for_user(kanban.owner_id) kanban.save(update_fields=['workspace']) for api_key in ApiKey.objects.select_related('owner'): api_key.workspace = workspace_for_user(api_key.owner_id) api_key.save(update_fields=['workspace']) fallback_workspace = next(iter(personal.values()), None) for tag in list(Tag.objects.all()): workspace_ids = set(tag.items.exclude(workspace__isnull=True).values_list('workspace_id', flat=True)) workspace_ids.update(tag.tag_collections.exclude(workspace__isnull=True).values_list('workspace_id', flat=True)) workspace_ids.update(tag.kanbans.exclude(workspace__isnull=True).values_list('workspace_id', flat=True)) workspace_ids.update(tag.api_keys.exclude(workspace__isnull=True).values_list('workspace_id', flat=True)) workspace_ids.update(Team.objects.filter(slug=tag.name).exclude(workspace__isnull=True).values_list('workspace_id', flat=True)) if not workspace_ids and fallback_workspace: workspace_ids.add(fallback_workspace.pk) if not workspace_ids: tag.delete() continue first = True for workspace_id in sorted(workspace_ids): if first: scoped_tag = tag scoped_tag.workspace_id = workspace_id scoped_tag.save(update_fields=['workspace']) first = False else: scoped_tag, _ = Tag.objects.get_or_create(workspace_id=workspace_id, name=tag.name) for item in list(tag.items.filter(workspace_id=workspace_id)): item.tags.remove(tag) item.tags.add(scoped_tag) for collection in list(tag.tag_collections.filter(workspace_id=workspace_id)): collection.filter_tags.remove(tag) collection.filter_tags.add(scoped_tag) for api_key in list(tag.api_keys.filter(workspace_id=workspace_id)): api_key.tags.remove(tag) api_key.tags.add(scoped_tag) Kanban.objects.filter(workspace_id=workspace_id, tag=tag).update(tag=scoped_tag) for team in Team.objects.exclude(workspace__isnull=True): Tag.objects.get_or_create(workspace=team.workspace, name=team.slug) class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('core', '0021_collection_type_filters'), ] operations = [ migrations.CreateModel( name='Workspace', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=120)), ('slug', models.SlugField(allow_unicode=True, max_length=80, unique=True)), ('created_at', models.DateTimeField(auto_now_add=True)), ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='owned_workspaces', to=settings.AUTH_USER_MODEL)), ], options={'ordering': ['name']}, ), migrations.CreateModel( name='WorkspaceMembership', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('role', models.CharField(choices=[('owner', 'Owner'), ('admin', 'Admin'), ('member', 'Member')], default='member', max_length=10)), ('created_at', models.DateTimeField(auto_now_add=True)), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='workspace_memberships', to=settings.AUTH_USER_MODEL)), ('workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='memberships', to='core.workspace')), ], options={'unique_together': {('workspace', 'user')}}, ), migrations.AddField('tag', 'workspace', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tags', to='core.workspace')), migrations.AlterField('tag', 'name', models.SlugField(allow_unicode=True, max_length=80)), migrations.AddField('team', 'workspace', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='teams', to='core.workspace')), migrations.AlterField('team', 'slug', models.SlugField(allow_unicode=True, help_text='Team-Tag ohne #, z.B. my2dos', max_length=80)), migrations.AddField('item', 'workspace', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='items', to='core.workspace')), migrations.AddField('collection', 'workspace', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='collections', to='core.workspace')), migrations.AddField('kanban', 'workspace', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kanbans', to='core.workspace')), migrations.AddField('apikey', 'workspace', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='api_keys', to='core.workspace')), migrations.RunPython(forwards, migrations.RunPython.noop), migrations.AlterField('tag', 'workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tags', to='core.workspace')), migrations.AlterField('team', 'workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teams', to='core.workspace')), migrations.AlterField('item', 'workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='core.workspace')), migrations.AlterField('collection', 'workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='collections', to='core.workspace')), migrations.AlterField('kanban', 'workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='kanbans', to='core.workspace')), migrations.AlterField('apikey', 'workspace', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='api_keys', to='core.workspace')), migrations.AddConstraint('tag', models.UniqueConstraint(fields=('workspace', 'name'), name='unique_workspace_tag_name')), migrations.AddConstraint('team', models.UniqueConstraint(fields=('workspace', 'slug'), name='unique_workspace_team_slug')), ]