Refactor Fee handling so that each fee knows if it's premium (#626)

* Refactor Fee handling so that each fee knows if it's premium

This is a noop for now, as the new isPremium boolean isn't yet used by anything,
but it will be used in follow-up PRs to add additional fee information using the
fee extension (see: b/157621273).  Specifically what we're trying to do here is
return <fee:command name="create" standard="1"> (using the finalized version of
the fee extension) when an entire command has no premium fee associated with
it. And in the current earlier versions of the fee extension that we support,
we'll want to display the correct fee amount and class for creates/checks on
reserved domains when a valid allocation token is passed. This also needs the
isPremium information.

There are no testing implications yet because isPremium isn't exposed anywhere,
but there will definitely be lots of test changes once it's feeding into EPP-
visible changes.

* Rename things, add method Javadoc

* Apply formatting
This commit is contained in:
Ben McIlwain 2020-06-12 16:43:02 -04:00 committed by GitHub
parent cf1448bca8
commit 4be70c8509
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 133 additions and 81 deletions

View file

@ -690,7 +690,7 @@ public class DomainFlowUtils {
List<Fee> fees = feeCommand.get().getFees(); List<Fee> fees = feeCommand.get().getFees();
// The schema guarantees that at least one fee will be present. // The schema guarantees that at least one fee will be present.
checkState(!fees.isEmpty()); checkState(!fees.isEmpty());
BigDecimal total = BigDecimal.ZERO; BigDecimal total = zeroInCurrency(feeCommand.get().getCurrency());
for (Fee fee : fees) { for (Fee fee : fees) {
if (!fee.hasDefaultAttributes()) { if (!fee.hasDefaultAttributes()) {
throw new UnsupportedFeeAttributeException(); throw new UnsupportedFeeAttributeException();
@ -938,6 +938,16 @@ public class DomainFlowUtils {
} }
} }
/**
* Returns zero for a specific currency.
*
* <p>{@link BigDecimal} has a concept of significant figures, so zero is not always zero. E.g.
* zero in USD is 0.00, whereas zero in Yen is 0, and zero in Dinars is 0.000 (!).
*/
static BigDecimal zeroInCurrency(CurrencyUnit currencyUnit) {
return Money.of(currencyUnit, BigDecimal.ZERO).getAmount();
}
/** /**
* Check that if there's a claims notice it's on the claims list, and that if there's not one it's * Check that if there's a claims notice it's on the claims list, and that if there's not one it's
* not on the claims list. * not on the claims list.

View file

@ -14,8 +14,9 @@
package google.registry.flows.domain; package google.registry.flows.domain;
import static google.registry.flows.domain.DomainFlowUtils.zeroInCurrency;
import static google.registry.pricing.PricingEngineProxy.getDomainFeeClass; import static google.registry.pricing.PricingEngineProxy.getDomainFeeClass;
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost; import static google.registry.pricing.PricingEngineProxy.getPricesForDomainName;
import com.google.common.net.InternetDomainName; import com.google.common.net.InternetDomainName;
import google.registry.flows.EppException; import google.registry.flows.EppException;
@ -33,7 +34,6 @@ import google.registry.model.domain.fee.Fee;
import google.registry.model.domain.token.AllocationToken; import google.registry.model.domain.token.AllocationToken;
import google.registry.model.pricing.PremiumPricingEngine.DomainPrices; import google.registry.model.pricing.PremiumPricingEngine.DomainPrices;
import google.registry.model.registry.Registry; import google.registry.model.registry.Registry;
import google.registry.pricing.PricingEngineProxy;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.util.Optional; import java.util.Optional;
@ -64,21 +64,27 @@ public final class DomainPricingLogic {
public FeesAndCredits getCreatePrice( public FeesAndCredits getCreatePrice(
Registry registry, Registry registry,
String domainName, String domainName,
DateTime date, DateTime dateTime,
int years, int years,
boolean isAnchorTenant, boolean isAnchorTenant,
Optional<AllocationToken> allocationToken) Optional<AllocationToken> allocationToken)
throws EppException { throws EppException {
CurrencyUnit currency = registry.getCurrency(); CurrencyUnit currency = registry.getCurrency();
BaseFee createFeeOrCredit;
// Domain create cost is always zero for anchor tenants // Domain create cost is always zero for anchor tenants
if (isAnchorTenant) {
createFeeOrCredit = Fee.create(zeroInCurrency(currency), FeeType.CREATE, false);
} else {
DomainPrices domainPrices = getPricesForDomainName(domainName, dateTime);
Money domainCreateCost = Money domainCreateCost =
isAnchorTenant getDomainCreateCostWithDiscount(domainPrices, years, allocationToken);
? Money.of(currency, BigDecimal.ZERO) createFeeOrCredit =
: getDomainCreateCostWithDiscount(domainName, date, years, allocationToken); Fee.create(domainCreateCost.getAmount(), FeeType.CREATE, domainPrices.isPremium());
BaseFee createFeeOrCredit = Fee.create(domainCreateCost.getAmount(), FeeType.CREATE); }
// Create fees for the cost and the EAP fee, if any. // Create fees for the cost and the EAP fee, if any.
Fee eapFee = registry.getEapFeeFor(date); Fee eapFee = registry.getEapFeeFor(dateTime);
FeesAndCredits.Builder feesBuilder = FeesAndCredits.Builder feesBuilder =
new FeesAndCredits.Builder().setCurrency(currency).addFeeOrCredit(createFeeOrCredit); new FeesAndCredits.Builder().setCurrency(currency).addFeeOrCredit(createFeeOrCredit);
// Don't charge anchor tenants EAP fees. // Don't charge anchor tenants EAP fees.
@ -92,7 +98,7 @@ public final class DomainPricingLogic {
.setFeesAndCredits(feesBuilder.build()) .setFeesAndCredits(feesBuilder.build())
.setRegistry(registry) .setRegistry(registry)
.setDomainName(InternetDomainName.from(domainName)) .setDomainName(InternetDomainName.from(domainName))
.setAsOfDate(date) .setAsOfDate(dateTime)
.setYears(years) .setYears(years)
.build()); .build());
} }
@ -100,69 +106,73 @@ public final class DomainPricingLogic {
/** Returns a new renew price for the pricer. */ /** Returns a new renew price for the pricer. */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public FeesAndCredits getRenewPrice( public FeesAndCredits getRenewPrice(
Registry registry, Registry registry, String domainName, DateTime dateTime, int years) throws EppException {
String domainName, DomainPrices domainPrices = getPricesForDomainName(domainName, dateTime);
DateTime date, BigDecimal renewCost = domainPrices.getRenewCost().multipliedBy(years).getAmount();
int years)
throws EppException {
Money renewCost = getDomainRenewCost(domainName, date, years);
return customLogic.customizeRenewPrice( return customLogic.customizeRenewPrice(
RenewPriceParameters.newBuilder() RenewPriceParameters.newBuilder()
.setFeesAndCredits( .setFeesAndCredits(
new FeesAndCredits.Builder() new FeesAndCredits.Builder()
.setCurrency(registry.getCurrency()) .setCurrency(registry.getCurrency())
.addFeeOrCredit(Fee.create(renewCost.getAmount(), FeeType.RENEW)) .addFeeOrCredit(Fee.create(renewCost, FeeType.RENEW, domainPrices.isPremium()))
.build()) .build())
.setRegistry(registry) .setRegistry(registry)
.setDomainName(InternetDomainName.from(domainName)) .setDomainName(InternetDomainName.from(domainName))
.setAsOfDate(date) .setAsOfDate(dateTime)
.setYears(years) .setYears(years)
.build()); .build());
} }
/** Returns a new restore price for the pricer. */ /** Returns a new restore price for the pricer. */
public FeesAndCredits getRestorePrice(Registry registry, String domainName, DateTime date) public FeesAndCredits getRestorePrice(Registry registry, String domainName, DateTime dateTime)
throws EppException { throws EppException {
DomainPrices domainPrices = getPricesForDomainName(domainName, dateTime);
FeesAndCredits feesAndCredits = FeesAndCredits feesAndCredits =
new FeesAndCredits.Builder() new FeesAndCredits.Builder()
.setCurrency(registry.getCurrency()) .setCurrency(registry.getCurrency())
.addFeeOrCredit( .addFeeOrCredit(
Fee.create(getDomainRenewCost(domainName, date, 1).getAmount(), FeeType.RENEW)) Fee.create(
domainPrices.getRenewCost().getAmount(),
FeeType.RENEW,
domainPrices.isPremium()))
.addFeeOrCredit( .addFeeOrCredit(
Fee.create(registry.getStandardRestoreCost().getAmount(), FeeType.RESTORE)) Fee.create(registry.getStandardRestoreCost().getAmount(), FeeType.RESTORE, false))
.build(); .build();
return customLogic.customizeRestorePrice( return customLogic.customizeRestorePrice(
RestorePriceParameters.newBuilder() RestorePriceParameters.newBuilder()
.setFeesAndCredits(feesAndCredits) .setFeesAndCredits(feesAndCredits)
.setRegistry(registry) .setRegistry(registry)
.setDomainName(InternetDomainName.from(domainName)) .setDomainName(InternetDomainName.from(domainName))
.setAsOfDate(date) .setAsOfDate(dateTime)
.build()); .build());
} }
/** Returns a new transfer price for the pricer. */ /** Returns a new transfer price for the pricer. */
public FeesAndCredits getTransferPrice(Registry registry, String domainName, DateTime date) public FeesAndCredits getTransferPrice(Registry registry, String domainName, DateTime dateTime)
throws EppException { throws EppException {
Money renewCost = getDomainRenewCost(domainName, date, 1); DomainPrices domainPrices = getPricesForDomainName(domainName, dateTime);
return customLogic.customizeTransferPrice( return customLogic.customizeTransferPrice(
TransferPriceParameters.newBuilder() TransferPriceParameters.newBuilder()
.setFeesAndCredits( .setFeesAndCredits(
new FeesAndCredits.Builder() new FeesAndCredits.Builder()
.setCurrency(registry.getCurrency()) .setCurrency(registry.getCurrency())
.addFeeOrCredit(Fee.create(renewCost.getAmount(), FeeType.RENEW)) .addFeeOrCredit(
Fee.create(
domainPrices.getRenewCost().getAmount(),
FeeType.RENEW,
domainPrices.isPremium()))
.build()) .build())
.setRegistry(registry) .setRegistry(registry)
.setDomainName(InternetDomainName.from(domainName)) .setDomainName(InternetDomainName.from(domainName))
.setAsOfDate(date) .setAsOfDate(dateTime)
.build()); .build());
} }
/** Returns a new update price for the pricer. */ /** Returns a new update price for the pricer. */
public FeesAndCredits getUpdatePrice(Registry registry, String domainName, DateTime date) public FeesAndCredits getUpdatePrice(Registry registry, String domainName, DateTime dateTime)
throws EppException { throws EppException {
CurrencyUnit currency = registry.getCurrency(); CurrencyUnit currency = registry.getCurrency();
BaseFee feeOrCredit = BaseFee feeOrCredit = Fee.create(zeroInCurrency(currency), FeeType.UPDATE, false);
Fee.create(Money.zero(registry.getCurrency()).getAmount(), FeeType.UPDATE);
return customLogic.customizeUpdatePrice( return customLogic.customizeUpdatePrice(
UpdatePriceParameters.newBuilder() UpdatePriceParameters.newBuilder()
.setFeesAndCredits( .setFeesAndCredits(
@ -172,19 +182,19 @@ public final class DomainPricingLogic {
.build()) .build())
.setRegistry(registry) .setRegistry(registry)
.setDomainName(InternetDomainName.from(domainName)) .setDomainName(InternetDomainName.from(domainName))
.setAsOfDate(date) .setAsOfDate(dateTime)
.build()); .build());
} }
/** Returns the fee class for a given domain and date. */ /** Returns the fee class for a given domain and date. */
public Optional<String> getFeeClass(String domainName, DateTime date) { public Optional<String> getFeeClass(String domainName, DateTime dateTime) {
return getDomainFeeClass(domainName, date); return getDomainFeeClass(domainName, dateTime);
} }
/** Returns the domain create cost with allocation-token-related discounts applied. */
private Money getDomainCreateCostWithDiscount( private Money getDomainCreateCostWithDiscount(
String domainName, DateTime date, int years, Optional<AllocationToken> allocationToken) DomainPrices domainPrices, int years, Optional<AllocationToken> allocationToken)
throws EppException { throws EppException {
DomainPrices domainPrices = PricingEngineProxy.getPricesForDomainName(domainName, date);
if (allocationToken.isPresent() if (allocationToken.isPresent()
&& allocationToken.get().getDiscountFraction() != 0.0 && allocationToken.get().getDiscountFraction() != 0.0
&& domainPrices.isPremium()) { && domainPrices.isPremium()) {

View file

@ -211,8 +211,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
BeforeResponseParameters.newBuilder() BeforeResponseParameters.newBuilder()
.setDomain(newDomain) .setDomain(newDomain)
.setResData(DomainRenewData.create(targetId, newExpirationTime)) .setResData(DomainRenewData.create(targetId, newExpirationTime))
.setResponseExtensions( .setResponseExtensions(createResponseExtensions(feesAndCredits, feeRenew))
createResponseExtensions(feesAndCredits.getTotalCost(), feeRenew))
.build()); .build());
return responseBuilder return responseBuilder
.setResData(responseData.resData()) .setResData(responseData.resData())
@ -270,14 +269,19 @@ public final class DomainRenewFlow implements TransactionalFlow {
} }
private ImmutableList<FeeTransformResponseExtension> createResponseExtensions( private ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
Money renewCost, Optional<FeeRenewCommandExtension> feeRenew) { FeesAndCredits feesAndCredits, Optional<FeeRenewCommandExtension> feeRenew) {
return feeRenew.isPresent() return feeRenew.isPresent()
? ImmutableList.of( ? ImmutableList.of(
feeRenew feeRenew
.get() .get()
.createResponseBuilder() .createResponseBuilder()
.setCurrency(renewCost.getCurrencyUnit()) .setCurrency(feesAndCredits.getCurrency())
.setFees(ImmutableList.of(Fee.create(renewCost.getAmount(), FeeType.RENEW))) .setFees(
ImmutableList.of(
Fee.create(
feesAndCredits.getRenewCost().getAmount(),
FeeType.RENEW,
feesAndCredits.hasPremiumFeesOfType(FeeType.RENEW))))
.build()) .build())
: ImmutableList.of(); : ImmutableList.of();
} }

View file

@ -176,9 +176,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
ofy().delete().key(existingDomain.getDeletePollMessage()); ofy().delete().key(existingDomain.getDeletePollMessage());
dnsQueue.addDomainRefreshTask(existingDomain.getFullyQualifiedDomainName()); dnsQueue.addDomainRefreshTask(existingDomain.getFullyQualifiedDomainName());
return responseBuilder return responseBuilder
.setExtensions( .setExtensions(createResponseExtensions(feesAndCredits, feeUpdate))
createResponseExtensions(
feesAndCredits.getRestoreCost(), feesAndCredits.getRenewCost(), feeUpdate))
.build(); .build();
} }
@ -265,17 +263,23 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
} }
private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions( private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
Money restoreCost, Money renewCost, Optional<FeeUpdateCommandExtension> feeUpdate) { FeesAndCredits feesAndCredits, Optional<FeeUpdateCommandExtension> feeUpdate) {
return feeUpdate.isPresent() return feeUpdate.isPresent()
? ImmutableList.of( ? ImmutableList.of(
feeUpdate feeUpdate
.get() .get()
.createResponseBuilder() .createResponseBuilder()
.setCurrency(restoreCost.getCurrencyUnit()) .setCurrency(feesAndCredits.getCurrency())
.setFees( .setFees(
ImmutableList.of( ImmutableList.of(
Fee.create(restoreCost.getAmount(), FeeType.RESTORE), Fee.create(
Fee.create(renewCost.getAmount(), FeeType.RENEW))) feesAndCredits.getRestoreCost().getAmount(),
FeeType.RESTORE,
feesAndCredits.hasPremiumFeesOfType(FeeType.RESTORE)),
Fee.create(
feesAndCredits.getRenewCost().getAmount(),
FeeType.RENEW,
feesAndCredits.hasPremiumFeesOfType(FeeType.RENEW))))
.build()) .build())
: ImmutableList.of(); : ImmutableList.of();
} }

