diff --git a/core/src/main/java/google/registry/flows/domain/DomainCheckFlow.java b/core/src/main/java/google/registry/flows/domain/DomainCheckFlow.java index b1df32887..318c81754 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainCheckFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainCheckFlow.java @@ -17,6 +17,7 @@ package google.registry.flows.domain; import static com.google.common.base.Strings.emptyToNull; import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.ImmutableMap.toImmutableMap; +import static com.google.common.collect.ImmutableSet.toImmutableSet; import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn; import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount; import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld; @@ -31,6 +32,7 @@ import static google.registry.flows.domain.DomainFlowUtils.validateDomainNameWit import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPredelegation; import static google.registry.model.tld.Registry.TldState.START_DATE_SUNRISE; import static google.registry.model.tld.label.ReservationType.getTypeOfHighestSeverity; +import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -51,6 +53,7 @@ import google.registry.flows.custom.DomainCheckFlowCustomLogic.BeforeResponseRet import google.registry.flows.domain.token.AllocationTokenDomainCheckResults; import google.registry.flows.domain.token.AllocationTokenFlowUtils; import google.registry.model.EppResource; +import google.registry.model.billing.BillingEvent; import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainCommand.Check; import google.registry.model.domain.fee.FeeCheckCommandExtension; @@ -261,22 +264,26 @@ public final class DomainCheckFlow implements Flow { FeeCheckCommandExtension feeCheck = feeCheckOpt.get(); ImmutableList.Builder responseItems = new ImmutableList.Builder<>(); - ImmutableMap domainObjs = + ImmutableMap domainObjs = loadDomainsForRestoreChecks(feeCheck, domainNames, existingDomains); + ImmutableMap recurrences = + loadRecurrencesForDomains(domainObjs); for (FeeCheckCommandExtensionItem feeCheckItem : feeCheck.getItems()) { for (String domainName : getDomainNamesToCheckForFee(feeCheckItem, domainNames.keySet())) { FeeCheckResponseExtensionItem.Builder builder = feeCheckItem.createResponseBuilder(); + Optional domainBase = Optional.ofNullable(domainObjs.get(domainName)); handleFeeRequest( feeCheckItem, builder, domainNames.get(domainName), - Optional.ofNullable((DomainBase) domainObjs.get(domainName)), + domainBase, feeCheck.getCurrency(), now, pricingLogic, allocationToken, - availableDomains.contains(domainName)); + availableDomains.contains(domainName), + recurrences.getOrDefault(domainName, null)); responseItems.add(builder.setDomainNameIfSupported(domainName).build()); } } @@ -294,7 +301,7 @@ public final class DomainCheckFlow implements Flow { * nicer in Cloud SQL when we can SELECT just the fields we want rather than having to load the * entire entity. */ - private ImmutableMap loadDomainsForRestoreChecks( + private ImmutableMap loadDomainsForRestoreChecks( FeeCheckCommandExtension feeCheck, ImmutableMap domainNames, ImmutableMap> existingDomains) { @@ -326,7 +333,23 @@ public final class DomainCheckFlow implements Flow { ImmutableMap, EppResource> loadedDomains = EppResource.loadCached(ImmutableList.copyOf(existingDomainsToLoad.values())); return ImmutableMap.copyOf( - Maps.transformEntries(existingDomainsToLoad, (k, v) -> loadedDomains.get(v))); + Maps.transformEntries(existingDomainsToLoad, (k, v) -> (DomainBase) loadedDomains.get(v))); + } + + private ImmutableMap loadRecurrencesForDomains( + ImmutableMap domainObjs) { + return tm().transact( + () -> { + ImmutableMap, BillingEvent.Recurring> + recurrences = + tm().loadByKeys( + domainObjs.values().stream() + .map(DomainBase::getAutorenewBillingEvent) + .collect(toImmutableSet())); + return ImmutableMap.copyOf( + Maps.transformValues( + domainObjs, d -> recurrences.get(d.getAutorenewBillingEvent()))); + }); } /** diff --git a/core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java b/core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java index f33453e29..71ffd53a6 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java +++ b/core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java @@ -633,7 +633,8 @@ public class DomainFlowUtils { DateTime currentDate, DomainPricingLogic pricingLogic, Optional allocationToken, - boolean isAvailable) + boolean isAvailable, + @Nullable Recurring recurringBillingEvent) throws EppException { DateTime now = currentDate; // Use the custom effective date specified in the fee check request, if there is one. @@ -680,7 +681,10 @@ public class DomainFlowUtils { break; case RENEW: builder.setAvailIfSupported(true); - fees = pricingLogic.getRenewPrice(registry, domainNameString, now, years, null).getFees(); + fees = + pricingLogic + .getRenewPrice(registry, domainNameString, now, years, recurringBillingEvent) + .getFees(); break; case RESTORE: // The minimum allowable period per the EPP spec is 1, so, strangely, 1 year still has to be diff --git a/core/src/main/java/google/registry/flows/domain/DomainInfoFlow.java b/core/src/main/java/google/registry/flows/domain/DomainInfoFlow.java index 7c2ca8c0c..b21fd0840 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainInfoFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainInfoFlow.java @@ -163,7 +163,8 @@ public final class DomainInfoFlow implements Flow { now, pricingLogic, Optional.empty(), - false); + false, + tm().transact(() -> tm().loadByKey(domain.getAutorenewBillingEvent()))); extensions.add(builder.build()); } return extensions.build(); 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 42207c690..26439098b 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java @@ -14,6 +14,9 @@ package google.registry.flows.domain; +import static google.registry.model.billing.BillingEvent.RenewalPriceBehavior.DEFAULT; +import static google.registry.model.billing.BillingEvent.RenewalPriceBehavior.NONPREMIUM; +import static google.registry.model.billing.BillingEvent.RenewalPriceBehavior.SPECIFIED; import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE; import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE; import static google.registry.model.eppoutput.CheckData.DomainCheck.create; @@ -24,6 +27,7 @@ import static google.registry.testing.DatabaseHelper.createTlds; import static google.registry.testing.DatabaseHelper.loadRegistrar; import static google.registry.testing.DatabaseHelper.newDomainBase; import static google.registry.testing.DatabaseHelper.persistActiveDomain; +import static google.registry.testing.DatabaseHelper.persistBillingRecurrenceForDomain; import static google.registry.testing.DatabaseHelper.persistDeletedDomain; import static google.registry.testing.DatabaseHelper.persistPremiumList; import static google.registry.testing.DatabaseHelper.persistReservedList; @@ -66,7 +70,11 @@ import google.registry.flows.domain.DomainFlowUtils.TrailingDashException; import google.registry.flows.domain.DomainFlowUtils.TransfersAreAlwaysForOneYearException; import google.registry.flows.domain.DomainFlowUtils.UnknownFeeCommandException; import google.registry.flows.exceptions.TooManyResourceChecksException; +import google.registry.model.billing.BillingEvent; +import google.registry.model.billing.BillingEvent.Flag; +import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.domain.DomainBase; +import google.registry.model.domain.DomainHistory; import google.registry.model.domain.token.AllocationToken; import google.registry.model.domain.token.AllocationToken.TokenStatus; import google.registry.model.eppcommon.StatusValue; @@ -75,6 +83,7 @@ import google.registry.model.tld.Registry; import google.registry.model.tld.Registry.TldState; import google.registry.model.tld.label.ReservedList; import google.registry.testing.SetClockExtension; +import java.math.BigDecimal; import org.joda.money.CurrencyUnit; import org.joda.money.Money; import org.joda.time.DateTime; @@ -806,6 +815,29 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase(Ordering.natural()) .put(START_OF_TIME, Money.of(USD, 0)) - .put(clock.nowUtc().minusDays(1), Money.of(USD, 100)) - .put(clock.nowUtc().plusDays(1), Money.of(USD, 50)) - .put(clock.nowUtc().plusDays(2), Money.of(USD, 0)) + .put(startTime.minusDays(1), Money.of(USD, 100)) + .put(startTime.plusDays(1), Money.of(USD, 50)) + .put(startTime.plusDays(2), Money.of(USD, 0)) .build()) .build()); - runFlowAssertResponse(loadFile("domain_check_fee_premium_eap_response_v06_with_renewal.xml")); } @@ -942,7 +981,7 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase substitutions) - throws Exception { - doSuccessfulTest(expectedXmlFilename, inactive, substitutions, false); - } - private void doSuccessfulTest(String expectedXmlFilename, boolean inactive) throws Exception { doSuccessfulTest(expectedXmlFilename, inactive, ImmutableMap.of(), false); } @@ -195,6 +198,16 @@ class DomainInfoFlowTest extends ResourceFlowTestCasecreate 1 100.00 - 100.00 + 100.00 premium diff --git a/core/src/test/resources/google/registry/flows/domain/domain_check_fee_response_domain_exists_v06.xml b/core/src/test/resources/google/registry/flows/domain/domain_check_fee_response_domain_exists_v06.xml new file mode 100644 index 000000000..86f5fe1be --- /dev/null +++ b/core/src/test/resources/google/registry/flows/domain/domain_check_fee_response_domain_exists_v06.xml @@ -0,0 +1,55 @@ + + + + Command completed successfully + + + + + rich.example + In use + + + + + + + rich.example + USD + create + 1 + 100.00 + premium + + + rich.example + USD + renew + 1 + %RENEWPRICE% + + + rich.example + USD + transfer + 1 + + 100.00 + premium + + + rich.example + USD + restore + 1 + 17.00 + + + + + ABC-12345 + server-trid + + +