Skip to content

Commit

Permalink
Use LeafGroup
Browse files Browse the repository at this point in the history
- DB Migration reset
- Update load_dummy_data
- Update test cases
  • Loading branch information
thenav56 committed Sep 1, 2023
1 parent b74c7f5 commit a53b51f
Show file tree
Hide file tree
Showing 29 changed files with 1,507 additions and 684 deletions.
91 changes: 66 additions & 25 deletions apps/common/management/commands/load_dummy_data.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import random

from django.core.management.base import BaseCommand
from django.db import transaction
from django.conf import settings

from apps.user.models import User
from apps.user.factories import UserFactory
from apps.project.models import Project, ProjectMembership
from apps.project.factories import ProjectFactory
from apps.questionnaire.models import Question
from apps.questionnaire.models import Question, Questionnaire, QuestionLeafGroup
from apps.questionnaire.factories import (
QuestionnaireFactory,
QuestionGroupFactory,
QuestionLeafGroupFactory,
QuestionFactory,
ChoiceCollectionFactory,
ChoiceFactory,
Expand All @@ -18,7 +21,18 @@
class Command(BaseCommand):
help = 'Load dummy data'

def create_superuser(self):
def add_arguments(self, parser):
parser.add_argument(
'--delete-all',
dest='DELETE_ALL',
action='store_true',
default=False,
)

def get_or_create_superuser(self):
user = User.objects.filter(email='[email protected]').first()
if user:
return user
user = UserFactory.create(
email='[email protected]',
password_text='admin123',
Expand All @@ -29,13 +43,7 @@ def create_superuser(self):
self.stdout.write(f'Added user with credentials: {user.email}:{user.password_text}')
return user

def process_questionnare(self, questionnaire):
# Groups
group1, group2, _ = QuestionGroupFactory.create_batch(
3,
**self.user_resource_params,
questionnaire=questionnaire,
)
def process_questionnare(self, questionnaire: Questionnaire):
# Choices
# -- Collection
choice_collection_1, choice_collection_2, choice_collection_3 = ChoiceCollectionFactory.create_batch(
Expand All @@ -47,19 +55,38 @@ def process_questionnare(self, questionnaire):
ChoiceFactory.create_batch(10, collection=choice_collection_1)
ChoiceFactory.create_batch(5, collection=choice_collection_2)
ChoiceFactory.create_batch(7, collection=choice_collection_3)

# Questions
# -- No group
question_params = {
**self.user_resource_params,
'type': Question.Type.INTEGER,
'questionnaire': questionnaire,
group_categories = QuestionLeafGroupFactory.random_category_generator(100)
group_order_by_type = {
QuestionLeafGroup.Type.MATRIX_1D: 100,
QuestionLeafGroup.Type.MATRIX_2D: 200,
}
QuestionFactory.create_batch(5, **question_params)
# -- Group 1
QuestionFactory.create_batch(3, **question_params, group=group1)
# -- Group 2
QuestionFactory.create_batch(2, **question_params, group=group2, choice_collection=choice_collection_1)
QuestionFactory.create_batch(2, **question_params, group=group2, choice_collection=choice_collection_2)
for _type, *categories in group_categories:
# Group
group = QuestionLeafGroupFactory.create(
questionnaire=questionnaire,
type=_type,
category_1=categories[0],
category_2=categories[1],
category_3=categories[2],
category_4=categories[3],
order=group_order_by_type[_type],
**self.user_resource_params,
)
group_order_by_type[_type] += 1
# Questions
question_params = {
**self.user_resource_params,
'type': Question.Type.INTEGER,
'questionnaire': questionnaire,
'leaf_group': group,
}
# Without choices
QuestionFactory.create_batch(random.randrange(4, 10), **question_params)
# With choices
QuestionFactory.create_batch(random.randrange(1, 3), **question_params, choice_collection=choice_collection_2)
QuestionFactory.create_batch(random.randrange(1, 4), **question_params, choice_collection=choice_collection_1)

def process_project(
self,
Expand All @@ -77,13 +104,28 @@ def process_project(
self.process_questionnare(questionnaire)

@transaction.atomic
def handle(self, **_):
user = self.create_superuser() # Main user
UserFactory.create_batch(10) # Other users
def handle(self, **kwargs):
if not (settings.DEBUG and settings.ALLOW_DUMMY_DATA_SCRIPT):
self.stdout.write(
self.style.ERROR(
'You need to enable DEBUG & ALLOW_DUMMY_DATA_SCRIPT to use this'
)
)
return

user = self.get_or_create_superuser() # Main user
self.user_resource_params = {
'created_by': user,
'modified_by': user,
}
if not User.objects.exclude(pk=user.pk).exists():
UserFactory.create_batch(10) # Other users

if kwargs.get('DELETE_ALL', False):
self.stdout.write(self.style.WARNING('Removing existing Data'))
Question.objects.all().delete()
Project.objects.all().delete()

projects = ProjectFactory.create_batch(10, **self.user_resource_params)
total_projects = len(projects)
self.stdout.write(f'Created {total_projects} projects')
Expand All @@ -103,7 +145,6 @@ def handle(self, **_):
role,
)

# raise Exception('NOOOP')
self.stdout.write(
self.style.SUCCESS('Loaded sucessfully')
)
5 changes: 3 additions & 2 deletions apps/project/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 4.2.1 on 2023-06-07 10:35
# Generated by Django 4.2.1 on 2023-08-29 08:10

from django.db import migrations, models

Expand All @@ -18,6 +18,7 @@ class Migration(migrations.Migration):
('created_at', models.DateTimeField(auto_now_add=True)),
('modified_at', models.DateTimeField(auto_now=True)),
('title', models.CharField(max_length=255)),
('description', models.TextField(blank=True)),
],
options={
'ordering': ['-id'],
Expand All @@ -28,7 +29,7 @@ class Migration(migrations.Migration):
name='ProjectMembership',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('role', models.PositiveSmallIntegerField(choices=[(0, 'Admin'), (1, 'Member')], default=1)),
('role', models.PositiveSmallIntegerField(choices=[(1, 'Admin'), (2, 'Member'), (3, 'Viewer')], default=2)),
('joined_at', models.DateTimeField(auto_now_add=True)),
],
),
Expand Down
4 changes: 2 additions & 2 deletions apps/project/migrations/0002_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 4.2.1 on 2023-06-07 10:35
# Generated by Django 4.2.1 on 2023-08-29 08:10

from django.conf import settings
from django.db import migrations, models
Expand All @@ -10,8 +10,8 @@ class Migration(migrations.Migration):
initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('project', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
Expand Down
18 changes: 0 additions & 18 deletions apps/project/migrations/0003_project_description.py

This file was deleted.

18 changes: 0 additions & 18 deletions apps/project/migrations/0004_alter_projectmembership_role.py

This file was deleted.

5 changes: 5 additions & 0 deletions apps/qbank/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.apps import AppConfig


class QuestionBankConfig(AppConfig):
name = "apps.qbank"
50 changes: 50 additions & 0 deletions apps/qbank/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from django.db import models

from apps.common.models import UserResource
from apps.questionnaire.models import (
ChoiceCollection,
Choice,
QuestionGroup,
Question,
)


class QuestionBank(UserResource):
title = models.CharField(max_length=255)
is_draft = models.BooleanField(default=True)


class QBChoiceCollection(ChoiceCollection):
questionnaire = None
qbank = models.ForeignKey(QuestionBank, on_delete=models.CASCADE)
choice_set: models.QuerySet['QBChoice']

class Meta:
unique_together = ('qbank', 'name')


class QBChoice(Choice):
collection = models.ForeignKey(QBChoiceCollection, on_delete=models.CASCADE)

class Meta:
unique_together = ('collection', 'name')


class QBGroup(QuestionGroup):
questionnaire = None
qbank = models.ForeignKey(QuestionBank, on_delete=models.CASCADE)

class Meta:
unique_together = ('qbank', 'name')


class QBQuestion(Question):
questionnaire = None
qbank = models.ForeignKey(QuestionBank, on_delete=models.CASCADE)
group = models.ForeignKey(QBGroup, on_delete=models.CASCADE, null=True, blank=True)
choice_collection = models.ForeignKey(
QBChoiceCollection,
on_delete=models.PROTECT,
blank=True,
null=True,
)
29 changes: 28 additions & 1 deletion apps/questionnaire/admin.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from django.contrib import admin
from admin_auto_filters.filters import AutocompleteFilterFactory

from .models import Questionnaire, Question
from .models import (
Questionnaire,
Question,
QuestionLeafGroup,
)


@admin.register(Questionnaire)
Expand All @@ -27,3 +31,26 @@ class QuestionAdmin(admin.ModelAdmin):
list_filter = (
AutocompleteFilterFactory('Questionnaire', 'questionnaire'),
)


@admin.register(QuestionLeafGroup)
class QuestionLeafGroupAdmin(admin.ModelAdmin):
search_fields = ('title',)
list_display = (
'name',
'order',
'type',
'category_1',
'category_2',
'category_3',
'category_4',
'relevant',
)
list_filter = (
AutocompleteFilterFactory('Questionnaire', 'questionnaire'),
'type',
'category_1',
'category_2',
'category_3',
'category_4',
)
20 changes: 19 additions & 1 deletion apps/questionnaire/enums.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,34 @@
import strawberry
from enum import Enum, auto

from utils.strawberry.enums import get_enum_name_from_django_field

from .models import Question
from .models import Question, QuestionLeafGroup


QuestionTypeEnum = strawberry.enum(Question.Type, name='QuestionTypeEnum')
QuestionLeafGroupTypeEnum = strawberry.enum(QuestionLeafGroup.Type, name='QuestionLeafGroupTypeEnum')
QuestionLeafGroupCategory1TypeEnum = strawberry.enum(QuestionLeafGroup.Category1, name='QuestionLeafGroupCategory1TypeEnum')
QuestionLeafGroupCategory2TypeEnum = strawberry.enum(QuestionLeafGroup.Category2, name='QuestionLeafGroupCategory2TypeEnum')
QuestionLeafGroupCategory3TypeEnum = strawberry.enum(QuestionLeafGroup.Category3, name='QuestionLeafGroupCategory3TypeEnum')
QuestionLeafGroupCategory4TypeEnum = strawberry.enum(QuestionLeafGroup.Category4, name='QuestionLeafGroupCategory4TypeEnum')


enum_map = {
get_enum_name_from_django_field(field): enum
for field, enum in (
(Question.type, QuestionTypeEnum),
# QuestionLeafGroup
(QuestionLeafGroup.type, QuestionLeafGroupTypeEnum),
(QuestionLeafGroup.category_1, QuestionLeafGroupCategory1TypeEnum),
(QuestionLeafGroup.category_2, QuestionLeafGroupCategory2TypeEnum),
(QuestionLeafGroup.category_3, QuestionLeafGroupCategory3TypeEnum),
(QuestionLeafGroup.category_4, QuestionLeafGroupCategory4TypeEnum),
)
}


@strawberry.enum
class QuestionLeafGroupVisibilityActionEnum(Enum):
SHOW = auto(), 'Show'
HIDE = auto(), 'Hide'
Loading

0 comments on commit a53b51f

Please sign in to comment.