From 7f3dbfb62f738a18043834c1fa0f1201195939c0 Mon Sep 17 00:00:00 2001 From: Ben McIlwain Date: Fri, 8 May 2020 21:51:20 -0400 Subject: [PATCH] Reflect refunded billing events on deletion in expiration time (#579) * Reflect refunded billing events on deletion in expiration time This doesn't make any change at the time of the domain deletion itself, but it will matter if the domain is then undeleted, because we need to know what expiration date to restore, and if there were any renew or autorenew charges that were refunded by the deletion because they were in a grace period, they shouldn't be coming back during the restore. * Add tests for new expiration date behavior * Add handling of add/renew grace period overlap --- .../flows/domain/DomainDeleteFlow.java | 31 +- .../flows/EppLifecycleDomainTest.java | 309 +++++++++++++++++- .../google/registry/flows/EppTestCase.java | 51 ++- .../flows/domain/DomainDeleteFlowTest.java | 4 +- .../registry/tools/EppLifecycleToolsTest.java | 6 +- ...omain_info_response_addperiod_wildcard.xml | 35 ++ .../domain_info_response_graceperiod.xml | 37 +++ ...nfo_response_graceperiod_add_and_renew.xml | 38 +++ ...nfo_response_redemptionperiod_wildcard.xml | 38 +++ 9 files changed, 523 insertions(+), 26 deletions(-) create mode 100644 core/src/test/resources/google/registry/flows/domain_info_response_addperiod_wildcard.xml create mode 100644 core/src/test/resources/google/registry/flows/domain_info_response_graceperiod.xml create mode 100644 core/src/test/resources/google/registry/flows/domain_info_response_graceperiod_add_and_renew.xml create mode 100644 core/src/test/resources/google/registry/flows/domain_info_response_redemptionperiod_wildcard.xml diff --git a/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java b/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java index 730a9827f..5f4375d94 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java @@ -212,6 +212,28 @@ public final class DomainDeleteFlow implements TransactionalFlow { builder.setDeletePollMessage(Key.create(deletePollMessage)); } + // Cancel any grace periods that were still active, and set the expiration time accordingly. + DateTime newExpirationTime = existingDomain.getRegistrationExpirationTime(); + for (GracePeriod gracePeriod : existingDomain.getGracePeriods()) { + // No cancellation is written if the grace period was not for a billable event. + if (gracePeriod.hasBillingEvent()) { + entitiesToSave.add( + BillingEvent.Cancellation.forGracePeriod(gracePeriod, historyEntry, targetId)); + if (gracePeriod.getOneTimeBillingEvent() != null) { + // Take the amount of amount of registration time being refunded off the expiration time. + // This can be either add grace periods or renew grace periods. + BillingEvent.OneTime oneTime = + ofy().load().key(gracePeriod.getOneTimeBillingEvent()).now(); + newExpirationTime = newExpirationTime.minusYears(oneTime.getPeriodYears()); + } else if (gracePeriod.getRecurringBillingEvent() != null) { + // Take 1 year off the registration if in the autorenew grace period (no need to load the + // recurring billing event; all autorenews are for 1 year). + newExpirationTime = newExpirationTime.minusYears(1); + } + } + } + builder.setRegistrationExpirationTime(newExpirationTime); + DomainBase newDomain = builder.build(); updateForeignKeyIndexDeletionTime(newDomain); handlePendingTransferOnDelete(existingDomain, newDomain, now, historyEntry); @@ -221,14 +243,7 @@ public final class DomainDeleteFlow implements TransactionalFlow { // event and poll message will already have been deleted in // ResourceDeleteFlow since it's listed in serverApproveEntities. dnsQueue.addDomainRefreshTask(existingDomain.getFullyQualifiedDomainName()); - // Cancel any grace periods that were still active. - for (GracePeriod gracePeriod : existingDomain.getGracePeriods()) { - // No cancellation is written if the grace period was not for a billable event. - if (gracePeriod.hasBillingEvent()) { - entitiesToSave.add( - BillingEvent.Cancellation.forGracePeriod(gracePeriod, historyEntry, targetId)); - } - } + entitiesToSave.add(newDomain, historyEntry); EntityChanges entityChanges = flowCustomLogic.beforeSave( BeforeSaveParameters.newBuilder() diff --git a/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java b/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java index 17d0afa95..614751a5e 100644 --- a/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java +++ b/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java @@ -18,6 +18,7 @@ import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.model.eppoutput.Result.Code.SUCCESS; import static google.registry.model.eppoutput.Result.Code.SUCCESS_AND_CLOSE; import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING; +import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.registry.Registry.TldState.GENERAL_AVAILABILITY; import static google.registry.model.registry.Registry.TldState.PREDELEGATION; import static google.registry.model.registry.Registry.TldState.START_DATE_SUNRISE; @@ -26,6 +27,7 @@ import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.createTlds; import static google.registry.testing.DatastoreHelper.getOnlyHistoryEntryOfType; import static google.registry.testing.DatastoreHelper.persistResource; +import static google.registry.testing.DomainBaseSubject.assertAboutDomains; import static google.registry.testing.EppMetricSubject.assertThat; import static google.registry.util.DateTimeUtils.START_OF_TIME; import static org.joda.money.CurrencyUnit.USD; @@ -84,19 +86,311 @@ public class EppLifecycleDomainTest extends EppTestCase { "domain_create_response.xml", ImmutableMap.of( "DOMAIN", "example.tld", - "CRDATE", "2000-06-01T00:02:00.0Z", - "EXDATE", "2002-06-01T00:02:00.0Z")); + "CRDATE", "2000-06-01T00:02:00Z", + "EXDATE", "2002-06-01T00:02:00Z")); + + assertThatCommand("domain_info.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2000-06-07T00:02:00Z") + .hasResponse( + "domain_info_response_inactive.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + "EXDATE", "2002-06-01T00:02:00Z", + "UPDATE", "2000-06-06T00:02:00Z")); // Delete domain example.tld after its add grace period has expired. assertThatCommand("domain_delete.xml", ImmutableMap.of("DOMAIN", "example.tld")) .atTime("2000-07-01T00:02:00Z") .hasResponse("generic_success_action_pending_response.xml"); + assertThatCommand("domain_info.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2000-07-03T00:02:00Z") + .hasResponse( + "domain_info_response_redemptionperiod_wildcard.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + // The exp. date doesn't change because the deletion didn't cancel any charges. + "EXDATE", "2002-06-01T00:02:00Z", + "UPDATE", "2000-07-01T00:02:00Z")); + // Restore the domain. assertThatCommand("domain_update_restore_request.xml") .atTime("2000-07-01T00:03:00Z") .hasResponse("generic_success_response.xml"); + assertThatCommand("domain_info.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2000-07-02T00:03:00Z") + .hasResponse( + "domain_info_response_inactive.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + // TODO(mcilwain): The exp. date should be restored back to 2002-06-01T00:02:00Z, + // but this is old behavior of being 1 year after the moment of the restore. + "EXDATE", "2001-07-01T00:03:00Z", + "UPDATE", "2000-07-01T00:03:00Z")); + + assertThatLogoutSucceeds(); + } + + @Test + public void testDomainDeleteRestore_duringAutorenewGracePeriod() throws Exception { + assertThatLoginSucceeds("NewRegistrar", "foo-BAR2"); + createContacts(DateTime.parse("2000-06-01T00:00:00Z")); + + // Create domain example.tld + assertThatCommand( + "domain_create_no_hosts_or_dsdata.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2000-06-01T00:02:00Z") + .hasResponse( + "domain_create_response.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + "EXDATE", "2002-06-01T00:02:00Z")); + + assertThatCommand("domain_info.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2000-06-07T00:02:00Z") + .hasResponse( + "domain_info_response_inactive.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + "EXDATE", "2002-06-01T00:02:00Z", + "UPDATE", "2000-06-06T00:02:00Z")); + + assertThatCommand("domain_info.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2002-06-07T00:02:00Z") + .hasResponse( + "domain_info_response_graceperiod.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + // The exp. date has advanced 1 year because of autorenew. + "EXDATE", "2003-06-01T00:02:00Z", + // This is the time of the autorenew. + "UPDATE", "2002-06-01T00:02:00Z", + "GRACEPERIOD", "autoRenewPeriod")); + + // Delete domain example.tld during its autorenew grace period. + assertThatCommand("domain_delete.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2002-07-01T00:02:00Z") + .hasResponse("generic_success_action_pending_response.xml"); + + assertThatCommand("domain_info.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2002-07-03T00:02:00Z") + .hasResponse( + "domain_info_response_redemptionperiod_wildcard.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + // The exp. date reverts back to what it was originally because the deletion + // canceled out the autorenew. + "EXDATE", "2002-06-01T00:02:00Z", + "UPDATE", "2002-07-01T00:02:00Z")); + + // Restore the domain. + assertThatCommand("domain_update_restore_request.xml") + .atTime("2002-07-05T00:03:00Z") + .hasResponse("generic_success_response.xml"); + + assertThatCommand("domain_info.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2002-07-07T00:03:00Z") + .hasResponse( + "domain_info_response_inactive.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + // TODO(mcilwain): The exp. date should be 2003-06-01T00:02:00Z, the same as its + // value prior to the deletion, because the year that was taken off when the + // autorenew was canceled will be re-added in renewal during the restore. + // For now though, the current behavior is 1 year after restore. + "EXDATE", "2003-07-05T00:03:00Z", + "UPDATE", "2002-07-05T00:03:00Z")); + + assertThatLogoutSucceeds(); + } + + @Test + public void testDomainDeleteRestore_duringRenewalGracePeriod() throws Exception { + assertThatLoginSucceeds("NewRegistrar", "foo-BAR2"); + createContacts(DateTime.parse("2000-06-01T00:00:00Z")); + + // Create domain example.tld + assertThatCommand( + "domain_create_no_hosts_or_dsdata.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2000-06-01T00:02:00Z") + .hasResponse( + "domain_create_response.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + "EXDATE", "2002-06-01T00:02:00Z")); + + assertThatCommand("domain_info.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2000-06-07T00:02:00Z") + .hasResponse( + "domain_info_response_inactive.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + "EXDATE", "2002-06-01T00:02:00Z", + "UPDATE", "2000-06-06T00:02:00Z")); + + assertThatCommand( + "domain_renew.xml", + ImmutableMap.of("DOMAIN", "example.tld", "EXPDATE", "2002-06-01", "YEARS", "3")) + .atTime("2000-06-08T00:00:00Z") + .hasResponse( + "domain_renew_response.xml", + ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-06-01T00:02:00Z")); + + assertThatCommand("domain_info.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2000-06-10T00:02:00Z") + .hasResponse( + "domain_info_response_graceperiod.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + // The exp. date is 5 years in total after the create. + "EXDATE", "2005-06-01T00:02:00Z", + // This is the time of the renew. + "UPDATE", "2000-06-08T00:00:00Z", + "GRACEPERIOD", "renewPeriod")); + + // Delete domain example.tld during its renew grace period. + assertThatCommand("domain_delete.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2000-06-12T00:00:00Z") + .hasResponse("generic_success_action_pending_response.xml"); + + assertThatCommand("domain_info.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2000-06-13T00:00:00Z") + .hasResponse( + "domain_info_response_redemptionperiod_wildcard.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + // The exp. date reverts back to what it was originally because the deletion + // canceled out the 3-year renewal. + "EXDATE", "2002-06-01T00:02:00Z", + "UPDATE", "2000-06-12T00:00:00Z")); + + // Restore the domain. + assertThatCommand("domain_update_restore_request.xml") + .atTime("2000-06-20T00:00:00Z") + .hasResponse("generic_success_response.xml"); + + assertThatCommand("domain_info.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2000-06-21T00:00:00Z") + .hasResponse( + "domain_info_response_inactive.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + // TODO(mcilwain): The exp. date should be 2002-06-01T00:02:00Z, which is the + // current registration expiration time on the (deleted) domain, but for now is + // 1 year after restore. + "EXDATE", "2001-06-20T00:00:00Z", + "UPDATE", "2000-06-20T00:00:00Z")); + + assertThatLogoutSucceeds(); + } + + @Test + public void testDomainDelete_duringAddAndRenewalGracePeriod_deletesImmediately() + throws Exception { + assertThatLoginSucceeds("NewRegistrar", "foo-BAR2"); + createContacts(DateTime.parse("2000-06-01T00:00:00Z")); + + DateTime createTime = DateTime.parse("2000-06-01T00:02:00Z"); + // Create domain example.tld + assertThatCommand( + "domain_create_no_hosts_or_dsdata.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime(createTime) + .hasResponse( + "domain_create_response.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + "EXDATE", "2002-06-01T00:02:00Z")); + + assertThatCommand("domain_info.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2000-06-02T00:02:00Z") + .hasResponse( + "domain_info_response_addperiod_wildcard.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + "EXDATE", "2002-06-01T00:02:00Z")); + + DateTime renewTime = DateTime.parse("2000-06-03T00:00:00Z"); + assertThatCommand( + "domain_renew.xml", + ImmutableMap.of("DOMAIN", "example.tld", "EXPDATE", "2002-06-01", "YEARS", "3")) + .atTime(renewTime) + .hasResponse( + "domain_renew_response.xml", + ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-06-01T00:02:00Z")); + + assertThatCommand("domain_info.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2000-06-03T03:00:00Z") + .hasResponse( + "domain_info_response_graceperiod_add_and_renew.xml", + ImmutableMap.of( + "DOMAIN", "example.tld", + "CRDATE", "2000-06-01T00:02:00Z", + // The exp. date is 5 years in total after the create. + "EXDATE", "2005-06-01T00:02:00Z", + // This is the time of the renew. + "UPDATE", "2000-06-03T00:00:00Z")); + + DomainBase domain = + loadByForeignKey(DomainBase.class, "example.tld", DateTime.parse("2000-06-03T04:00:00Z")) + .get(); + + DateTime deleteTime = DateTime.parse("2000-06-04T00:00:00Z"); + // Delete domain example.tld during both grace periods. + assertThatCommand("domain_delete.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2000-06-04T00:00:00Z") + .hasResponse("generic_success_response.xml"); + + // Verify that it is immediately non-existent. + assertThatCommand("domain_info.xml", ImmutableMap.of("DOMAIN", "example.tld")) + .atTime("2000-06-04T00:01:00Z") + .hasResponse( + "response_error.xml", + ImmutableMap.of( + "CODE", "2303", "MSG", "The domain with given ID (example.tld) doesn't exist.")); + + // The expected one-time billing event, that should have an associated Cancellation. + OneTime oneTimeCreateBillingEvent = makeOneTimeCreateBillingEvent(domain, createTime); + OneTime oneTimeRenewBillingEvent = makeOneTimeRenewBillingEvent(domain, renewTime); + + // Verify that the OneTime billing event associated with the domain creation is canceled. + assertBillingEventsForResource( + domain, + // There should be one-time billing events for the create and the renew. + oneTimeCreateBillingEvent, + oneTimeRenewBillingEvent, + // There should be two ended recurring billing events, one each from the create and renew. + // (The former was ended by the renew and the latter was ended by the delete.) + makeRecurringCreateBillingEvent(domain, createTime.plusYears(2), renewTime), + makeRecurringRenewBillingEvent(domain, createTime.plusYears(5), deleteTime), + // There should be Cancellations offsetting both of the one-times. + makeCancellationBillingEventForCreate( + domain, oneTimeCreateBillingEvent, createTime, deleteTime), + makeCancellationBillingEventForRenew( + domain, oneTimeRenewBillingEvent, renewTime, deleteTime)); + + // Verify that the registration expiration time was set back to the creation time, because the + // entire cost of registration was refunded. We have to do this through the DB instead of EPP + // because domains deleted during the add grace period vanish immediately as far as the world + // outside our system is concerned. + DomainBase deletedDomain = ofy().load().entity(domain).now(); + assertAboutDomains().that(deletedDomain).hasRegistrationExpirationTime(createTime); + assertThatLogoutSucceeds(); } @@ -143,9 +437,16 @@ public class EppLifecycleDomainTest extends EppTestCase { oneTimeCreateBillingEvent, makeRecurringCreateBillingEvent(domain, createTime.plusYears(2), deleteTime), // Check for the existence of a cancellation for the given one-time billing event. - makeCancellationBillingEventFor( + makeCancellationBillingEventForCreate( domain, oneTimeCreateBillingEvent, createTime, deleteTime)); + // Verify that the registration expiration time was set back to the creation time, because the + // entire cost of registration was refunded. We have to do this through the DB instead of EPP + // because domains deleted during the add grace period vanish immediately as far as the world + // outside our system is concerned. + DomainBase deletedDomain = ofy().load().entity(domain).now(); + assertAboutDomains().that(deletedDomain).hasRegistrationExpirationTime(createTime); + assertThatLogoutSucceeds(); } @@ -268,7 +569,7 @@ public class EppLifecycleDomainTest extends EppTestCase { expectedCreateEapBillingEvent, makeRecurringCreateBillingEvent(domain, createTime.plusYears(2), deleteTime), // ... and verify that the create one-time billing event was canceled ... - makeCancellationBillingEventFor( + makeCancellationBillingEventForCreate( domain, expectedOneTimeCreateBillingEvent, createTime, deleteTime)); // ... but there was NOT a Cancellation for the EAP fee, as this would fail if additional // billing events were present. diff --git a/core/src/test/java/google/registry/flows/EppTestCase.java b/core/src/test/java/google/registry/flows/EppTestCase.java index 5b77d133a..9f1f59136 100644 --- a/core/src/test/java/google/registry/flows/EppTestCase.java +++ b/core/src/test/java/google/registry/flows/EppTestCase.java @@ -284,20 +284,42 @@ public class EppTestCase extends ShardableTestCase { .setCost(Money.parse("USD 26.00")) .setPeriodYears(2) .setEventTime(createTime) - .setBillingTime(createTime.plus(Registry.get(domain.getTld()).getRenewGracePeriodLength())) + .setBillingTime(createTime.plus(Registry.get(domain.getTld()).getAddGracePeriodLength())) .setParent(getOnlyHistoryEntryOfType(domain, Type.DOMAIN_CREATE)) .build(); } + /** Makes a one-time billing event corresponding to the given domain's renewal. */ + protected static BillingEvent.OneTime makeOneTimeRenewBillingEvent( + DomainBase domain, DateTime renewTime) { + return new BillingEvent.OneTime.Builder() + .setReason(Reason.RENEW) + .setTargetId(domain.getFullyQualifiedDomainName()) + .setClientId(domain.getCurrentSponsorClientId()) + .setCost(Money.parse("USD 33.00")) + .setPeriodYears(3) + .setEventTime(renewTime) + .setBillingTime(renewTime.plus(Registry.get(domain.getTld()).getRenewGracePeriodLength())) + .setParent(getOnlyHistoryEntryOfType(domain, Type.DOMAIN_RENEW)) + .build(); + } + /** Makes a recurring billing event corresponding to the given domain's creation. */ protected static BillingEvent.Recurring makeRecurringCreateBillingEvent( DomainBase domain, DateTime eventTime, DateTime endTime) { - return makeRecurringCreateBillingEvent( + return makeRecurringBillingEvent( domain, getOnlyHistoryEntryOfType(domain, Type.DOMAIN_CREATE), eventTime, endTime); } + /** Makes a recurring billing event corresponding to the given domain's renewal. */ + protected static BillingEvent.Recurring makeRecurringRenewBillingEvent( + DomainBase domain, DateTime eventTime, DateTime endTime) { + return makeRecurringBillingEvent( + domain, getOnlyHistoryEntryOfType(domain, Type.DOMAIN_RENEW), eventTime, endTime); + } + /** Makes a recurring billing event corresponding to the given history entry. */ - protected static BillingEvent.Recurring makeRecurringCreateBillingEvent( + protected static BillingEvent.Recurring makeRecurringBillingEvent( DomainBase domain, HistoryEntry historyEntry, DateTime eventTime, DateTime endTime) { return new BillingEvent.Recurring.Builder() .setReason(Reason.RENEW) @@ -311,22 +333,33 @@ public class EppTestCase extends ShardableTestCase { } /** Makes a cancellation billing event cancelling out the given domain create billing event. */ - protected static BillingEvent.Cancellation makeCancellationBillingEventFor( - DomainBase domain, - OneTime billingEventToCancel, - DateTime createTime, - DateTime deleteTime) { + protected static BillingEvent.Cancellation makeCancellationBillingEventForCreate( + DomainBase domain, OneTime billingEventToCancel, DateTime createTime, DateTime deleteTime) { return new BillingEvent.Cancellation.Builder() .setTargetId(domain.getFullyQualifiedDomainName()) .setClientId(domain.getCurrentSponsorClientId()) .setEventTime(deleteTime) .setOneTimeEventKey(findKeyToActualOneTimeBillingEvent(billingEventToCancel)) - .setBillingTime(createTime.plus(Registry.get(domain.getTld()).getRenewGracePeriodLength())) + .setBillingTime(createTime.plus(Registry.get(domain.getTld()).getAddGracePeriodLength())) .setReason(Reason.CREATE) .setParent(getOnlyHistoryEntryOfType(domain, Type.DOMAIN_DELETE)) .build(); } + /** Makes a cancellation billing event cancelling out the given domain renew billing event. */ + protected static BillingEvent.Cancellation makeCancellationBillingEventForRenew( + DomainBase domain, OneTime billingEventToCancel, DateTime renewTime, DateTime deleteTime) { + return new BillingEvent.Cancellation.Builder() + .setTargetId(domain.getFullyQualifiedDomainName()) + .setClientId(domain.getCurrentSponsorClientId()) + .setEventTime(deleteTime) + .setOneTimeEventKey(findKeyToActualOneTimeBillingEvent(billingEventToCancel)) + .setBillingTime(renewTime.plus(Registry.get(domain.getTld()).getRenewGracePeriodLength())) + .setReason(Reason.RENEW) + .setParent(getOnlyHistoryEntryOfType(domain, Type.DOMAIN_DELETE)) + .build(); + } + /** * Finds the Key to the actual one-time create billing event associated with a domain's creation. * diff --git a/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java index dcf054498..0b2ccf7cb 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java @@ -391,7 +391,7 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase + + + Command completed successfully + + + + %DOMAIN% + 8-TLD + + jd1234 + sh8013 + sh8013 + NewRegistrar + NewRegistrar + %CRDATE% + %EXDATE% + + 2fooBAR + + + + + + + + + + ABC-12345 + server-trid + + + diff --git a/core/src/test/resources/google/registry/flows/domain_info_response_graceperiod.xml b/core/src/test/resources/google/registry/flows/domain_info_response_graceperiod.xml new file mode 100644 index 000000000..012e57125 --- /dev/null +++ b/core/src/test/resources/google/registry/flows/domain_info_response_graceperiod.xml @@ -0,0 +1,37 @@ + + + + Command completed successfully + + + + %DOMAIN% + 8-TLD + + jd1234 + sh8013 + sh8013 + NewRegistrar + NewRegistrar + 2000-06-01T00:02:00Z + NewRegistrar + %UPDATE% + %EXDATE% + + 2fooBAR + + + + + + + + + + ABC-12345 + server-trid + + + diff --git a/core/src/test/resources/google/registry/flows/domain_info_response_graceperiod_add_and_renew.xml b/core/src/test/resources/google/registry/flows/domain_info_response_graceperiod_add_and_renew.xml new file mode 100644 index 000000000..20951b6ba --- /dev/null +++ b/core/src/test/resources/google/registry/flows/domain_info_response_graceperiod_add_and_renew.xml @@ -0,0 +1,38 @@ + + + + Command completed successfully + + + + %DOMAIN% + 8-TLD + + jd1234 + sh8013 + sh8013 + NewRegistrar + NewRegistrar + 2000-06-01T00:02:00Z + NewRegistrar + %UPDATE% + %EXDATE% + + 2fooBAR + + + + + + + + + + + ABC-12345 + server-trid + + + diff --git a/core/src/test/resources/google/registry/flows/domain_info_response_redemptionperiod_wildcard.xml b/core/src/test/resources/google/registry/flows/domain_info_response_redemptionperiod_wildcard.xml new file mode 100644 index 000000000..70daae37f --- /dev/null +++ b/core/src/test/resources/google/registry/flows/domain_info_response_redemptionperiod_wildcard.xml @@ -0,0 +1,38 @@ + + + + Command completed successfully + + + + %DOMAIN% + 8-TLD + + + jd1234 + sh8013 + sh8013 + NewRegistrar + NewRegistrar + %CRDATE% + NewRegistrar + %UPDATE% + %EXDATE% + + 2fooBAR + + + + + + + + + + ABC-12345 + server-trid + + +