-
Notifications
You must be signed in to change notification settings - Fork 64
ENT-11235: Updating schema to add invited_date and joined_date fields to customer admin #2524
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
sjasti-sonata-svg
wants to merge
2
commits into
openedx:master
Choose a base branch
from
sjasti-sonata-svg:feature/Update-Admintable-ENT-11235
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # Generated by Django 5.2.8 on 2026-02-08 03:59 | ||
|
|
||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ("enterprise", "0242_mariadb_uuid_conversion"), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.AddField( | ||
| model_name="enterprisecustomeradmin", | ||
| name="invited_date", | ||
| field=models.DateTimeField( | ||
| blank=True, | ||
| help_text="The date and time when the admin was invited.", | ||
| null=True, | ||
| ), | ||
| ), | ||
| migrations.AddField( | ||
| model_name="enterprisecustomeradmin", | ||
| name="joined_date", | ||
| field=models.DateTimeField( | ||
| blank=True, | ||
| help_text="The date and time when the admin joined/registered their account.", | ||
| null=True, | ||
| ), | ||
| ), | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| # Generated manually on 2026-02-08 | ||
|
|
||
| from django.db import migrations | ||
|
|
||
|
|
||
| def backfill_admin_dates(apps, schema_editor): | ||
| """ | ||
| Backfill invited_date and joined_date for existing EnterpriseCustomerAdmin records. | ||
|
|
||
| Strategy: | ||
| - Use the admin's created timestamp as invited_date (best approximation) | ||
| - Use the same timestamp as joined_date (they're already active) | ||
| - If last_login exists and is earlier than created, use it as joined_date | ||
| """ | ||
| EnterpriseCustomerAdmin = apps.get_model('enterprise', 'EnterpriseCustomerAdmin') | ||
|
|
||
| for admin in EnterpriseCustomerAdmin.objects.all(): | ||
| # Set invited_date to created timestamp if not already set | ||
| if not admin.invited_date: | ||
| admin.invited_date = admin.created | ||
|
|
||
| # Set joined_date to created timestamp (or last_login if earlier) | ||
| if not admin.joined_date: | ||
| # If they have a last_login and it's earlier than created, use it | ||
| if admin.last_login and admin.last_login < admin.created: | ||
| admin.joined_date = admin.last_login | ||
| else: | ||
| admin.joined_date = admin.created | ||
|
|
||
| admin.save(update_fields=['invited_date', 'joined_date']) | ||
|
|
||
|
|
||
| def reverse_backfill(apps, schema_editor): | ||
| """ | ||
| Reverse migration - clear the backfilled data. | ||
| """ | ||
| EnterpriseCustomerAdmin = apps.get_model('enterprise', 'EnterpriseCustomerAdmin') | ||
| EnterpriseCustomerAdmin.objects.all().update( | ||
| invited_date=None, | ||
| joined_date=None | ||
| ) | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ('enterprise', '0243_add_admin_invite_join_dates'), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.RunPython( | ||
| backfill_admin_dates, | ||
| reverse_backfill | ||
| ), | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| # Generated manually on 2026-02-08 | ||
|
|
||
| from django.db import connection, migrations, models | ||
|
|
||
|
|
||
| def is_sqlite(): | ||
| """Check if the database backend is SQLite.""" | ||
| return connection.vendor == 'sqlite' | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ('enterprise', '0244_backfill_admin_dates'), | ||
| ] | ||
|
|
||
| operations = [ | ||
| # Only apply the AlterField operation if not using SQLite | ||
| # SQLite has issues with ALTER TABLE when views exist | ||
| # In production (MySQL/PostgreSQL), this will make the field non-nullable | ||
| # In development (SQLite), the model definition enforces the constraint | ||
| ] | ||
|
|
||
| # Conditionally add the operation based on database backend | ||
| if not is_sqlite(): | ||
| operations.append( | ||
| migrations.AlterField( | ||
| model_name='enterprisecustomeradmin', | ||
| name='invited_date', | ||
| field=models.DateTimeField( | ||
| blank=False, | ||
| null=False, | ||
| help_text='The date and time when the admin was invited.' | ||
| ), | ||
| ) | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| """ | ||
| Quick test script to verify admin date fields are working correctly. | ||
| Run with: python manage.py test test_admin_dates --settings=test_settings | ||
| """ | ||
| from django.test import TestCase | ||
| from django.utils import timezone | ||
| from enterprise.models import EnterpriseCustomerAdmin | ||
| from test_utils import factories | ||
|
|
||
|
|
||
| class TestAdminDatesImplementation(TestCase): | ||
| """Test that invited_date and joined_date work correctly.""" | ||
|
|
||
| def test_admin_dates_fields_exist(self): | ||
| """Test that the new date fields exist on the model.""" | ||
| user = factories.UserFactory() | ||
| enterprise_customer = factories.EnterpriseCustomerFactory() | ||
| enterprise_customer_user = factories.EnterpriseCustomerUserFactory( | ||
| user_id=user.id, | ||
| enterprise_customer=enterprise_customer | ||
| ) | ||
|
|
||
| # Create admin with explicit dates | ||
| now = timezone.now() | ||
| admin = EnterpriseCustomerAdmin.objects.create( | ||
| enterprise_customer_user=enterprise_customer_user, | ||
| invited_date=now, | ||
| joined_date=now | ||
| ) | ||
|
|
||
| # Verify fields are set | ||
| self.assertIsNotNone(admin.invited_date) | ||
| self.assertIsNotNone(admin.joined_date) | ||
| self.assertEqual(admin.invited_date, now) | ||
| self.assertEqual(admin.joined_date, now) | ||
| print("Test passed: Admin date fields are working correctly!") | ||
|
|
||
| def test_invited_date_required(self): | ||
| """Test that invited_date is required.""" | ||
| user = factories.UserFactory() | ||
| enterprise_customer = factories.EnterpriseCustomerFactory() | ||
| enterprise_customer_user = factories.EnterpriseCustomerUserFactory( | ||
| user_id=user.id, | ||
| enterprise_customer=enterprise_customer | ||
| ) | ||
|
|
||
| # Try to create admin without invited_date - should fail | ||
| from django.db import IntegrityError | ||
| with self.assertRaises((IntegrityError, ValueError)): | ||
| EnterpriseCustomerAdmin.objects.create( | ||
| enterprise_customer_user=enterprise_customer_user, | ||
| joined_date=timezone.now() | ||
| # invited_date is missing - should fail | ||
| ) | ||
| print("Test passed: invited_date is required!") | ||
|
|
||
| def test_joined_date_can_be_null(self): | ||
| """Test that joined_date can be null.""" | ||
| user = factories.UserFactory() | ||
| enterprise_customer = factories.EnterpriseCustomerFactory() | ||
| enterprise_customer_user = factories.EnterpriseCustomerUserFactory( | ||
| user_id=user.id, | ||
| enterprise_customer=enterprise_customer | ||
| ) | ||
|
|
||
| # Create admin with null joined_date | ||
| admin = EnterpriseCustomerAdmin.objects.create( | ||
| enterprise_customer_user=enterprise_customer_user, | ||
| invited_date=timezone.now(), | ||
| joined_date=None # Should be allowed | ||
| ) | ||
|
|
||
| self.assertIsNone(admin.joined_date) | ||
| print("Test passed: joined_date can be null!") |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
joined_dateis redundant withcreated. Remove thejoined_datefield.