refactor: migrate to question sets for person qs

This means we're starting to use the same system for person questions
as for relationship questions
This commit is contained in:
James Graham
2020-11-26 12:59:30 +00:00
parent a94db2713e
commit 5035b121a6
8 changed files with 304 additions and 31 deletions

View File

@@ -0,0 +1,55 @@
# Generated by Django 2.2.10 on 2020-11-23 14:29
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('people', '0021_refactor_person_disciplines'),
]
operations = [
migrations.CreateModel(
name='PersonQuestion',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('version', models.PositiveSmallIntegerField(default=1)),
('text', models.CharField(max_length=255)),
('order', models.SmallIntegerField(default=0)),
],
options={
'ordering': ['order', 'text'],
},
),
migrations.CreateModel(
name='PersonQuestionChoice',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('text', models.CharField(max_length=255)),
('order', models.SmallIntegerField(default=0)),
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='people.PersonQuestion')),
],
options={
'ordering': ['question__order', 'order', 'text'],
},
),
migrations.CreateModel(
name='PersonAnswerSet',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('timestamp', models.DateTimeField(auto_now_add=True)),
('replaced_timestamp', models.DateTimeField(blank=True, editable=False, null=True)),
('person', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answer_sets', to='people.Person')),
('question_answers', models.ManyToManyField(to='people.PersonQuestionChoice')),
],
options={
'ordering': ['timestamp'],
},
),
migrations.AddConstraint(
model_name='personquestionchoice',
constraint=models.UniqueConstraint(fields=('question', 'text'), name='unique_question_answer'),
),
]

View File

@@ -0,0 +1,65 @@
# Generated by Django 2.2.10 on 2020-11-25 15:50
from django.core.exceptions import ObjectDoesNotExist
from django.db import migrations
from django.utils import timezone
from .utils.question_sets import port_question
def migrate_forward(apps, schema_editor):
Person = apps.get_model('people', 'Person')
Role = apps.get_model('people', 'Role')
role_question = port_question(apps, 'Role',
Role.objects.values_list('name', flat=True))
for person in Person.objects.all():
try:
prev_set = person.answer_sets.latest('timestamp')
except ObjectDoesNotExist:
prev_set = None
try:
answer_set = person.answer_sets.create()
answer_set.question_answers.add(
role_question.answers.get(text=person.role.name))
prev_set.replaced_timestamp = timezone.datetime.now()
except AttributeError:
pass
def migrate_backward(apps, schema_editor):
Person = apps.get_model('people', 'Person')
Role = apps.get_model('people', 'Role')
for person in Person.objects.all():
try:
current_answers = person.answer_sets.latest('timestamp')
role_answer = current_answers.question_answers.get(
question__text='Role')
person.role, _ = Role.objects.get_or_create(name=role_answer.text)
person.save()
except ObjectDoesNotExist:
pass
class Migration(migrations.Migration):
dependencies = [
('people', '0022_refactor_person_questions'),
]
operations = [
migrations.RunPython(migrate_forward, migrate_backward),
migrations.RemoveField(
model_name='person',
name='role',
),
migrations.DeleteModel('Role'),
]

View File

View File

@@ -0,0 +1,23 @@
import typing
from django.core.exceptions import ObjectDoesNotExist
def port_question(apps, question_text: str,
answers_text: typing.Iterable[str]):
PersonQuestion = apps.get_model('people', 'PersonQuestion')
try:
prev_question = PersonQuestion.objects.filter(
text=question_text).latest('version')
question = PersonQuestion.objects.create(
text=question_text, version=prev_question.version + 1)
except ObjectDoesNotExist:
question = PersonQuestion.objects.create(text=question_text)
for answer_text in answers_text:
question.answers.get_or_create(text=answer_text)
return question