diff --git a/apps/account/management/commands/add_affilations.py b/apps/account/management/commands/add_affilations.py new file mode 100644 index 00000000..591e676d --- /dev/null +++ b/apps/account/management/commands/add_affilations.py @@ -0,0 +1,152 @@ +from account.models import OldRole, Role, User, UserRole +from main.models import SiteSettings +from django.core.management.base import BaseCommand +from django.db import connections, transaction +from django.db.models import Prefetch +from establishment.management.commands.add_position import namedtuplefetchall +from tqdm import tqdm + + +class Command(BaseCommand): + help = '''Add site affilations from old db to new db. + Run after migrate account models!!!''' + + def map_role_sql(self): + with connections['legacy'].cursor() as cursor: + cursor.execute(''' + select distinct + case when role = 'news_editor' then 'CONTENT_PAGE_MANAGER' + when role in ('reviewer', 'reviwer', 'reviewer_manager') then 'REVIEWER_MANGER' + when role = 'admin' then 'SUPERUSER' + when role ='community_manager' then 'COUNTRY_ADMIN' + when role = 'site_admin' then 'COUNTRY_ADMIN' + when role = 'wine_reviewer' then 'WINERY_REVIEWER' + when role in ('salesman', 'sales_man') then 'SALES_MAN' + when role = 'seller' then 'SELLER' + else role + end as new_role, + case when role = 'GUEST' then null else role end as role + from + ( + SELECT + DISTINCT + COALESCE(role, 'GUEST') as role + FROM site_affiliations AS sa + ) t + ''') + return namedtuplefetchall(cursor) + + def add_old_roles(self): + objects = [] + OldRole.objects.all().delete() + for s in tqdm(self.map_role_sql(), desc='Add permissions old'): + objects.append( + OldRole(new_role=s.new_role, old_role=s.role) + ) + OldRole.objects.bulk_create(objects) + self.stdout.write(self.style.WARNING(f'Migrated old roles.')) + + def site_role_sql(self): + with connections['legacy'].cursor() as cursor: + cursor.execute(''' + select site_id, + role + from + ( + SELECT + DISTINCT + site_id, + COALESCE(role, 'GUEST') as role + FROM site_affiliations AS sa + ) t + where t.role not in ('admin', 'GUEST') + ''') + return namedtuplefetchall(cursor) + + def add_site_role(self): + objects = [] + for s in tqdm(self.site_role_sql(), desc='Add site role'): + old_role = OldRole.objects.get(old_role=s.role) + role_choice = getattr(Role, old_role.new_role) + sites = SiteSettings.objects.filter(old_id=s.site_id) + for site in sites: + role = Role.objects.filter(site=site, role=role_choice) + if not role.exists(): + objects.append( + Role(site=site, role=role_choice) + ) + + Role.objects.bulk_create(objects) + self.stdout.write(self.style.WARNING(f'Added site roles.')) + + def update_site_role(self): + roles = Role.objects.filter(country__isnull=True).select_related('site')\ + .filter(site__id__isnull=False).select_for_update() + with transaction.atomic(): + for role in tqdm(roles, desc='Update role country'): + role.country = role.site.country + role.save() + self.stdout.write(self.style.WARNING(f'Updated site roles.')) + + def user_role_sql(self): + with connections['legacy'].cursor() as cursor: + cursor.execute(''' + select t.* + from + ( + SELECT + site_id, + account_id, + COALESCE(role, 'GUEST') as role + FROM site_affiliations AS sa + ) t + join accounts a on a.id = t.account_id + where t.role not in ('admin', 'GUEST') + ''') + return namedtuplefetchall(cursor) + + def add_role_user(self): + for s in tqdm(self.user_role_sql(), desc='Add role to user'): + sites = SiteSettings.objects.filter(old_id=s.site_id) + old_role = OldRole.objects.get(old_role=s.role) + role_choice = getattr(Role, old_role.new_role) + roles = Role.objects.filter(site__in=[site for site in sites], role=role_choice) + users = User.objects.filter(old_id=s.account_id) + for user in users: + for role in roles: + user_role = UserRole.objects.get_or_create(user=user, + role=role) + self.stdout.write(self.style.WARNING(f'Added users roles.')) + + def superuser_role_sql(self): + with connections['legacy'].cursor() as cursor: + cursor.execute(''' + select t.* + from + ( + SELECT + site_id, + account_id, + COALESCE(role, 'GUEST') as role + FROM site_affiliations AS sa + ) t + join accounts a on a.id = t.account_id + where t.role in ('admin') + ''') + return namedtuplefetchall(cursor) + + def add_superuser(self): + for s in tqdm(self.superuser_role_sql(), desc='Add superuser'): + users = User.objects.filter(old_id=s.account_id).select_for_update() + with transaction.atomic(): + for user in users: + user.is_superuser = True + user.save() + self.stdout.write(self.style.WARNING(f'Added superuser.')) + + def handle(self, *args, **kwargs): + self.add_old_roles() + self.add_site_role() + self.update_site_role() + self.add_role_user() + self.add_superuser() \ No newline at end of file diff --git a/apps/account/migrations/0021_oldrole.py b/apps/account/migrations/0021_oldrole.py new file mode 100644 index 00000000..9a8fd4e9 --- /dev/null +++ b/apps/account/migrations/0021_oldrole.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2.7 on 2019-12-03 10:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0020_role_site'), + ] + + operations = [ + migrations.CreateModel( + name='OldRole', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('new_role', models.CharField(max_length=512, verbose_name='New role')), + ('old_role', models.CharField(max_length=512, verbose_name='Old role')), + ], + options={ + 'unique_together': {('new_role', 'old_role')}, + }, + ), + ] diff --git a/apps/account/migrations/0022_auto_20191203_1149.py b/apps/account/migrations/0022_auto_20191203_1149.py new file mode 100644 index 00000000..f6b554ba --- /dev/null +++ b/apps/account/migrations/0022_auto_20191203_1149.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.7 on 2019-12-03 11:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0021_oldrole'), + ] + + operations = [ + migrations.AlterField( + model_name='oldrole', + name='old_role', + field=models.CharField(max_length=512, null=True, verbose_name='Old role'), + ), + ] diff --git a/apps/account/migrations/0023_auto_20191204_0916.py b/apps/account/migrations/0023_auto_20191204_0916.py new file mode 100644 index 00000000..68d313a0 --- /dev/null +++ b/apps/account/migrations/0023_auto_20191204_0916.py @@ -0,0 +1,22 @@ +# Generated by Django 2.2.7 on 2019-12-04 09:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0022_auto_20191203_1149'), + ] + + operations = [ + migrations.AlterField( + model_name='role', + name='role', + field=models.PositiveIntegerField(choices=[(1, 'Standard user'), (2, 'Comments moderator'), (3, 'Country admin'), (4, 'Content page manager'), (5, 'Establishment manager'), (6, 'Reviewer manager'), (7, 'Restaurant reviewer'), (8, 'Sales man'), (9, 'Winery reviewer'), (10, 'Seller')], verbose_name='Role'), + ), + migrations.AlterUniqueTogether( + name='userrole', + unique_together={('user', 'role')}, + ), + ] diff --git a/apps/account/models.py b/apps/account/models.py index 956baa56..205171d0 100644 --- a/apps/account/models.py +++ b/apps/account/models.py @@ -32,6 +32,9 @@ class Role(ProjectBaseMixin): ESTABLISHMENT_MANAGER = 5 REVIEWER_MANGER = 6 RESTAURANT_REVIEWER = 7 + SALES_MAN = 8 + WINERY_REVIEWER = 9 + SELLER = 10 ROLE_CHOICES = ( (STANDARD_USER, 'Standard user'), @@ -40,7 +43,10 @@ class Role(ProjectBaseMixin): (CONTENT_PAGE_MANAGER, 'Content page manager'), (ESTABLISHMENT_MANAGER, 'Establishment manager'), (REVIEWER_MANGER, 'Reviewer manager'), - (RESTAURANT_REVIEWER, 'Restaurant reviewer') + (RESTAURANT_REVIEWER, 'Restaurant reviewer'), + (SALES_MAN, 'Sales man'), + (WINERY_REVIEWER, 'Winery reviewer'), + (SELLER, 'Seller') ) role = models.PositiveIntegerField(verbose_name=_('Role'), choices=ROLE_CHOICES, null=False, blank=False) @@ -293,3 +299,13 @@ class UserRole(ProjectBaseMixin): role = models.ForeignKey(Role, verbose_name=_('Role'), on_delete=models.SET_NULL, null=True) establishment = models.ForeignKey(Establishment, verbose_name=_('Establishment'), on_delete=models.SET_NULL, null=True, blank=True) + class Meta: + unique_together = ['user', 'role'] + + +class OldRole(models.Model): + new_role = models.CharField(verbose_name=_('New role'), max_length=512) + old_role = models.CharField(verbose_name=_('Old role'), max_length=512, null=True) + + class Meta: + unique_together = ('new_role', 'old_role') \ No newline at end of file