From dd86c56ddc4bbf5371bf813342d0454e57f83c7d Mon Sep 17 00:00:00 2001 From: gbrodman Date: Fri, 1 Dec 2023 15:37:05 -0500 Subject: [PATCH] Return the correct renewal fee for anchor tenants in domain checks (#2238) The code as previously written assumed that creation fees would be the same as renewal fees -- this is not the case for anchor tenants, where the renewal fee is always the standard cost for the TLD (instead of any premium cost). This was already handled properly in the actual billing implementation, but we didn't tell the user the right renewal cost in domain checks. This also removes some warning logs related to nested transactions --- .../flows/domain/DomainPricingLogic.java | 28 +++++++++++++------ .../model/tld/label/ReservedList.java | 2 +- .../flows/domain/DomainCheckFlowTest.java | 2 ++ .../domain_check_allocationtoken_fee.xml | 18 ++++++++++++ ...ck_allocationtoken_fee_anchor_response.xml | 22 +++++++++++++++ ...ain_check_allocationtoken_fee_response.xml | 21 ++++++++++++++ 6 files changed, 84 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/google/registry/flows/domain/DomainPricingLogic.java b/core/src/main/java/google/registry/flows/domain/DomainPricingLogic.java index 368c0eb5f..bbd479de2 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainPricingLogic.java +++ b/core/src/main/java/google/registry/flows/domain/DomainPricingLogic.java @@ -18,7 +18,6 @@ import static com.google.common.base.Preconditions.checkArgument; import static google.registry.flows.domain.DomainFlowUtils.zeroInCurrency; import static google.registry.flows.domain.token.AllocationTokenFlowUtils.validateTokenForPossiblePremiumName; import static google.registry.pricing.PricingEngineProxy.getPricesForDomainName; -import static google.registry.util.DomainNameUtils.getTldFromDomainName; import static google.registry.util.PreconditionsUtils.checkArgumentPresent; import com.google.common.net.InternetDomainName; @@ -31,11 +30,13 @@ import google.registry.flows.custom.DomainPricingCustomLogic.RenewPriceParameter import google.registry.flows.custom.DomainPricingCustomLogic.RestorePriceParameters; import google.registry.flows.custom.DomainPricingCustomLogic.TransferPriceParameters; import google.registry.flows.custom.DomainPricingCustomLogic.UpdatePriceParameters; +import google.registry.model.billing.BillingBase.RenewalPriceBehavior; import google.registry.model.billing.BillingRecurrence; import google.registry.model.domain.fee.BaseFee; import google.registry.model.domain.fee.BaseFee.FeeType; import google.registry.model.domain.fee.Fee; import google.registry.model.domain.token.AllocationToken; +import google.registry.model.domain.token.AllocationToken.RegistrationBehavior; import google.registry.model.domain.token.AllocationToken.TokenBehavior; import google.registry.model.pricing.PremiumPricingEngine.DomainPrices; import google.registry.model.tld.Tld; @@ -132,12 +133,14 @@ public final class DomainPricingLogic { // recurrence is null if the domain is still available. Billing events are created // in the process of domain creation. if (billingRecurrence == null) { - renewCost = getDomainRenewCostWithDiscount(domainPrices, years, allocationToken); + renewCost = + getDomainRenewCostWithDiscount(tld, domainPrices, dateTime, years, allocationToken); isRenewCostPremiumPrice = domainPrices.isPremium(); } else { switch (billingRecurrence.getRenewalPriceBehavior()) { case DEFAULT: - renewCost = getDomainRenewCostWithDiscount(domainPrices, years, allocationToken); + renewCost = + getDomainRenewCostWithDiscount(tld, domainPrices, dateTime, years, allocationToken); isRenewCostPremiumPrice = domainPrices.isPremium(); break; // if the renewal price behavior is specified, then the renewal price should be the same @@ -156,10 +159,7 @@ public final class DomainPricingLogic { case NONPREMIUM: renewCost = getDomainCostWithDiscount( - false, - years, - allocationToken, - Tld.get(getTldFromDomainName(domainName)).getStandardRenewCost(dateTime)); + false, years, allocationToken, tld.getStandardRenewCost(dateTime)); isRenewCostPremiumPrice = false; break; default: @@ -257,8 +257,20 @@ public final class DomainPricingLogic { /** Returns the domain renew cost with allocation-token-related discounts applied. */ private Money getDomainRenewCostWithDiscount( - DomainPrices domainPrices, int years, Optional allocationToken) + Tld tld, + DomainPrices domainPrices, + DateTime dateTime, + int years, + Optional allocationToken) throws AllocationTokenInvalidForPremiumNameException { + // Short-circuit if the user sent an anchor-tenant or otherwise NONPREMIUM-renewal token + if (allocationToken.isPresent()) { + AllocationToken token = allocationToken.get(); + if (token.getRegistrationBehavior().equals(RegistrationBehavior.ANCHOR_TENANT) + || token.getRenewalPriceBehavior().equals(RenewalPriceBehavior.NONPREMIUM)) { + return tld.getStandardRenewCost(dateTime).multipliedBy(years); + } + } return getDomainCostWithDiscount( domainPrices.isPremium(), years, allocationToken, domainPrices.getRenewCost()); } diff --git a/core/src/main/java/google/registry/model/tld/label/ReservedList.java b/core/src/main/java/google/registry/model/tld/label/ReservedList.java index 46601181c..a643f9238 100644 --- a/core/src/main/java/google/registry/model/tld/label/ReservedList.java +++ b/core/src/main/java/google/registry/model/tld/label/ReservedList.java @@ -199,7 +199,7 @@ public final class ReservedList public synchronized ImmutableMap getReservedListEntries() { if (reservedListMap == null) { reservedListMap = - tm().transact( + tm().reTransact( () -> tm() .createQueryComposer(ReservedListEntry.class) diff --git a/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java index 73534ae34..49075a846 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java @@ -340,6 +340,7 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCasenaturalOrder() .put(START_OF_TIME, TokenStatus.NOT_STARTED) diff --git a/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken_fee.xml b/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken_fee.xml index 1bf30eae0..1b432f0ec 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken_fee.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken_fee.xml @@ -34,6 +34,24 @@ create 1 + + example1.tld + USD + renew + 1 + + + example2.example + USD + renew + 1 + + + reserved.tld + USD + renew + 1 + ABC-12345 diff --git a/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken_fee_anchor_response.xml b/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken_fee_anchor_response.xml index bf0688e7c..b0cb4a7dd 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken_fee_anchor_response.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken_fee_anchor_response.xml @@ -42,6 +42,28 @@ 1 token-not-supported + + example1.tld + USD + renew + 1 + 11.00 + premium + + + example2.example + USD + renew + 1 + token-not-supported + + + reserved.tld + USD + renew + 1 + token-not-supported + diff --git a/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken_fee_response.xml b/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken_fee_response.xml index 5dcd84538..4ef967f0e 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken_fee_response.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken_fee_response.xml @@ -41,6 +41,27 @@ 1 reserved + + example1.tld + USD + renew + 1 + token-not-supported + + + example2.example + USD + renew + 1 + token-not-supported + + + reserved.tld + USD + renew + 1 + token-not-supported +