View file

@ -15,6 +15,7 @@
package google.registry.flows.domain; package google.registry.flows.domain;
import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.flows.domain.DomainFlowUtils.zeroInCurrency;
import static google.registry.util.CollectionUtils.nullToEmpty; import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy; import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
@ -27,6 +28,7 @@ import google.registry.model.domain.fee.BaseFee;
import google.registry.model.domain.fee.BaseFee.FeeType; import google.registry.model.domain.fee.BaseFee.FeeType;
import google.registry.model.domain.fee.Credit; import google.registry.model.domain.fee.Credit;
import google.registry.model.domain.fee.Fee; import google.registry.model.domain.fee.Fee;
import java.math.BigDecimal;
import org.joda.money.CurrencyUnit; import org.joda.money.CurrencyUnit;
import org.joda.money.Money; import org.joda.money.Money;
@ -39,26 +41,30 @@ public class FeesAndCredits extends ImmutableObject implements Buildable {
private ImmutableList<Credit> credits; private ImmutableList<Credit> credits;
private Money getTotalCostForType(FeeType type) { private Money getTotalCostForType(FeeType type) {
Money result = Money.zero(currency);
checkArgumentNotNull(type); checkArgumentNotNull(type);
for (Fee fee : fees) { return Money.of(
if (fee.getType() == type) { currency,
result = result.plus(fee.getCost()); fees.stream()
.filter(f -> f.getType() == type)
.map(BaseFee::getCost)
.reduce(zeroInCurrency(currency), BigDecimal::add));
} }
}
return result; public boolean hasPremiumFeesOfType(FeeType type) {
return fees.stream().filter(f -> f.getType() == type).anyMatch(BaseFee::isPremium);
} }
/** Returns the total cost of all fees and credits for the event. */ /** Returns the total cost of all fees and credits for the event. */
public Money getTotalCost() { public Money getTotalCost() {
Money result = Money.zero(currency); return Money.of(
for (Fee fee : fees) { currency,
result = result.plus(fee.getCost()); Streams.concat(fees.stream(), credits.stream())
.map(BaseFee::getCost)
.reduce(zeroInCurrency(currency), BigDecimal::add));
} }
for (Credit credit : credits) {
result = result.plus(credit.getCost()); public boolean hasAnyPremiumFees() {
} return fees.stream().anyMatch(BaseFee::isPremium);
return result;
} }
/** Returns the create cost for the event. */ /** Returns the create cost for the event. */

View file

@ -104,6 +104,8 @@ public abstract class BaseFee extends ImmutableObject {
@XmlTransient Range<DateTime> validDateRange; @XmlTransient Range<DateTime> validDateRange;
@XmlTransient boolean isPremium;
public String getDescription() { public String getDescription() {
return description; return description;
} }
@ -120,6 +122,11 @@ public abstract class BaseFee extends ImmutableObject {
return firstNonNull(refundable, true); return firstNonNull(refundable, true);
} }
/** Returns whether the fee in question is a premium price. */
public boolean isPremium() {
return isPremium;
}
/** /**
* According to the fee extension specification, a fee must always be non-negative, while a credit * According to the fee extension specification, a fee must always be non-negative, while a credit
* must always be negative. Essentially, they are the same thing, just with different sign. * must always be negative. Essentially, they are the same thing, just with different sign.

View file

@ -31,25 +31,33 @@ import org.joda.time.DateTime;
public class Fee extends BaseFee { public class Fee extends BaseFee {
/** Creates a Fee for the given cost and type with the default description. */ /** Creates a Fee for the given cost and type with the default description. */
public static Fee create(BigDecimal cost, FeeType type, Object... descriptionArgs) { public static Fee create(
BigDecimal cost, FeeType type, boolean isPremium, Object... descriptionArgs) {
checkArgumentNotNull(type, "Must specify the type of the fee"); checkArgumentNotNull(type, "Must specify the type of the fee");
return createWithCustomDescription(cost, type, type.renderDescription(descriptionArgs)); return createWithCustomDescription(
cost, type, isPremium, type.renderDescription(descriptionArgs));
} }
/** Creates a Fee for the given cost, type, and valid date range with the default description. */ /** Creates a Fee for the given cost, type, and valid date range with the default description. */
public static Fee create( public static Fee create(
BigDecimal cost, FeeType type, Range<DateTime> validDateRange, Object... descriptionArgs) { BigDecimal cost,
Fee instance = create(cost, type, descriptionArgs); FeeType type,
boolean isPremium,
Range<DateTime> validDateRange,
Object... descriptionArgs) {
Fee instance = create(cost, type, isPremium, descriptionArgs);
instance.validDateRange = validDateRange; instance.validDateRange = validDateRange;
return instance; return instance;
} }
/** Creates a Fee for the given cost and type with a custom description. */ /** Creates a Fee for the given cost and type with a custom description. */
public static Fee createWithCustomDescription(BigDecimal cost, FeeType type, String description) { private static Fee createWithCustomDescription(
BigDecimal cost, FeeType type, boolean isPremium, String description) {
Fee instance = new Fee(); Fee instance = new Fee();
instance.cost = checkNotNull(cost); instance.cost = checkNotNull(cost);
checkArgument(instance.cost.signum() >= 0); checkArgument(instance.cost.signum() >= 0, "Cost must be a positive number");
instance.type = checkNotNull(type); instance.type = checkNotNull(type);
instance.isPremium = isPremium;
instance.description = description; instance.description = description;
return instance; return instance;
} }

View file

@ -56,7 +56,7 @@ public class FeeCheckCommandExtensionV11 extends ImmutableObject
/** The period to check. */ /** The period to check. */
Period period; Period period;
/** The class to check. */ /** The fee class to check. */
@XmlElement(name = "class") @XmlElement(name = "class")
String feeClass; String feeClass;

View file

@ -579,6 +579,8 @@ public class Registry extends ImmutableObject implements Buildable {
return Fee.create( return Fee.create(
eapFeeSchedule.getValueAtTime(now).getAmount(), eapFeeSchedule.getValueAtTime(now).getAmount(),
FeeType.EAP, FeeType.EAP,
// An EAP fee counts as premium so the domain's overall Fee doesn't show as standard-priced.
true,
validPeriod, validPeriod,
validPeriod.upperEndpoint()); validPeriod.upperEndpoint());
} }

