diff --git a/src/registrar/models/domain.py b/src/registrar/models/domain.py index 6c94bd8d7..7feeb820d 100644 --- a/src/registrar/models/domain.py +++ b/src/registrar/models/domain.py @@ -201,6 +201,14 @@ class Domain(TimeStampedModel, DomainHelper): """Get the `cr_date` element from the registry.""" return self._get_property("cr_date") + @creation_date.setter # type: ignore + def creation_date(self, ex_date: date): + """ + Direct setting of the creation date in the registry is not implemented. + + Creation date can only be set by registry.""" + raise NotImplementedError() + @Cache def last_transferred_date(self) -> date: """Get the `tr_date` element from the registry.""" @@ -969,11 +977,11 @@ class Domain(TimeStampedModel, DomainHelper): Check if the domain's expiration date is in the past. Returns True if expired, False otherwise. """ - if not self.expiration_date: + if self.expiration_date is None: return True now = timezone.now().date() return self.expiration_date < now - + def map_epp_contact_to_public_contact(self, contact: eppInfo.InfoContactResultData, contact_id, contact_type): """Maps the Epp contact representation to a PublicContact object. @@ -1620,10 +1628,22 @@ class Domain(TimeStampedModel, DomainHelper): if old_cache_contacts is not None: cleaned["contacts"] = old_cache_contacts + requires_save = False + # if expiration date from registry does not match what is in db, # update the db if "ex_date" in cleaned and cleaned["ex_date"] != self.expiration_date: self.expiration_date = cleaned["ex_date"] + requires_save = True + + # if creation_date from registry does not match what is in db, + # update the db + if "cr_date" in cleaned and cleaned["cr_date"] != self.created_at: + self.created_at = cleaned["cr_date"] + requires_save = True + + # if either registration date or creation date need updating + if requires_save: self.save() self._cache = cleaned diff --git a/src/registrar/tests/test_models_domain.py b/src/registrar/tests/test_models_domain.py index 39f63c942..2f54d7794 100644 --- a/src/registrar/tests/test_models_domain.py +++ b/src/registrar/tests/test_models_domain.py @@ -1962,6 +1962,9 @@ class TestExpirationDate(MockEppLib): """ super().setUp() # for the tests, need a domain in the ready state + # mock data for self.domain includes the following dates: + # cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35) + # ex_date=datetime.date(2023, 5, 25) self.domain, _ = Domain.objects.get_or_create(name="fake.gov", state=Domain.State.READY) # for the test, need a domain that will raise an exception self.domain_w_error, _ = Domain.objects.get_or_create(name="fake-error.gov", state=Domain.State.READY) @@ -1987,6 +1990,23 @@ class TestExpirationDate(MockEppLib): with self.assertRaises(RegistryError): self.domain_w_error.renew_domain() + def test_is_expired(self): + """assert that is_expired returns true for expiration_date in past""" + # force fetch_cache to be called + self.domain.statuses + self.assertTrue(self.domain.is_expired) + + def test_is_not_expired(self): + """assert that is_expired returns false for expiration in future""" + # to do this, need to mock value returned from timezone.now + # set now to 2023-01-01 + mocked_datetime = datetime.datetime(2023, 1, 1, 12, 0, 0) + # force fetch_cache which sets the expiration date to 2023-05-25 + self.domain.statuses + + with patch("registrar.models.domain.timezone.now", return_value=mocked_datetime): + self.assertFalse(self.domain.is_expired()) + def test_expiration_date_updated_on_info_domain_call(self): """assert that expiration date in db is updated on info domain call""" # force fetch_cache to be called @@ -1995,6 +2015,36 @@ class TestExpirationDate(MockEppLib): self.assertEquals(self.domain.expiration_date, test_date) +class TestCreationDate(MockEppLib): + """Created_at in domain model is updated from EPP""" + + def setUp(self): + """ + Domain exists in registry + """ + super().setUp() + # for the tests, need a domain with a creation date + self.domain, _ = Domain.objects.get_or_create(name="fake.gov", state=Domain.State.READY) + # creation_date returned from mockDataInfoDomain with creation date: + # cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35) + self.creation_date = datetime.datetime(2023, 5, 25, 19, 45, 35) + + def tearDown(self): + Domain.objects.all().delete() + super().tearDown() + + def test_creation_date_setter_not_implemented(self): + """assert that the setter for creation date is not implemented and will raise error""" + with self.assertRaises(NotImplementedError): + self.domain.creation_date = datetime.date.today() + + def test_creation_date_updated_on_info_domain_call(self): + """assert that creation date in db is updated on info domain call""" + # force fetch_cache to be called + self.domain.statuses + self.assertEquals(self.domain.created_at, self.creation_date) + + class TestAnalystClientHold(MockEppLib): """Rule: Analysts may suspend or restore a domain by using client hold"""