1
0
mirror of https://github.com/google/nomulus synced 2026-04-14 05:27:26 +00:00

Use the createBillingCostTransitions map to get the create cost for a domain (#2390)

* Use the createBillingCostTransitions map to get the create cost for a domain

* Add comment

* Add some TODOs

* use streams to check currency unit
This commit is contained in:
sarahcaseybot
2024-04-05 17:27:55 -04:00
committed by GitHub
parent 96e33f5b4f
commit 4f1ca920a7
23 changed files with 190 additions and 149 deletions

View File

@@ -42,7 +42,7 @@ public final class StaticPremiumListPricingEngine implements PremiumPricingEngin
tld.getPremiumListName().flatMap(pl -> PremiumListDao.getPremiumPrice(pl, label));
return DomainPrices.create(
premiumPrice.isPresent(),
premiumPrice.orElse(tld.getCreateBillingCost()),
premiumPrice.orElse(tld.getCreateBillingCost(priceTime)),
premiumPrice.orElse(tld.getStandardRenewCost(priceTime)));
}
}

View File

@@ -74,7 +74,6 @@ import google.registry.tldconfig.idn.IdnTableEnum;
import google.registry.util.Idn;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
@@ -138,10 +137,7 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
try {
String thisYaml = mapper.writeValueAsString(this);
String otherYaml = mapper.writeValueAsString(tldToCompare);
// Since Jackson uses getters and not field values to construct the YAML representation, an
// explicit check of the createBillingCostTransitions is necessary since this field is
// auto-populated in the getter when the field is set to null.
return thisYaml.equals(otherYaml) && createBillingCostTransitionsEqual(tldToCompare);
return thisYaml.equals(otherYaml);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
@@ -465,6 +461,7 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
// TODO(sarahbot@): Remove this field and make createBillingCostTransitions not-null once all TLDs
// are populated with a create cost transition map
/** The per-year billing cost for registering a new domain name. */
@Deprecated
@Type(type = JodaMoneyType.TYPE_NAME)
@Columns(
columns = {
@@ -473,11 +470,13 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
})
Money createBillingCost = DEFAULT_CREATE_BILLING_COST;
// TODO(sarahbot@): Make this field not null and add a default value once field is populated on
// all existing TLDs
// TODO(sarahbot@): Make this field not null in the database
// TODO(sarahbot@): Rename this field to createBillingCost once the old createBillingCost has been
// removed
/** A property that transitions to different create billing costs at different times. */
@JsonDeserialize(using = TimedTransitionPropertyMoneyDeserializer.class)
TimedTransitionProperty<Money> createBillingCostTransitions;
TimedTransitionProperty<Money> createBillingCostTransitions =
TimedTransitionProperty.withInitialValue(DEFAULT_CREATE_BILLING_COST);
/** The one-time billing cost for restoring a domain name from the redemption grace period. */
@Type(type = JodaMoneyType.TYPE_NAME)
@@ -684,24 +683,20 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
* domain create.
*/
@VisibleForTesting
public Money getCreateBillingCost(DateTime now) {
return createBillingCostTransitions.getValueAtTime(now);
}
// This getter is still necessary for the Jackson deserialization in the ConfigureTldCommand
// TODO(sarahbot@): Remove this getter once the deprecated createBillingCost field is removed from
// the schema
@Deprecated
public Money getCreateBillingCost() {
return createBillingCost;
}
public ImmutableSortedMap<DateTime, Money> getCreateBillingCostTransitions() {
return Objects.requireNonNullElseGet(
createBillingCostTransitions,
() -> TimedTransitionProperty.withInitialValue(getCreateBillingCost()))
.toValueMap();
}
public boolean createBillingCostTransitionsEqual(Tld newTld) {
if (createBillingCostTransitions == null) {
return false;
}
return createBillingCostTransitions
.toValueMap()
.equals(newTld.getCreateBillingCostTransitions());
return createBillingCostTransitions.toValueMap();
}
/**
@@ -1171,16 +1166,14 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
// and cloned it into a new builder, to block re-building a Tld in an invalid state.
instance.tldStateTransitions.checkValidity();
// TODO(sarahbot@): Remove null check when createBillingCostTransitions field is made not-null
if (instance.createBillingCostTransitions != null) {
instance.createBillingCostTransitions.checkValidity();
}
checkArgumentNotNull(
instance.getCreateBillingCostTransitions(),
"CreateBillingCostTransitions cannot be null");
instance.createBillingCostTransitions.checkValidity();
instance.renewBillingCostTransitions.checkValidity();
instance.eapFeeSchedule.checkValidity();
// All costs must be in the expected currency.
checkArgumentNotNull(instance.getCurrency(), "Currency must be set");
checkArgument(
instance.getCreateBillingCost().getCurrencyUnit().equals(instance.currency),
"Create cost must be in the tld's currency");
checkArgument(
instance.getRestoreBillingCost().getCurrencyUnit().equals(instance.currency),
"Restore cost must be in the TLD's currency");
@@ -1195,6 +1188,9 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl
checkArgument(
instance.getRenewBillingCostTransitions().values().stream().allMatch(currencyCheck),
"Renew cost must be in the TLD's currency");
checkArgument(
instance.getCreateBillingCostTransitions().values().stream().allMatch(currencyCheck),
"Create cost must be in the TLD's currency");
checkArgument(
instance.eapFeeSchedule.toValueMap().values().stream().allMatch(currencyCheck),
"All EAP fees must be in the TLD's currency");

View File

@@ -25,11 +25,9 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import com.google.common.flogger.FluentLogger;
import google.registry.model.common.TimedTransitionProperty;
import google.registry.model.tld.Tld;
import google.registry.model.tld.label.PremiumList;
import google.registry.model.tld.label.PremiumListDao;
@@ -43,11 +41,9 @@ import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.inject.Inject;
import javax.inject.Named;
import org.joda.money.CurrencyUnit;
@@ -123,9 +119,7 @@ public class ConfigureTldCommand extends MutatingCommand {
checkName(name, tldData);
Tld oldTld = getTlds().contains(name) ? Tld.get(name) : null;
checkForMissingFields(
Stream.concat(tldData.keySet().stream(), Stream.of("createBillingCostTransitions"))
.collect(toImmutableSet()));
checkForMissingFields(tldData.keySet().stream().collect(toImmutableSet()));
Tld newTld = mapper.readValue(inputFile.toFile(), Tld.class);
if (oldTld != null) {
oldTldInBreakGlass = oldTld.getBreakglassMode();
@@ -156,14 +150,6 @@ public class ConfigureTldCommand extends MutatingCommand {
checkPremiumList(newTld);
checkDnsWriters(newTld);
checkCurrency(newTld);
// TODO(sarahbot@): Remove this once the createBillingCost field is removed
checkArgument(
Objects.equals(
TimedTransitionProperty.fromValueMap(newTld.getCreateBillingCostTransitions())
.getValueAtTime(clock.nowUtc()),
newTld.getCreateBillingCost()),
"The createBillingCostTransitions map must have the same current cost as the"
+ " createBillingCost field");
// bsaEnrollStartTime only exists in DB. Need to carry it over to the updated copy. See Tld.java
// for more information.
Optional<DateTime> bsaEnrollTime =
@@ -259,9 +245,6 @@ public class ConfigureTldCommand extends MutatingCommand {
private void checkCurrency(Tld newTld) {
CurrencyUnit currencyUnit = newTld.getCurrency();
checkArgument(
currencyUnit.equals(newTld.getCreateBillingCost().getCurrencyUnit()),
"createBillingCost must use the same currency as the TLD");
checkArgument(
currencyUnit.equals(newTld.getRestoreBillingCost().getCurrencyUnit()),
"restoreBillingCost must use the same currency as the TLD");
@@ -271,19 +254,38 @@ public class ConfigureTldCommand extends MutatingCommand {
checkArgument(
currencyUnit.equals(newTld.getRegistryLockOrUnlockBillingCost().getCurrencyUnit()),
"registryLockOrUnlockBillingCost must use the same currency as the TLD");
ImmutableSortedMap<DateTime, Money> renewBillingCostTransitions =
newTld.getRenewBillingCostTransitions();
for (Money renewBillingCost : renewBillingCostTransitions.values()) {
checkArgument(
renewBillingCost.getCurrencyUnit().equals(currencyUnit),
"All Money values in the renewBillingCostTransitions map must use the TLD's currency"
+ " unit");
}
ImmutableSortedMap<DateTime, Money> eapFeeSchedule = newTld.getEapFeeScheduleAsMap();
for (Money eapFee : eapFeeSchedule.values()) {
checkArgument(
eapFee.getCurrencyUnit().equals(currencyUnit),
"All Money values in the eapFeeSchedule map must use the TLD's currency unit");
}
ImmutableSet<CurrencyUnit> currencies =
newTld.getRenewBillingCostTransitions().values().stream()
.map(Money::getCurrencyUnit)
.distinct()
.collect(toImmutableSet());
checkArgument(
currencies.size() == 1 && currencies.contains(currencyUnit),
"All Money values in the renewBillingCostTransitions map must use the TLD's currency unit"
+ " %s. Found %s currency unit(s) in the renewBillingCostTransitionsMap",
currencyUnit,
currencies);
ImmutableSet<CurrencyUnit> createCurrencies =
newTld.getCreateBillingCostTransitions().values().stream()
.map(Money::getCurrencyUnit)
.distinct()
.collect(toImmutableSet());
checkArgument(
createCurrencies.size() == 1 && createCurrencies.contains(currencyUnit),
"All Money values in the createBillingCostTransitions map must use the TLD's currency unit"
+ " %s. Found %s currency unit(s) in the createBillingCostTransitionsMap",
currencyUnit,
createCurrencies);
ImmutableSet<CurrencyUnit> eapCurrencies =
newTld.getEapFeeScheduleAsMap().values().stream()
.map(Money::getCurrencyUnit)
.distinct()
.collect(toImmutableSet());
checkArgument(
eapCurrencies.size() == 1 && eapCurrencies.contains(currencyUnit),
"All Money values in the eapFeeSchedule map must use the TLD's currency unit"
+ " %s. Found %s currency unit(s) in the eapFeeSchedule",
currencyUnit,
eapCurrencies);
}
}

View File

@@ -751,7 +751,8 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
Tld.get("tld")
.asBuilder()
.setCurrency(JPY)
.setCreateBillingCost(Money.ofMajor(JPY, 800))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))
.setRenewBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))
@@ -1344,7 +1345,12 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
// Note that the response xml expects to see "11.10" with two digits after the decimal point.
// This works because Money.getAmount(), used in the flow, returns a BigDecimal that is set to
// display the number of digits that is conventional for the given currency.
persistResource(Tld.get("tld").asBuilder().setCreateBillingCost(Money.of(USD, 11.1)).build());
persistResource(
Tld.get("tld")
.asBuilder()
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 11.1)))
.build());
setEppInput("domain_check_fee_fractional.xml");
runFlowAssertResponse(loadFile("domain_check_fee_fractional_response.xml"));
}

View File

@@ -134,7 +134,8 @@ public class DomainClaimsCheckFlowTest extends ResourceFlowTestCase<DomainClaims
Tld.get("tld")
.asBuilder()
.setCurrency(JPY)
.setCreateBillingCost(Money.ofMajor(JPY, 800))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))
.setRenewBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))

View File

@@ -1086,7 +1086,12 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
@Test
void testFailure_wrongFeeAmount_v06() {
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6", "CURRENCY", "USD"));
persistResource(Tld.get("tld").asBuilder().setCreateBillingCost(Money.of(USD, 20)).build());
persistResource(
Tld.get("tld")
.asBuilder()
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 20)))
.build());
persistContactsAndHosts();
EppException thrown = assertThrows(FeesMismatchException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
@@ -1107,7 +1112,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
Tld.get("tld")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.setCreateBillingCost(Money.of(USD, 8))
.setCreateBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 8)))
.build());
// Expects fee of $26
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6", "CURRENCY", "USD"));
@@ -1134,7 +1139,8 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
Tld.get("tld")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.setCreateBillingCost(Money.of(USD, 100))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 100)))
.build());
// Expects fee of $26
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6", "CURRENCY", "USD"));
@@ -1146,7 +1152,12 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
@Test
void testFailure_wrongFeeAmount_v11() {
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11", "CURRENCY", "USD"));
persistResource(Tld.get("tld").asBuilder().setCreateBillingCost(Money.of(USD, 20)).build());
persistResource(
Tld.get("tld")
.asBuilder()
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 20)))
.build());
persistContactsAndHosts();
EppException thrown = assertThrows(FeesMismatchException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
@@ -1167,7 +1178,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
Tld.get("tld")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.setCreateBillingCost(Money.of(USD, 8))
.setCreateBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 8)))
.build());
// Expects fee of $26
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11", "CURRENCY", "USD"));
@@ -1194,7 +1205,8 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
Tld.get("tld")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.setCreateBillingCost(Money.of(USD, 100))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 100)))
.build());
// Expects fee of $26
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11", "CURRENCY", "USD"));
@@ -1206,7 +1218,12 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
@Test
void testFailure_wrongFeeAmount_v12() {
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.12", "CURRENCY", "USD"));
persistResource(Tld.get("tld").asBuilder().setCreateBillingCost(Money.of(USD, 20)).build());
persistResource(
Tld.get("tld")
.asBuilder()
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 20)))
.build());
persistContactsAndHosts();
EppException thrown = assertThrows(FeesMismatchException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
@@ -1227,7 +1244,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
Tld.get("tld")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.setCreateBillingCost(Money.of(USD, 8))
.setCreateBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 8)))
.build());
// Expects fee of $26
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.12", "CURRENCY", "USD"));
@@ -1254,7 +1271,8 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
Tld.get("tld")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.setCreateBillingCost(Money.of(USD, 100))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 100)))
.build());
// Expects fee of $26
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.12", "CURRENCY", "USD"));
@@ -2981,7 +2999,8 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
Tld.get("tld")
.asBuilder()
.setCurrency(JPY)
.setCreateBillingCost(Money.ofMajor(JPY, 800))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))
.setRenewBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))

View File

@@ -186,7 +186,8 @@ class DomainFlowUtilsTest extends ResourceFlowTestCase<DomainInfoFlow, Domain> {
.asBuilder()
.setTldType(tldType)
.setCurrency(CHF)
.setCreateBillingCost(Money.ofMajor(CHF, 800))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(CHF, 800)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(CHF, 800)))
.setRenewBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(CHF, 800)))

View File

@@ -1033,7 +1033,8 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
Tld.get("tld")
.asBuilder()
.setCurrency(EUR)
.setCreateBillingCost(Money.of(EUR, 13))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 13)))
.setRestoreBillingCost(Money.of(EUR, 11))
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
@@ -1052,7 +1053,8 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
Tld.get("tld")
.asBuilder()
.setCurrency(EUR)
.setCreateBillingCost(Money.of(EUR, 13))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 13)))
.setRestoreBillingCost(Money.of(EUR, 11))
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
@@ -1071,7 +1073,8 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
Tld.get("tld")
.asBuilder()
.setCurrency(EUR)
.setCreateBillingCost(Money.of(EUR, 13))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 13)))
.setRestoreBillingCost(Money.of(EUR, 11))
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
@@ -1114,7 +1117,8 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
Tld.get("tld")
.asBuilder()
.setCurrency(JPY)
.setCreateBillingCost(Money.ofMajor(JPY, 800))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))
.setRenewBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))

View File

@@ -559,7 +559,8 @@ class DomainRestoreRequestFlowTest extends ResourceFlowTestCase<DomainRestoreReq
Tld.get("tld")
.asBuilder()
.setCurrency(EUR)
.setCreateBillingCost(Money.of(EUR, 13))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 13)))
.setRestoreBillingCost(Money.of(EUR, 11))
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
@@ -702,7 +703,8 @@ class DomainRestoreRequestFlowTest extends ResourceFlowTestCase<DomainRestoreReq
Tld.get("tld")
.asBuilder()
.setCurrency(JPY)
.setCreateBillingCost(Money.ofMajor(JPY, 800))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))
.setRenewBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))

View File

@@ -1070,7 +1070,8 @@ class DomainTransferRequestFlowTest
Tld.get("tld")
.asBuilder()
.setCurrency(JPY)
.setCreateBillingCost(Money.ofMajor(JPY, 800))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))
.setRenewBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 800)))

View File

@@ -65,7 +65,8 @@ class RegistrarTest extends EntityTestCase {
newTld("xn--q9jyb4c", "MINNA")
.asBuilder()
.setCurrency(JPY)
.setCreateBillingCost(Money.of(JPY, new BigDecimal(1300)))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(JPY, new BigDecimal(1300))))
.setRestoreBillingCost(Money.of(JPY, new BigDecimal(1700)))
.setServerStatusChangeBillingCost(Money.of(JPY, new BigDecimal(1900)))
.setRegistryLockOrUnlockBillingCost(Money.of(JPY, new BigDecimal(2700)))

View File

@@ -223,14 +223,6 @@ public final class TldTest extends EntityTestCase {
.isFalse();
}
@Test
void testSettingCreateBillingCost() {
Tld registry = Tld.get("tld").asBuilder().setCreateBillingCost(Money.of(USD, 42)).build();
assertThat(registry.getCreateBillingCost()).isEqualTo(Money.of(USD, 42));
// The default value of 17 is set in createTld().
assertThat(registry.getRestoreBillingCost()).isEqualTo(Money.of(USD, 17));
}
@Test
void testSetCreateBillingCostTransitions() {
ImmutableSortedMap<DateTime, Money> createCostTransitions =
@@ -246,6 +238,10 @@ public final class TldTest extends EntityTestCase {
Tld registry =
Tld.get("tld").asBuilder().setCreateBillingCostTransitions(createCostTransitions).build();
assertThat(registry.getCreateBillingCostTransitions()).isEqualTo(createCostTransitions);
assertThat(registry.getCreateBillingCost(fakeClock.nowUtc().minus(Duration.standardDays(5))))
.isEqualTo(Money.of(USD, 8));
assertThat(registry.getCreateBillingCost(fakeClock.nowUtc().plusMonths(8)))
.isEqualTo(Money.of(USD, 3));
}
@Test
@@ -275,7 +271,7 @@ public final class TldTest extends EntityTestCase {
void testSettingRestoreBillingCost() {
Tld registry = Tld.get("tld").asBuilder().setRestoreBillingCost(Money.of(USD, 42)).build();
// The default value of 13 is set in createTld().
assertThat(registry.getCreateBillingCost()).isEqualTo(Money.of(USD, 13));
assertThat(registry.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 13));
assertThat(registry.getRestoreBillingCost()).isEqualTo(Money.of(USD, 42));
}
@@ -595,7 +591,13 @@ public final class TldTest extends EntityTestCase {
void testFailure_pricingEngineIsRequired() {
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class, () -> new Tld.Builder().setTldStr("invalid").build());
IllegalArgumentException.class,
() ->
new Tld.Builder()
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 13)))
.setTldStr("invalid")
.build());
assertThat(thrown)
.hasMessageThat()
.contains("All registries must have a configured pricing engine");
@@ -680,8 +682,13 @@ public final class TldTest extends EntityTestCase {
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class,
() -> Tld.get("tld").asBuilder().setCreateBillingCost(Money.of(EUR, 42)).build());
assertThat(thrown).hasMessageThat().contains("cost must be in the tld's currency");
() ->
Tld.get("tld")
.asBuilder()
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 42)))
.build());
assertThat(thrown).hasMessageThat().contains("cost must be in the TLD's currency");
}
@Test

View File

@@ -244,6 +244,7 @@ public final class DatabaseHelper {
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 11)))
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(USD)))
.setCreateBillingCost(Money.of(USD, 13))
.setCreateBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 13)))
.setRestoreBillingCost(Money.of(USD, 17))
.setServerStatusChangeBillingCost(Money.of(USD, 19))
// Always set a default premium list. Tests that don't want it can delete it.

View File

@@ -89,7 +89,7 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
Tld tld = Tld.get("tld");
assertThat(tld).isNotNull();
assertThat(tld.getDriveFolderId()).isEqualTo("driveFolder");
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
assertThat(tld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 25));
testTldConfiguredSuccessfully(tld, "tld.yaml");
assertThat(tld.getBreakglassMode()).isFalse();
}
@@ -101,7 +101,8 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
runCommandForced("--input=" + tldFile);
Tld tld = Tld.get("jpy");
assertThat(tld).isNotNull();
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(JPY, new BigDecimal("250")));
assertThat(tld.getCreateBillingCost(fakeClock.nowUtc()))
.isEqualTo(Money.of(JPY, new BigDecimal("250")));
assertThat(tld.getEapFeeFor(DateTime.now(UTC)).getCost()).isEqualTo(new BigDecimal(0));
testTldConfiguredSuccessfully(tld, "jpy.yaml");
}
@@ -109,12 +110,12 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
@Test
void testSuccess_updateTld() throws Exception {
Tld tld = createTld("tld");
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 13));
assertThat(tld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 13));
File tldFile = tmpDir.resolve("tld.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml"));
runCommandForced("--input=" + tldFile);
Tld updatedTld = Tld.get("tld");
assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
assertThat(updatedTld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 25));
testTldConfiguredSuccessfully(updatedTld, "tld.yaml");
assertThat(updatedTld.getBreakglassMode()).isFalse();
assertThat(tld.getBsaEnrollStartTime()).isEmpty();
@@ -139,8 +140,6 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
tld.asBuilder()
.setIdnTables(ImmutableSet.of(JA, UNCONFUSABLE_LATIN, EXTENDED_LATIN))
.setAllowedFullyQualifiedHostNames(ImmutableSet.of("zeta", "alpha", "gamma", "beta"))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 13)))
.build());
File tldFile = tmpDir.resolve("idns.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "idns.yaml"));
@@ -150,22 +149,6 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
.hasLogAtLevelWithMessage(INFO, "TLD YAML file contains no new changes");
}
@Test
void testSuccess_addCreateCostTransitions_hasDiff() throws Exception {
Tld tld = createTld("idns");
persistResource(
tld.asBuilder()
.setIdnTables(ImmutableSet.of(JA, UNCONFUSABLE_LATIN, EXTENDED_LATIN))
.setAllowedFullyQualifiedHostNames(ImmutableSet.of("zeta", "alpha", "gamma", "beta"))
.build());
File tldFile = tmpDir.resolve("idns.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "idns.yaml"));
runCommandForced("--input=" + tldFile);
Tld updatedTld = Tld.get("idns");
testTldConfiguredSuccessfully(updatedTld, "idns.yaml");
assertThat(tld.createBillingCostTransitionsEqual(updatedTld)).isFalse();
}
@Test
void testSuccess_outOfOrderFieldsOnCreate() throws Exception {
File tldFile = tmpDir.resolve("outoforderfields.yaml").toFile();
@@ -176,21 +159,21 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
// TLD's YAML will contain the fields in the correct order
assertThat(tld).isNotNull();
assertThat(tld.getDriveFolderId()).isEqualTo("driveFolder");
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
assertThat(tld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 25));
assertThat(tld.getPremiumListName().get()).isEqualTo("test");
}
@Test
void testSuccess_outOfOrderFieldsOnUpdate() throws Exception {
Tld tld = createTld("outoforderfields");
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 13));
assertThat(tld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 13));
File tldFile = tmpDir.resolve("outoforderfields.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "outoforderfields.yaml"));
runCommandForced("--input=" + tldFile);
Tld updatedTld = Tld.get("outoforderfields");
// Cannot test that created TLD converted to YAML is equal to original YAML since the created
// TLD's YAML will contain the fields in the correct order
assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
assertThat(updatedTld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 25));
}
@Test
@@ -231,19 +214,6 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
.isEqualTo(ImmutableSortedMap.of(START_OF_TIME, Money.of(USD, 25)));
}
@Test
void testFailure_billingCostTransitionsDoesNotMatchCreateCost() throws Exception {
createTld("diffcostmap");
File tldFile = tmpDir.resolve("diffcostmap.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "diffcostmap.yaml"));
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile));
assertThat(thrown.getMessage())
.isEqualTo(
"The createBillingCostTransitions map must have the same current cost as the"
+ " createBillingCost field");
}
@Test
void testFailure_fileMissingNullableFieldsOnCreate() throws Exception {
File tldFile = tmpDir.resolve("missingnullablefields.yaml").toFile();
@@ -296,7 +266,7 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
Tld tld = Tld.get("nullablefieldsallnull");
assertThat(tld).isNotNull();
assertThat(tld.getDriveFolderId()).isEqualTo(null);
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
assertThat(tld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 25));
// cannot test that created TLD converted to YAML is equal to original YAML since the created
// TLD's YAML will contain empty sets for some of the null fields
assertThat(tld.getIdnTables()).isEmpty();
@@ -314,7 +284,7 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
Tld updatedTld = Tld.get("nullablefieldsallnull");
assertThat(updatedTld).isNotNull();
assertThat(updatedTld.getDriveFolderId()).isEqualTo(null);
assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
assertThat(updatedTld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 25));
// cannot test that created TLD converted to YAML is equal to original YAML since the created
// TLD's YAML will contain empty sets for some of the null fields
assertThat(updatedTld.getIdnTables()).isEmpty();
@@ -387,7 +357,7 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
Tld tld = Tld.get(name);
assertThat(tld).isNotNull();
assertThat(tld.getDriveFolderId()).isEqualTo("driveFolder");
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
assertThat(tld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 25));
String yaml = objectMapper.writeValueAsString(tld);
assertThat(yaml).isEqualTo(fileContents);
}
@@ -505,7 +475,7 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
assertThat(thrown.getMessage())
.isEqualTo(
"All Money values in the renewBillingCostTransitions map must use the TLD's currency"
+ " unit");
+ " unit USD. Found [EUR] currency unit(s) in the renewBillingCostTransitionsMap");
}
@Test
@@ -534,7 +504,7 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
assertThat(thrown.getMessage())
.isEqualTo(
"All Money values in the renewBillingCostTransitions map must use the TLD's currency"
+ " unit");
+ " unit USD. Found [EUR] currency unit(s) in the renewBillingCostTransitionsMap");
}
@Test
@@ -614,12 +584,12 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
@Test
void testSuccess_breakGlassFlag_startsBreakGlassMode() throws Exception {
Tld tld = createTld("tld");
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 13));
assertThat(tld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 13));
File tldFile = tmpDir.resolve("tld.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml"));
runCommandForced("--input=" + tldFile, "--break_glass=true");
Tld updatedTld = Tld.get("tld");
assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
assertThat(updatedTld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 25));
testTldConfiguredSuccessfully(updatedTld, "tld.yaml");
assertThat(updatedTld.getBreakglassMode()).isTrue();
}
@@ -627,13 +597,13 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
@Test
void testSuccess_breakGlassFlag_continuesBreakGlassMode() throws Exception {
Tld tld = createTld("tld");
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 13));
assertThat(tld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 13));
persistResource(tld.asBuilder().setBreakglassMode(true).build());
File tldFile = tmpDir.resolve("tld.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml"));
runCommandForced("--input=" + tldFile, "--break_glass=true");
Tld updatedTld = Tld.get("tld");
assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
assertThat(updatedTld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 25));
testTldConfiguredSuccessfully(updatedTld, "tld.yaml");
assertThat(updatedTld.getBreakglassMode()).isTrue();
}
@@ -712,13 +682,13 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
@Test
void testSuccess_breakGlassFlagFalse_endsBreakGlassMode() throws Exception {
Tld tld = createTld("tld");
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 13));
assertThat(tld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 13));
persistResource(tld.asBuilder().setBreakglassMode(true).build());
File tldFile = tmpDir.resolve("tld.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml"));
runCommandForced("--break_glass=false", "--input=" + tldFile);
Tld updatedTld = Tld.get("tld");
assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
assertThat(updatedTld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 25));
testTldConfiguredSuccessfully(updatedTld, "tld.yaml");
assertThat(updatedTld.getBreakglassMode()).isFalse();
}
@@ -755,12 +725,12 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
@Test
void testSuccess_dryRunOnUpdate_noChanges() throws Exception {
Tld tld = createTld("tld");
assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 13));
assertThat(tld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 13));
File tldFile = tmpDir.resolve("tld.yaml").toFile();
Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml"));
runCommandForced("--input=" + tldFile, "-d");
Tld notUpdatedTld = Tld.get("tld");
assertThat(notUpdatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 13));
assertThat(notUpdatedTld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 13));
}
@Test
@@ -787,7 +757,7 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
runCommandInEnvironment(
RegistryToolEnvironment.PRODUCTION, "--input=" + tldFile, "--break_glass=true", "-f");
Tld updatedTld = Tld.get("tld");
assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
assertThat(updatedTld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 25));
testTldConfiguredSuccessfully(updatedTld, "tld.yaml");
assertThat(updatedTld.getBreakglassMode()).isTrue();
}
@@ -800,7 +770,7 @@ public class ConfigureTldCommandTest extends CommandTestCase<ConfigureTldCommand
runCommandInEnvironment(
RegistryToolEnvironment.PRODUCTION, "--input=" + tldFile, "--build_environment", "-f");
Tld updatedTld = Tld.get("tld");
assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25));
assertThat(updatedTld.getCreateBillingCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 25));
testTldConfiguredSuccessfully(updatedTld, "tld.yaml");
assertThat(updatedTld.getBreakglassMode()).isFalse();
}

View File

@@ -593,7 +593,8 @@ class CreateRegistrarCommandTest extends CommandTestCase<CreateRegistrarCommand>
newTld("foo", "FOO")
.asBuilder()
.setCurrency(JPY)
.setCreateBillingCost(Money.of(JPY, new BigDecimal(1300)))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(JPY, new BigDecimal(1300))))
.setRestoreBillingCost(Money.of(JPY, new BigDecimal(1700)))
.setServerStatusChangeBillingCost(Money.of(JPY, new BigDecimal(1900)))
.setRegistryLockOrUnlockBillingCost(Money.of(JPY, new BigDecimal(2700)))

View File

@@ -449,7 +449,8 @@ class UpdateRegistrarCommandTest extends CommandTestCase<UpdateRegistrarCommand>
newTld("foo", "FOO")
.asBuilder()
.setCurrency(JPY)
.setCreateBillingCost(Money.of(JPY, new BigDecimal(1300)))
.setCreateBillingCostTransitions(
ImmutableSortedMap.of(START_OF_TIME, Money.of(JPY, new BigDecimal(1300))))
.setRestoreBillingCost(Money.of(JPY, new BigDecimal(1700)))
.setServerStatusChangeBillingCost(Money.of(JPY, new BigDecimal(1900)))
.setRegistryLockOrUnlockBillingCost(Money.of(JPY, new BigDecimal(2700)))

View File

@@ -8,6 +8,10 @@ claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
createBillingCost:
currency: "USD"
amount: 25.00
createBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 25.00
creationTime: "2022-09-01T00:00:00.000Z"
currency: "USD"
defaultPromoTokens: []

View File

@@ -8,6 +8,10 @@ claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
createBillingCost:
currency: "USD"
amount: 25.00
createBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 25.00
creationTime: "2022-09-01T00:00:00.000Z"
currency: "USD"
defaultPromoTokens: []

View File

@@ -8,6 +8,10 @@ claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
createBillingCost:
currency: "USD"
amount: 25.00
createBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 25.00
creationTime: "2022-09-01T00:00:00.000Z"
defaultPromoTokens: []
dnsAPlusAaaaTtl: null

View File

@@ -8,6 +8,10 @@ claimsPeriodEnd: "294247-01-10T04:00:54.775Z"
createBillingCost:
currency: "USD"
amount: 25.00
createBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 25.00
creationTime: "2022-09-01T00:00:00.000Z"
currency: "USD"
defaultPromoTokens: []

View File

@@ -30,6 +30,10 @@ currency: "USD"
createBillingCost:
currency: "USD"
amount: 25.00
createBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 25.00
restoreBillingCost:
currency: "USD"
amount: 17.00

View File

@@ -53,3 +53,7 @@ eapFeeSchedule:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 0.00
createBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 25.00

View File

@@ -30,6 +30,10 @@ currency: "USD"
createBillingCost:
currency: "USD"
amount: 25.00
createBillingCostTransitions:
"1970-01-01T00:00:00.000Z":
currency: "USD"
amount: 25.00
restoreBillingCost:
currency: %RESTORECURRENCY%
amount: 70.00