Support date and notAfter in fee extension response v12

When custom effective date is passed in the check command, the response should
contain that date as an acknowledgemant that the check is performed at a time
different from now.

Also when the fee(s) returned contains a validDateRange (i. e. EAP fees that
are only valid during a certain period), the response will contain a notAfter
field which is the date after which the quoted fee(s) are no longer valid. (i.
e. the earliest of the end dates of all fees that would expire.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=133989775
This commit is contained in:
jianglai 2016-09-22 13:07:21 -07:00 committed by Ben McIlwain
parent 863eac3b11
commit b783acfcc6
13 changed files with 139 additions and 25 deletions

View file

@ -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());
}

View file

@ -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<Fee> 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(

View file

@ -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());
}

View file

@ -118,6 +118,11 @@ public abstract class BaseFee extends ImmutableObject {
public boolean hasValidDateRange() {
return validDateRange != null;
}
public Range<DateTime> getValidDateRange() {
checkState(hasValidDateRange());
return validDateRange;
}
protected void generateDescription(Object... args) {
checkState(type != null);

View file

@ -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<Fee> fees);
public Builder setClass(String feeClass);

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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<Fee> fees) {
getInstance().fee = forceEmptyToNull(ImmutableList.copyOf(fees));
return this;

View file

@ -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;
}
}
}

View file

@ -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.
}
}

View file

@ -29,6 +29,8 @@
<fee:period unit="y">1</fee:period>
<fee:fee description="create">13.00</fee:fee>
<fee:fee description="Early Access Period, fee expires: 2010-01-03T10:00:00.000Z">50.00</fee:fee>
<fee:date>2010-01-02T13:22:21Z</fee:date>
<fee:notAfter>2010-01-03T10:00:00.000Z</fee:notAfter>
</fee:command>
</fee:cd>
<fee:cd>
@ -39,6 +41,8 @@
<fee:period unit="y">1</fee:period>
<fee:fee description="create">13.00</fee:fee>
<fee:fee description="Early Access Period, fee expires: 2010-01-03T10:00:00.000Z">50.00</fee:fee>
<fee:date>2010-01-02T13:22:21Z</fee:date>
<fee:notAfter>2010-01-03T10:00:00.000Z</fee:notAfter>
</fee:command>
</fee:cd>
<fee:cd>
@ -49,6 +53,8 @@
<fee:period unit="y">1</fee:period>
<fee:fee description="create">13.00</fee:fee>
<fee:fee description="Early Access Period, fee expires: 2010-01-03T10:00:00.000Z">50.00</fee:fee>
<fee:date>2010-01-02T13:22:21Z</fee:date>
<fee:notAfter>2010-01-03T10:00:00.000Z</fee:notAfter>
</fee:command>
</fee:cd>
</fee:chkData>

View file

@ -29,6 +29,7 @@
<fee:period unit="y">1</fee:period>
<fee:fee description="create">13.00</fee:fee>
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.000Z">100.00</fee:fee>
<fee:notAfter>2010-01-02T10:00:00.000Z</fee:notAfter>
</fee:command>
</fee:cd>
<fee:cd>
@ -39,6 +40,7 @@
<fee:period unit="y">1</fee:period>
<fee:fee description="create">13.00</fee:fee>
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.000Z">100.00</fee:fee>
<fee:notAfter>2010-01-02T10:00:00.000Z</fee:notAfter>
</fee:command>
</fee:cd>
<fee:cd>
@ -49,6 +51,7 @@
<fee:period unit="y">1</fee:period>
<fee:fee description="create">13.00</fee:fee>
<fee:fee description="Early Access Period, fee expires: 2010-01-02T10:00:00.000Z">100.00</fee:fee>
<fee:notAfter>2010-01-02T10:00:00.000Z</fee:notAfter>
</fee:command>
</fee:cd>
</fee:chkData>