diff --git a/java/google/registry/flows/domain/DomainCheckFlow.java b/java/google/registry/flows/domain/DomainCheckFlow.java index 4cf163b75..e7c6544da 100644 --- a/java/google/registry/flows/domain/DomainCheckFlow.java +++ b/java/google/registry/flows/domain/DomainCheckFlow.java @@ -187,9 +187,7 @@ public final class DomainCheckFlow extends LoggedInFlow { domainNames.get(domainName), clientId, feeCheck.getCurrency(), - feeCheckItem.getEffectiveDate().isPresent() - ? feeCheckItem.getEffectiveDate().get() - : now, + now, eppInput); responseItems.add(builder.setDomainNameIfSupported(domainName).build()); } diff --git a/java/google/registry/flows/domain/DomainFlowUtils.java b/java/google/registry/flows/domain/DomainFlowUtils.java index 393a1775e..74de4f651 100644 --- a/java/google/registry/flows/domain/DomainFlowUtils.java +++ b/java/google/registry/flows/domain/DomainFlowUtils.java @@ -27,6 +27,7 @@ import static google.registry.model.registry.label.ReservedList.getReservation; import static google.registry.pricing.PricingEngineProxy.getPricesForDomainName; import static google.registry.tldconfig.idn.IdnLabelValidator.findValidIdnTableForTld; import static google.registry.util.CollectionUtils.nullToEmpty; +import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.DateTimeUtils.isAtOrAfter; import static google.registry.util.DomainNameUtils.ACE_PREFIX; @@ -64,8 +65,6 @@ import google.registry.model.domain.DomainResource; import google.registry.model.domain.Period; import google.registry.model.domain.fee.Credit; import google.registry.model.domain.fee.Fee; -import google.registry.model.domain.fee.FeeCheckCommandExtensionItem; -import google.registry.model.domain.fee.FeeCheckResponseExtensionItem; import google.registry.model.domain.fee.FeeQueryCommandExtensionItem; import google.registry.model.domain.fee.FeeQueryResponseExtensionItem; import google.registry.model.domain.fee.FeeTransformCommandExtension; @@ -570,8 +569,8 @@ public class DomainFlowUtils { } /** - * Validates a {@link FeeCheckCommandExtensionItem} and sets the appropriate fields on a - * {@link FeeCheckResponseExtensionItem} builder. + * Validates a {@link FeeQueryCommandExtensionItem} and sets the appropriate fields on a {@link + * FeeQueryResponseExtensionItem} builder. */ static void handleFeeRequest( FeeQueryCommandExtensionItem feeRequest, @@ -579,8 +578,14 @@ public class DomainFlowUtils { InternetDomainName domain, String clientId, @Nullable CurrencyUnit topLevelCurrency, - DateTime now, + DateTime currentDate, EppInput eppInput) throws EppException { + DateTime now = currentDate; + // Use the custom effective date specified in the fee check request, if there is one. + if (feeRequest.getEffectiveDate().isPresent()) { + now = feeRequest.getEffectiveDate().get(); + builder.setEffectiveDateIfSupported(now); + } String domainNameString = domain.toString(); Registry registry = Registry.get(domain.parent().toString()); int years = verifyUnitIsYears(feeRequest.getPeriod()).getValue(); @@ -602,6 +607,7 @@ public class DomainFlowUtils { .setPeriod(feeRequest.getPeriod()) .setClass(TldSpecificLogicProxy.getFeeClass(domainNameString, now).orNull()); + List fees = ImmutableList.of(); switch (feeRequest.getCommandName()) { case CREATE: if (isReserved(domain, isSunrise)) { // Don't return a create price for reserved names. @@ -610,36 +616,53 @@ public class DomainFlowUtils { builder.setReasonIfSupported("reserved"); } else { builder.setAvailIfSupported(true); - builder.setFees(TldSpecificLogicProxy.getCreatePrice( - registry, domainNameString, clientId, now, years, eppInput).getFees()); + fees = TldSpecificLogicProxy.getCreatePrice( + registry, domainNameString, clientId, now, years, eppInput).getFees(); } break; case RENEW: builder.setAvailIfSupported(true); - builder.setFees(TldSpecificLogicProxy.getRenewPrice( - registry, domainNameString, clientId, now, years, eppInput).getFees()); + fees = TldSpecificLogicProxy.getRenewPrice( + registry, domainNameString, clientId, now, years, eppInput).getFees(); break; case RESTORE: if (years != 1) { throw new RestoresAreAlwaysForOneYearException(); } builder.setAvailIfSupported(true); - builder.setFees(TldSpecificLogicProxy.getRestorePrice( - registry, domainNameString, clientId, now, eppInput).getFees()); + fees = TldSpecificLogicProxy.getRestorePrice( + registry, domainNameString, clientId, now, eppInput).getFees(); break; case TRANSFER: builder.setAvailIfSupported(true); - builder.setFees(TldSpecificLogicProxy.getTransferPrice( - registry, domainNameString, clientId, now, years, eppInput).getFees()); + fees = TldSpecificLogicProxy.getTransferPrice( + registry, domainNameString, clientId, now, years, eppInput).getFees(); break; case UPDATE: builder.setAvailIfSupported(true); - builder.setFees(TldSpecificLogicProxy.getUpdatePrice( - registry, domainNameString, clientId, now, eppInput).getFees()); + fees = TldSpecificLogicProxy.getUpdatePrice( + registry, domainNameString, clientId, now, eppInput).getFees(); break; default: throw new UnknownFeeCommandException(feeRequest.getUnparsedCommandName()); } + + // Set the fees, and based on the validDateRange of the fees, set the notAfterDate. + if (!fees.isEmpty()) { + builder.setFees(fees); + DateTime notAfterDate = null; + for (Fee fee : fees) { + if (fee.hasValidDateRange()) { + DateTime endDate = fee.getValidDateRange().upperEndpoint(); + if (notAfterDate == null || notAfterDate.isAfter(endDate)) { + notAfterDate = endDate; + } + } + } + if (notAfterDate != null && !notAfterDate.equals(END_OF_TIME)) { + builder.setNotAfterDateIfSupported(notAfterDate); + } + } } public static void validateFeeChallenge( diff --git a/java/google/registry/flows/domain/DomainInfoFlow.java b/java/google/registry/flows/domain/DomainInfoFlow.java index cd7e8264a..af860ae19 100644 --- a/java/google/registry/flows/domain/DomainInfoFlow.java +++ b/java/google/registry/flows/domain/DomainInfoFlow.java @@ -128,7 +128,7 @@ public final class DomainInfoFlow extends LoggedInFlow { InternetDomainName.from(targetId), clientId, null, - feeInfo.getEffectiveDate().isPresent() ? feeInfo.getEffectiveDate().get() : now, + now, eppInput); extensions.add(builder.build()); } diff --git a/java/google/registry/model/domain/fee/BaseFee.java b/java/google/registry/model/domain/fee/BaseFee.java index 2967209ea..f8aa6d610 100644 --- a/java/google/registry/model/domain/fee/BaseFee.java +++ b/java/google/registry/model/domain/fee/BaseFee.java @@ -118,6 +118,11 @@ public abstract class BaseFee extends ImmutableObject { public boolean hasValidDateRange() { return validDateRange != null; } + + public Range getValidDateRange() { + checkState(hasValidDateRange()); + return validDateRange; + } protected void generateDescription(Object... args) { checkState(type != null); diff --git a/java/google/registry/model/domain/fee/FeeQueryResponseExtensionItem.java b/java/google/registry/model/domain/fee/FeeQueryResponseExtensionItem.java index 0f46b8fac..0a252ef8f 100644 --- a/java/google/registry/model/domain/fee/FeeQueryResponseExtensionItem.java +++ b/java/google/registry/model/domain/fee/FeeQueryResponseExtensionItem.java @@ -18,6 +18,7 @@ import google.registry.model.domain.Period; import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName; import java.util.List; import org.joda.money.CurrencyUnit; +import org.joda.time.DateTime; /** * Interface for individual query items in Check and Info response. Each item indicates the fees and @@ -50,10 +51,16 @@ public interface FeeQueryResponseExtensionItem { /** The reason that the check item cannot be calculated. */ public Builder setReasonIfSupported(String reason); + /** The effective date that the check is run on. */ + public Builder setEffectiveDateIfSupported(DateTime effectiveDate); + + /** The date after which the quoted fees are no longer valid. */ + public Builder setNotAfterDateIfSupported(DateTime notAfterDate); + public Builder setCommand(CommandName commandName, String phase, String subphase); public Builder setPeriod(Period period); - + public Builder setFees(List fees); public Builder setClass(String feeClass); diff --git a/java/google/registry/model/domain/fee06/FeeCheckResponseExtensionItemV06.java b/java/google/registry/model/domain/fee06/FeeCheckResponseExtensionItemV06.java index 17de4550f..1377aa468 100644 --- a/java/google/registry/model/domain/fee06/FeeCheckResponseExtensionItemV06.java +++ b/java/google/registry/model/domain/fee06/FeeCheckResponseExtensionItemV06.java @@ -18,6 +18,7 @@ import google.registry.model.domain.fee.FeeCheckResponseExtensionItem; import google.registry.model.domain.fee.FeeQueryResponseExtensionItemImpl; import javax.xml.bind.annotation.XmlType; import org.joda.money.CurrencyUnit; +import org.joda.time.DateTime; /** The version 0.6 response for a domain check on a single resource. */ @XmlType(propOrder = {"name", "currency", "command", "period", "fee", "feeClass"}) @@ -54,5 +55,16 @@ public class FeeCheckResponseExtensionItemV06 public Builder setReasonIfSupported(String reason) { return this; } + + @Override + public Builder setEffectiveDateIfSupported(DateTime effectiveDate) { + return this; + } + + @Override + public Builder setNotAfterDateIfSupported(DateTime notAfterDate) { + return this; + } + } } diff --git a/java/google/registry/model/domain/fee06/FeeInfoResponseExtensionV06.java b/java/google/registry/model/domain/fee06/FeeInfoResponseExtensionV06.java index bf11f1c8f..c51fe8e4c 100644 --- a/java/google/registry/model/domain/fee06/FeeInfoResponseExtensionV06.java +++ b/java/google/registry/model/domain/fee06/FeeInfoResponseExtensionV06.java @@ -20,6 +20,7 @@ import google.registry.model.eppoutput.EppResponse.ResponseExtension; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import org.joda.money.CurrencyUnit; +import org.joda.time.DateTime; /** * An XML data object that represents a fee extension that may be present on the response to EPP @@ -52,5 +53,15 @@ public class FeeInfoResponseExtensionV06 getInstance().currency = currency; return this; } + + @Override + public Builder setEffectiveDateIfSupported(DateTime effectiveDate) { + return this; + } + + @Override + public Builder setNotAfterDateIfSupported(DateTime notAfterDate) { + return this; + } } } diff --git a/java/google/registry/model/domain/fee11/FeeCheckResponseExtensionItemV11.java b/java/google/registry/model/domain/fee11/FeeCheckResponseExtensionItemV11.java index 03a45da12..edd3759b3 100644 --- a/java/google/registry/model/domain/fee11/FeeCheckResponseExtensionItemV11.java +++ b/java/google/registry/model/domain/fee11/FeeCheckResponseExtensionItemV11.java @@ -20,6 +20,7 @@ import google.registry.model.domain.fee.FeeQueryResponseExtensionItemImpl; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlType; import org.joda.money.CurrencyUnit; +import org.joda.time.DateTime; /** The version 0.11 response for a domain check on a single resource. */ @XmlType(propOrder = {"object", "command", "currency", "period", "fee", "feeClass", "reason"}) @@ -66,5 +67,15 @@ public class FeeCheckResponseExtensionItemV11 getInstance().reason = reason; return this; } + + @Override + public Builder setEffectiveDateIfSupported(DateTime effectiveDate) { + return this; + } + + @Override + public Builder setNotAfterDateIfSupported(DateTime notAfterDate) { + return this; + } } } diff --git a/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemCommandV12.java b/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemCommandV12.java index 66d45cf1a..593363eab 100644 --- a/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemCommandV12.java +++ b/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemCommandV12.java @@ -27,11 +27,10 @@ import java.util.List; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; +import org.joda.time.DateTime; -/** - * The version 0.12 response command entity for a domain check on a single resource. - */ -@XmlType(propOrder = {"period", "fee", "feeClass"}) +/** The version 0.12 response command entity for a domain check on a single resource. */ +@XmlType(propOrder = {"period", "fee", "feeClass", "effectiveDate", "notAfterDate"}) public class FeeCheckResponseExtensionItemCommandV12 extends ImmutableObject { /** The command that was checked. */ @@ -63,6 +62,15 @@ public class FeeCheckResponseExtensionItemCommandV12 extends ImmutableObject { */ @XmlElement(name = "class") String feeClass; + + /** The effective date that the check is to be performed on (if specified in the query). */ + @XmlElement(name = "date") + DateTime effectiveDate; + + /** The date after which the quoted fee is no longer valid (if applicable). */ + @XmlElement(name = "notAfter") + DateTime notAfterDate; + public String getFeeClass() { return feeClass; @@ -92,6 +100,16 @@ public class FeeCheckResponseExtensionItemCommandV12 extends ImmutableObject { return this; } + public Builder setEffectiveDate(DateTime effectiveDate) { + getInstance().effectiveDate = effectiveDate; + return this; + } + + public Builder setNotAfterDate(DateTime notAfterDate) { + getInstance().notAfterDate = notAfterDate; + return this; + } + public Builder setFee(List fees) { getInstance().fee = forceEmptyToNull(ImmutableList.copyOf(fees)); return this; diff --git a/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemV12.java b/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemV12.java index fc957009b..2a5599e3e 100644 --- a/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemV12.java +++ b/java/google/registry/model/domain/fee12/FeeCheckResponseExtensionItemV12.java @@ -27,6 +27,7 @@ import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName import java.util.List; import javax.xml.bind.annotation.XmlType; import org.joda.money.CurrencyUnit; +import org.joda.time.DateTime; /** * The version 0.12 response for a domain check on a single resource. @@ -111,5 +112,17 @@ public class FeeCheckResponseExtensionItemV12 getInstance().command = commandBuilder.build(); return super.build(); } + + @Override + public Builder setEffectiveDateIfSupported(DateTime effectiveDate) { + commandBuilder.setEffectiveDate(effectiveDate); + return this; + } + + @Override + public Builder setNotAfterDateIfSupported(DateTime notAfterDate) { + commandBuilder.setNotAfterDate(notAfterDate); + return this; + } } } diff --git a/javatests/google/registry/flows/domain/DomainCheckFlowTest.java b/javatests/google/registry/flows/domain/DomainCheckFlowTest.java index 169943bbf..7c657236f 100644 --- a/javatests/google/registry/flows/domain/DomainCheckFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainCheckFlowTest.java @@ -60,6 +60,7 @@ import org.joda.money.CurrencyUnit; import org.joda.money.Money; import org.joda.time.DateTime; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; /** Unit tests for {@link DomainCheckFlow}. */ @@ -803,5 +804,11 @@ public class DomainCheckFlowTest runEapFeeCheckTest("domain_check_fee_date_v12.xml", "domain_check_eap_fee_response_date_v12.xml"); } - + + @Ignore + @Test + public void testSuccess_feeCheck_multipleRanges() throws Exception { + // TODO: If at some point we have more than one type of fees that are time dependent, populate + // this test to test if the notAfter date is the earliest of the end points of the ranges. + } } diff --git a/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_date_v12.xml b/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_date_v12.xml index f41e225c4..316179cdb 100644 --- a/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_date_v12.xml +++ b/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_date_v12.xml @@ -29,6 +29,8 @@ 1 13.00 50.00 + 2010-01-02T13:22:21Z + 2010-01-03T10:00:00.000Z @@ -39,6 +41,8 @@ 1 13.00 50.00 + 2010-01-02T13:22:21Z + 2010-01-03T10:00:00.000Z @@ -49,6 +53,8 @@ 1 13.00 50.00 + 2010-01-02T13:22:21Z + 2010-01-03T10:00:00.000Z diff --git a/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_v12.xml b/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_v12.xml index c6664c581..b1a6a3e54 100644 --- a/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_v12.xml +++ b/javatests/google/registry/flows/domain/testdata/domain_check_eap_fee_response_v12.xml @@ -29,6 +29,7 @@ 1 13.00 100.00 + 2010-01-02T10:00:00.000Z @@ -39,6 +40,7 @@ 1 13.00 100.00 + 2010-01-02T10:00:00.000Z @@ -49,6 +51,7 @@ 1 13.00 100.00 + 2010-01-02T10:00:00.000Z