Skip to content

Commit

Permalink
Fix multiple processes with migration (#52)
Browse files Browse the repository at this point in the history
* Migration to fix multiple processes

* Improvements

* Fix multiple processes migration curation by counting only distinct processes

* Migration multiple processes curation - Save version of deleted processes

* Add explanation for migration and delete flag

* Upgrade FMS version from 3.1.1 to 3.1.2
  • Loading branch information
jleblond authored May 7, 2021
1 parent 251a809 commit 99dd9c8
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 1 deletion.
2 changes: 1 addition & 1 deletion backend/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.1.1
3.1.2
83 changes: 83 additions & 0 deletions backend/fms_core/migrations/0019_v3_1_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
from django.conf import settings
from django.db import migrations
from django.contrib.auth.models import User
import reversion
import datetime

'''
This migration will fix an issue that occurred in release 3.1,
where multiple Process objects would erroneously be generated for each Sample part of a template
(i.e. Transfer, Extraction, etc.)
There should have only been one Process object created per template.
'''

ADMIN_USERNAME='biobankadmin'

def fix_process_data(apps, schema_editor):
Version = apps.get_model("reversion", "Version")
Revision = apps.get_model("reversion", "Revision")
ProcessSample = apps.get_model("fms_core", "ProcessSample")
Process = apps.get_model("fms_core", "Process")

affected_revisions_ids = Revision.objects.filter(date_created__range=["2021-04-29", "2021-05-01"]).values_list('id', flat=True)

for revision_id in affected_revisions_ids:
# Getting all ProcessSample created in this revision
list_affected_process_samples_ids = list(Version.objects.filter(content_type__model='processsample',
revision_id=revision_id).values_list('object_id', flat=True))

if len(list_affected_process_samples_ids) > 1:
process_samples = ProcessSample.objects.filter(id__in=list_affected_process_samples_ids)

# Getting all distinct Processes related to those ProcessSample
list_process_ids = list(process_samples.values_list('process_id', flat=True).distinct())

# Checks if many processes were created instead of only one
if len(list_process_ids) > 1:
# First Process; the only one that will be kept
first_process_id = min(list_process_ids)

processes_to_delete = Process.objects.filter(pk__in=list_process_ids).exclude(pk=first_process_id)

with reversion.create_revision(manage_manually=True):
reversion.set_comment("Curation of multiple processes into one process per template")
reversion.set_user(User.objects.get(username=ADMIN_USERNAME))

# Change process_id for ProcessSample now pointing to the wrong processes
for ps in process_samples:
ps.process_id = first_process_id
ps.save()
reversion.add_to_revision(ps)

# Delete Processes unused (should not have been created in first place)
for process in processes_to_delete:
process.comment = f'Deleted in curation {datetime.datetime.now().strftime("%Y-%m-%d")} v3.1.2 combined multiple processes - ' + process.comment
process.deleted = True
process.save()
reversion.add_to_revision(process)

# Update First Process for this revision batch with comment reflecting the current curation
first_process = Process.objects.get(id=first_process_id)
first_process.comment += f' - Curated {datetime.datetime.now().strftime("%Y-%m-%d")} v3.1.2 combined multiple processes'
first_process.save()
reversion.add_to_revision(first_process)


# Delete all processes to be deleted (has to be done outside of the previous Revision scope)
for process in processes_to_delete:
process.delete()


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('fms_core', '0018_v3_1_0'),
]

operations = [
migrations.RunPython(
fix_process_data,
reverse_code=migrations.RunPython.noop,
),
]

0 comments on commit 99dd9c8

Please sign in to comment.