diff --git a/src/registrar/migrations/0057_domain_deleted_at_domain_ready_at.py b/src/registrar/migrations/0057_domain_deleted_at_domain_first_ready_at.py similarity index 88% rename from src/registrar/migrations/0057_domain_deleted_at_domain_ready_at.py rename to src/registrar/migrations/0057_domain_deleted_at_domain_first_ready_at.py index 400fddc3a..77c565886 100644 --- a/src/registrar/migrations/0057_domain_deleted_at_domain_ready_at.py +++ b/src/registrar/migrations/0057_domain_deleted_at_domain_first_ready_at.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.7 on 2023-12-21 17:12 +# Generated by Django 4.2.7 on 2023-12-21 19:28 from django.db import migrations, models @@ -16,7 +16,7 @@ class Migration(migrations.Migration): ), migrations.AddField( model_name="domain", - name="ready_at", + name="first_ready_at", field=models.DateField( editable=False, help_text="The last time this domain moved into the READY state", null=True ), diff --git a/src/registrar/models/domain.py b/src/registrar/models/domain.py index 1c9a9f1ad..e02978937 100644 --- a/src/registrar/models/domain.py +++ b/src/registrar/models/domain.py @@ -967,7 +967,7 @@ class Domain(TimeStampedModel, DomainHelper): help_text="Deleted at date", ) - ready_at = DateField( + first_ready_at = DateField( null=True, editable=False, help_text="The last time this domain moved into the READY state", @@ -1336,7 +1336,11 @@ class Domain(TimeStampedModel, DomainHelper): """ logger.info("Changing to ready state") logger.info("able to transition to ready state") - self.ready_at = timezone.now() + # if self.first_ready_at is not None, this means that his + # domain wasr READY, then not READY, then is READY again. + # We do not want to overwrite first_ready_at. + if self.first_ready_at is None: + self.first_ready_at = timezone.now() @transition( field="state", diff --git a/src/registrar/tests/test_models_domain.py b/src/registrar/tests/test_models_domain.py index c84001569..95f8ca2a5 100644 --- a/src/registrar/tests/test_models_domain.py +++ b/src/registrar/tests/test_models_domain.py @@ -385,6 +385,34 @@ class TestDomainStatuses(MockEppLib): """Domain 'revert_client_hold' method causes the registry to change statuses""" raise + def test_first_ready_at(self): + """ + first_ready_at is set when a domain is first transitioned to READY. It does not get overwritten + in case the domain gets out of and back into READY. + """ + domain, _ = Domain.objects.get_or_create(name="pig-knuckles.gov", state=Domain.State.DNS_NEEDED) + self.assertEqual(domain.first_ready_at, None) + + domain.ready() + + # check that status is READY + self.assertTrue(domain.is_active()) + self.assertNotEqual(domain.first_ready_at, None) + + # Capture the value of first_ready_at + first_ready_at = domain.first_ready_at + + # change domain status + domain.dns_needed() + self.assertFalse(domain.is_active()) + + # change back to READY + domain.ready() + self.assertTrue(domain.is_active()) + + # assert that the value of first_ready_at has not changed + self.assertEqual(domain.first_ready_at, first_ready_at) + def tearDown(self) -> None: PublicContact.objects.all().delete() Domain.objects.all().delete() @@ -1112,7 +1140,7 @@ class TestRegistrantNameservers(MockEppLib): Then `commands.CreateHost` and `commands.UpdateDomain` is sent to the registry And `domain.is_active` returns False - And domain.ready_at is null + And domain.first_ready_at is null """ # set 1 nameserver @@ -1139,7 +1167,7 @@ class TestRegistrantNameservers(MockEppLib): # as you have less than 2 nameservers self.assertFalse(self.domain.is_active()) - self.assertEqual(self.domain.ready_at, None) + self.assertEqual(self.domain.first_ready_at, None) def test_user_adds_two_nameservers(self): """ @@ -1149,7 +1177,7 @@ class TestRegistrantNameservers(MockEppLib): Then `commands.CreateHost` and `commands.UpdateDomain` is sent to the registry And `domain.is_active` returns True - And domain.ready_at is not null + And domain.first_ready_at is not null """ # set 2 nameservers @@ -1180,7 +1208,7 @@ class TestRegistrantNameservers(MockEppLib): self.assertEqual(4, self.mockedSendFunction.call_count) # check that status is READY self.assertTrue(self.domain.is_active()) - self.assertNotEqual(self.domain.ready_at, None) + self.assertNotEqual(self.domain.first_ready_at, None) def test_user_adds_too_many_nameservers(self): """