View file

@ -40,7 +40,7 @@ public class TestDomainPricingCustomLogic extends DomainPricingCustomLogic {
public FeesAndCredits customizeRenewPrice(RenewPriceParameters priceParameters) { public FeesAndCredits customizeRenewPrice(RenewPriceParameters priceParameters) {
return priceParameters.domainName().toString().startsWith("costly-renew") return priceParameters.domainName().toString().startsWith("costly-renew")
? addCustomFee( ? addCustomFee(
priceParameters.feesAndCredits(), Fee.create(ONE_HUNDRED_BUCKS, FeeType.RENEW)) priceParameters.feesAndCredits(), Fee.create(ONE_HUNDRED_BUCKS, FeeType.RENEW, true))
: priceParameters.feesAndCredits(); : priceParameters.feesAndCredits();
} }
@ -48,7 +48,7 @@ public class TestDomainPricingCustomLogic extends DomainPricingCustomLogic {
public FeesAndCredits customizeTransferPrice(TransferPriceParameters priceParameters) { public FeesAndCredits customizeTransferPrice(TransferPriceParameters priceParameters) {
return priceParameters.domainName().toString().startsWith("expensive") return priceParameters.domainName().toString().startsWith("expensive")
? addCustomFee( ? addCustomFee(
priceParameters.feesAndCredits(), Fee.create(ONE_HUNDRED_BUCKS, FeeType.TRANSFER)) priceParameters.feesAndCredits(), Fee.create(ONE_HUNDRED_BUCKS, FeeType.TRANSFER, true))
: priceParameters.feesAndCredits(); : priceParameters.feesAndCredits();
} }
@ -56,7 +56,7 @@ public class TestDomainPricingCustomLogic extends DomainPricingCustomLogic {
public FeesAndCredits customizeUpdatePrice(UpdatePriceParameters priceParameters) { public FeesAndCredits customizeUpdatePrice(UpdatePriceParameters priceParameters) {
return priceParameters.domainName().toString().startsWith("non-free-update") return priceParameters.domainName().toString().startsWith("non-free-update")
? addCustomFee( ? addCustomFee(
priceParameters.feesAndCredits(), Fee.create(ONE_HUNDRED_BUCKS, FeeType.UPDATE)) priceParameters.feesAndCredits(), Fee.create(ONE_HUNDRED_BUCKS, FeeType.UPDATE, true))
: priceParameters.feesAndCredits(); : priceParameters.feesAndCredits();
} }

View file

@ -108,7 +108,8 @@ public class DomainTransferFlowTestCase<F extends Flow, R extends EppResource>
clock.nowUtc(), clock.nowUtc(),
DateTime.parse("1999-04-03T22:00:00.0Z"), DateTime.parse("1999-04-03T22:00:00.0Z"),
REGISTRATION_EXPIRATION_TIME); REGISTRATION_EXPIRATION_TIME);
subordinateHost = persistResource( subordinateHost =
persistResource(
new HostResource.Builder() new HostResource.Builder()
.setRepoId("2-".concat(Ascii.toUpperCase(tld))) .setRepoId("2-".concat(Ascii.toUpperCase(tld)))
.setFullyQualifiedHostName("ns1." + label + "." + tld) .setFullyQualifiedHostName("ns1." + label + "." + tld)