Skip to content

Commit

Permalink
chore: migration script to set Reg1 operation statuses to draft; exce…
Browse files Browse the repository at this point in the history
…pt for Declined operations which get archived
  • Loading branch information
andrea-williams committed Feb 25, 2025
1 parent de822ad commit 95b3f55
Showing 1 changed file with 111 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Generated by Django 5.0.11 on 2025-02-25 01:37

from django.db import migrations
from typing import Dict
import datetime
import uuid

"""
One-time forward-only migration to be applied to prod data.
Purpose: set the `status` field of Operations (created in Reg1) to match the statuses used in Administration/Registration2 modules.
Also archives operations with a "Declined" status (only 1 as of Feb 19, 2025)
Reg1 Status | Reg2 Status
-------------------+-------------------
PENDING | DRAFT
APPROVED | DRAFT
CHANGES_REQUESTED | DRAFT
NOT_STARTED | NOT_STARTED
DRAFT | DRAFT
DECLINED | Archive the operation
"""


def count_stats(Operation) -> Dict[str, int]:
total = Operation.objects.count()
declined = Operation.objects.filter(status="Declined").count()
approved = Operation.objects.filter(status="Approved").count()
not_started = Operation.objects.filter(status="Not Started").count()
draft = Operation.objects.filter(status="Draft").count()
changes_requested = Operation.objects.filter(status="Changes Requested").count()
pending = Operation.objects.filter(status="Pending").count()
registered = Operation.objects.filter(status="Registered").count()
return {
'total': total,
'declined': declined,
'approved': approved,
'not_started': not_started,
'draft': draft,
'changes_requested': changes_requested,
'pending': pending,
'registered': registered,
}


def migrate_reg1_operation_statuses(apps, schema_monitor):
# import the required Django model
Operation = apps.get_model('registration', 'Operation')
User = apps.get_model('registration', 'User')

before_stats = count_stats(Operation)
declined_operations_before = Operation.objects.filter(status="Declined")
print("\n\n\nDeclined operations - before migration:")
for op in declined_operations_before:
print(f'{op.id}: archived_by_id={op.archived_by_id}, archived_at={op.archived_at}')

pending_operations_updated = Operation.objects.filter(status="Pending").update(status="Draft")
approved_operations_updated = Operation.objects.filter(status="Approved").update(status="Draft")
changes_requested_operations_updated = Operation.objects.filter(status="Changes Requested").update(status="Draft")
filtered_users = User.objects.filter(first_name="Patricia", last_name="Russell")

assert filtered_users.count() == 1
po_user = filtered_users.first()

declined_operations_archived = Operation.objects.filter(status="Declined").update(
archived_by_id=po_user.user_guid, archived_at=datetime.datetime.now(datetime.timezone.utc)
) # declined operations will be archived, per PR's instruction and using her user GUID
after_stats = count_stats(Operation)
declined_operations_after = Operation.objects.filter(status="Declined")
updates = {
'pending_ops_updated': pending_operations_updated,
'approved_ops_updated': approved_operations_updated,
'changes_requested_ops_updated': changes_requested_operations_updated,
'declined_operations_archived': declined_operations_archived,
}
assertions(before_stats, after_stats, updates, declined_operations_after)


def assertions(before_stats, after_stats, updates, declined_operations_after):
print("\n\n\n*** BEFORE MIGRATION ***")
print(before_stats)
print("*** AFTER MIGRATION ***")
print(after_stats)
print("*** UPDATES ***")
print(updates)
print("\n\n\n")
# assert that the total number of operations does not change before and after the migration is applied
assert before_stats.get('total') == after_stats.get('total')
# assert that there are no more operations with a status of "Pending", "Approved", or "Changes Requested"
assert after_stats.get('pending') == 0
assert after_stats.get('approved') == 0
assert after_stats.get('changes_requested') == 0
# assert that the number of Declined operations before is the same as after the migration is applied
assert before_stats.get('declined') == after_stats.get('declined')
print("\n\n\nDeclined operations - after migration:")
for op in declined_operations_after:
print(f'{op.id}: archived_by_id={op.archived_by_id}, archived_at={op.archived_at}')
# assert that the Declined operations are marked as archived after the migration
for op in declined_operations_after:
assert op.archived_at is not None
assert op.archived_by_id == uuid.UUID('c3bc1b69-15de-44ac-b03b-982bf3163406')
# assert that the number of "Not Started" operations remains the same
assert before_stats.get('not_started') == after_stats.get('not_started')
# assert that the number of "Registered" operations is zero both before and after the migration is applied
assert before_stats.get('registered') == 0
assert after_stats.get('registered') == 0


class Migration(migrations.Migration):
dependencies = [
('registration', '0078_V1_22_0'),
]
operations = [migrations.RunPython(migrate_reg1_operation_statuses, migrations.RunPython.noop, elidable=True)]

0 comments on commit 95b3f55

Please sign in to comment.