mirror of
https://github.com/google/nomulus.git
synced 2025-07-07 19:53:30 +02:00
Create a separate per-tld registry lock/unlock cost (#800)
* Create a separate per-tld registry lock/unlock cost Currently we use the standard server status change cost for this, but this might not be ideal at some point in the future if we wish to allow manual forced updates outside of the standard registry lock system (we would charge for these manual forced updates, even if we don't charge for registry locks). * Remove period
This commit is contained in:
parent
054571a625
commit
1a63d50b82
10 changed files with 56 additions and 9 deletions
|
@ -133,6 +133,7 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||||
public static final Money DEFAULT_RENEW_BILLING_COST = Money.of(USD, 8);
|
public static final Money DEFAULT_RENEW_BILLING_COST = Money.of(USD, 8);
|
||||||
public static final Money DEFAULT_RESTORE_BILLING_COST = Money.of(USD, 100);
|
public static final Money DEFAULT_RESTORE_BILLING_COST = Money.of(USD, 100);
|
||||||
public static final Money DEFAULT_SERVER_STATUS_CHANGE_BILLING_COST = Money.of(USD, 20);
|
public static final Money DEFAULT_SERVER_STATUS_CHANGE_BILLING_COST = Money.of(USD, 20);
|
||||||
|
public static final Money DEFAULT_REGISTRY_LOCK_OR_UNLOCK_BILLING_COST = Money.of(USD, 0);
|
||||||
|
|
||||||
/** The type of TLD, which determines things like backups and escrow policy. */
|
/** The type of TLD, which determines things like backups and escrow policy. */
|
||||||
public enum TldType {
|
public enum TldType {
|
||||||
|
@ -478,6 +479,9 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||||
})
|
})
|
||||||
Money serverStatusChangeBillingCost = DEFAULT_SERVER_STATUS_CHANGE_BILLING_COST;
|
Money serverStatusChangeBillingCost = DEFAULT_SERVER_STATUS_CHANGE_BILLING_COST;
|
||||||
|
|
||||||
|
/** The one-time billing cost for a registry lock/unlock action initiated by a registrar. */
|
||||||
|
Money registryLockOrUnlockBillingCost = DEFAULT_REGISTRY_LOCK_OR_UNLOCK_BILLING_COST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A property that transitions to different renew billing costs at different times. Stored as a
|
* A property that transitions to different renew billing costs at different times. Stored as a
|
||||||
* list of BillingCostTransition embedded objects using the @Mapify annotation.
|
* list of BillingCostTransition embedded objects using the @Mapify annotation.
|
||||||
|
@ -631,6 +635,11 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||||
return serverStatusChangeBillingCost;
|
return serverStatusChangeBillingCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the cost of a registry lock/unlock. */
|
||||||
|
public Money getRegistryLockOrUnlockBillingCost() {
|
||||||
|
return registryLockOrUnlockBillingCost;
|
||||||
|
}
|
||||||
|
|
||||||
public ImmutableSortedMap<DateTime, TldState> getTldStateTransitions() {
|
public ImmutableSortedMap<DateTime, TldState> getTldStateTransitions() {
|
||||||
return tldStateTransitions.toValueMap();
|
return tldStateTransitions.toValueMap();
|
||||||
}
|
}
|
||||||
|
@ -932,6 +941,12 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder setRegistryLockOrUnlockBillingCost(Money amount) {
|
||||||
|
checkArgument(amount.isPositiveOrZero(), "Registry lock/unlock cost cannot be negative");
|
||||||
|
getInstance().registryLockOrUnlockBillingCost = amount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Builder setLordnUsername(String username) {
|
public Builder setLordnUsername(String username) {
|
||||||
getInstance().lordnUsername = username;
|
getInstance().lordnUsername = username;
|
||||||
return this;
|
return this;
|
||||||
|
@ -983,6 +998,9 @@ public class Registry extends ImmutableObject implements Buildable {
|
||||||
checkArgument(
|
checkArgument(
|
||||||
instance.getServerStatusChangeCost().getCurrencyUnit().equals(instance.currency),
|
instance.getServerStatusChangeCost().getCurrencyUnit().equals(instance.currency),
|
||||||
"Server status change cost must be in the registry's currency");
|
"Server status change cost must be in the registry's currency");
|
||||||
|
checkArgument(
|
||||||
|
instance.getRegistryLockOrUnlockBillingCost().getCurrencyUnit().equals(instance.currency),
|
||||||
|
"Registry lock/unlock cost must be in the registry's currency");
|
||||||
Predicate<Money> currencyCheck =
|
Predicate<Money> currencyCheck =
|
||||||
(Money money) -> money.getCurrencyUnit().equals(instance.currency);
|
(Money money) -> money.getCurrencyUnit().equals(instance.currency);
|
||||||
checkArgument(
|
checkArgument(
|
||||||
|
|
|
@ -110,6 +110,12 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
|
||||||
description = "One-time billing cost for a server status change")
|
description = "One-time billing cost for a server status change")
|
||||||
private Money serverStatusChangeCost;
|
private Money serverStatusChangeCost;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Parameter(
|
||||||
|
names = "--registry_lock_or_unlock_cost",
|
||||||
|
description = "One-time billing cost for a registry lock or unlock")
|
||||||
|
private Money registryLockOrUnlockCost;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Parameter(
|
@Parameter(
|
||||||
names = "--tld_type",
|
names = "--tld_type",
|
||||||
|
@ -326,6 +332,8 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
|
||||||
Optional.ofNullable(roidSuffix).ifPresent(builder::setRoidSuffix);
|
Optional.ofNullable(roidSuffix).ifPresent(builder::setRoidSuffix);
|
||||||
Optional.ofNullable(serverStatusChangeCost)
|
Optional.ofNullable(serverStatusChangeCost)
|
||||||
.ifPresent(builder::setServerStatusChangeBillingCost);
|
.ifPresent(builder::setServerStatusChangeBillingCost);
|
||||||
|
Optional.ofNullable(registryLockOrUnlockCost)
|
||||||
|
.ifPresent(builder::setRegistryLockOrUnlockBillingCost);
|
||||||
Optional.ofNullable(tldType).ifPresent(builder::setTldType);
|
Optional.ofNullable(tldType).ifPresent(builder::setTldType);
|
||||||
Optional.ofNullable(invoicingEnabled).ifPresent(builder::setInvoicingEnabled);
|
Optional.ofNullable(invoicingEnabled).ifPresent(builder::setInvoicingEnabled);
|
||||||
Optional.ofNullable(lordnUsername).ifPresent(u -> builder.setLordnUsername(u.orElse(null)));
|
Optional.ofNullable(lordnUsername).ifPresent(u -> builder.setLordnUsername(u.orElse(null)));
|
||||||
|
|
|
@ -380,7 +380,7 @@ public final class DomainLockUtils {
|
||||||
.setReason(Reason.SERVER_STATUS)
|
.setReason(Reason.SERVER_STATUS)
|
||||||
.setTargetId(domain.getForeignKey())
|
.setTargetId(domain.getForeignKey())
|
||||||
.setClientId(domain.getCurrentSponsorClientId())
|
.setClientId(domain.getCurrentSponsorClientId())
|
||||||
.setCost(Registry.get(domain.getTld()).getServerStatusChangeCost())
|
.setCost(Registry.get(domain.getTld()).getRegistryLockOrUnlockBillingCost())
|
||||||
.setEventTime(now)
|
.setEventTime(now)
|
||||||
.setBillingTime(now)
|
.setBillingTime(now)
|
||||||
.setParent(historyEntry)
|
.setParent(historyEntry)
|
||||||
|
|
|
@ -597,6 +597,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
|
||||||
.setRestoreBillingCost(Money.of(EUR, 11))
|
.setRestoreBillingCost(Money.of(EUR, 11))
|
||||||
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
|
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
|
||||||
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
|
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
|
||||||
|
.setRegistryLockOrUnlockBillingCost(Money.of(EUR, 20))
|
||||||
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
|
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
|
||||||
.build());
|
.build());
|
||||||
persistDomain();
|
persistDomain();
|
||||||
|
@ -615,6 +616,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
|
||||||
.setRestoreBillingCost(Money.of(EUR, 11))
|
.setRestoreBillingCost(Money.of(EUR, 11))
|
||||||
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
|
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
|
||||||
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
|
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
|
||||||
|
.setRegistryLockOrUnlockBillingCost(Money.of(EUR, 20))
|
||||||
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
|
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
|
||||||
.build());
|
.build());
|
||||||
persistDomain();
|
persistDomain();
|
||||||
|
@ -633,6 +635,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
|
||||||
.setRestoreBillingCost(Money.of(EUR, 11))
|
.setRestoreBillingCost(Money.of(EUR, 11))
|
||||||
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
|
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
|
||||||
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
|
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
|
||||||
|
.setRegistryLockOrUnlockBillingCost(Money.of(EUR, 20))
|
||||||
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
|
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
|
||||||
.build());
|
.build());
|
||||||
persistDomain();
|
persistDomain();
|
||||||
|
|
|
@ -533,6 +533,7 @@ class DomainRestoreRequestFlowTest
|
||||||
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
|
.setRenewBillingCostTransitions(ImmutableSortedMap.of(START_OF_TIME, Money.of(EUR, 7)))
|
||||||
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
|
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(EUR)))
|
||||||
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
|
.setServerStatusChangeBillingCost(Money.of(EUR, 19))
|
||||||
|
.setRegistryLockOrUnlockBillingCost(Money.of(EUR, 0))
|
||||||
.build());
|
.build());
|
||||||
EppException thrown = assertThrows(CurrencyUnitMismatchException.class, this::runFlow);
|
EppException thrown = assertThrows(CurrencyUnitMismatchException.class, this::runFlow);
|
||||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||||
|
|
|
@ -69,6 +69,8 @@ class CreateTldCommandTest extends CommandTestCase<CreateTldCommand> {
|
||||||
assertThat(registry.getRedemptionGracePeriodLength())
|
assertThat(registry.getRedemptionGracePeriodLength())
|
||||||
.isEqualTo(Registry.DEFAULT_REDEMPTION_GRACE_PERIOD);
|
.isEqualTo(Registry.DEFAULT_REDEMPTION_GRACE_PERIOD);
|
||||||
assertThat(registry.getPendingDeleteLength()).isEqualTo(Registry.DEFAULT_PENDING_DELETE_LENGTH);
|
assertThat(registry.getPendingDeleteLength()).isEqualTo(Registry.DEFAULT_PENDING_DELETE_LENGTH);
|
||||||
|
assertThat(registry.getRegistryLockOrUnlockBillingCost())
|
||||||
|
.isEqualTo(Registry.DEFAULT_REGISTRY_LOCK_OR_UNLOCK_BILLING_COST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -230,6 +232,17 @@ class CreateTldCommandTest extends CommandTestCase<CreateTldCommand> {
|
||||||
.isEqualTo(Money.of(USD, 42.42));
|
.isEqualTo(Money.of(USD, 42.42));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSuccess_registryLockOrUnlockCostFlag() throws Exception {
|
||||||
|
runCommandForced(
|
||||||
|
"--registry_lock_or_unlock_cost=\"USD 42.42\"",
|
||||||
|
"--roid_suffix=Q9JYB4C",
|
||||||
|
"--dns_writers=VoidDnsWriter",
|
||||||
|
"xn--q9jyb4c");
|
||||||
|
assertThat(Registry.get("xn--q9jyb4c").getRegistryLockOrUnlockBillingCost())
|
||||||
|
.isEqualTo(Money.of(USD, 42.42));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSuccess_nonUsdBillingCostFlag() throws Exception {
|
void testSuccess_nonUsdBillingCostFlag() throws Exception {
|
||||||
runCommandForced(
|
runCommandForced(
|
||||||
|
@ -237,6 +250,7 @@ class CreateTldCommandTest extends CommandTestCase<CreateTldCommand> {
|
||||||
"--restore_billing_cost=\"JPY 67890\"",
|
"--restore_billing_cost=\"JPY 67890\"",
|
||||||
"--initial_renew_billing_cost=\"JPY 101112\"",
|
"--initial_renew_billing_cost=\"JPY 101112\"",
|
||||||
"--server_status_change_cost=\"JPY 97865\"",
|
"--server_status_change_cost=\"JPY 97865\"",
|
||||||
|
"--registry_lock_or_unlock_cost=\"JPY 9001\"",
|
||||||
"--roid_suffix=Q9JYB4C",
|
"--roid_suffix=Q9JYB4C",
|
||||||
"--dns_writers=VoidDnsWriter",
|
"--dns_writers=VoidDnsWriter",
|
||||||
"xn--q9jyb4c");
|
"xn--q9jyb4c");
|
||||||
|
|
|
@ -528,7 +528,7 @@ public final class DomainLockUtilsTest {
|
||||||
.setReason(Reason.SERVER_STATUS)
|
.setReason(Reason.SERVER_STATUS)
|
||||||
.setTargetId(domain.getForeignKey())
|
.setTargetId(domain.getForeignKey())
|
||||||
.setClientId(domain.getCurrentSponsorClientId())
|
.setClientId(domain.getCurrentSponsorClientId())
|
||||||
.setCost(Registry.get(domain.getTld()).getServerStatusChangeCost())
|
.setCost(Registry.get(domain.getTld()).getRegistryLockOrUnlockBillingCost())
|
||||||
.setEventTime(clock.nowUtc())
|
.setEventTime(clock.nowUtc())
|
||||||
.setBillingTime(clock.nowUtc())
|
.setBillingTime(clock.nowUtc())
|
||||||
.setParent(entry)
|
.setParent(entry)
|
||||||
|
|
|
@ -212,19 +212,21 @@ class UpdateTldCommandTest extends CommandTestCase<UpdateTldCommand> {
|
||||||
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 1)))
|
ImmutableSortedMap.of(START_OF_TIME, Money.ofMajor(JPY, 1)))
|
||||||
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(JPY)))
|
.setEapFeeSchedule(ImmutableSortedMap.of(START_OF_TIME, Money.zero(JPY)))
|
||||||
.setServerStatusChangeBillingCost(Money.ofMajor(JPY, 1))
|
.setServerStatusChangeBillingCost(Money.ofMajor(JPY, 1))
|
||||||
|
.setRegistryLockOrUnlockBillingCost(Money.ofMajor(JPY, 1))
|
||||||
.build());
|
.build());
|
||||||
runCommandForced(
|
runCommandForced(
|
||||||
"--create_billing_cost=\"JPY 12345\"",
|
"--create_billing_cost=\"JPY 12345\"",
|
||||||
"--restore_billing_cost=\"JPY 67890\"",
|
"--restore_billing_cost=\"JPY 67890\"",
|
||||||
"--renew_billing_cost_transitions=\"0=JPY 101112\"",
|
"--renew_billing_cost_transitions=\"0=JPY 101112\"",
|
||||||
"--server_status_change_cost=\"JPY 97865\"",
|
"--server_status_change_cost=\"JPY 97865\"",
|
||||||
|
"--registry_lock_or_unlock_cost=\"JPY 9001\"",
|
||||||
"xn--q9jyb4c");
|
"xn--q9jyb4c");
|
||||||
assertThat(Registry.get("xn--q9jyb4c").getStandardCreateCost())
|
Registry registry = Registry.get("xn--q9jyb4c");
|
||||||
.isEqualTo(Money.ofMajor(JPY, 12345));
|
assertThat(registry.getStandardCreateCost()).isEqualTo(Money.ofMajor(JPY, 12345));
|
||||||
assertThat(Registry.get("xn--q9jyb4c").getStandardRestoreCost())
|
assertThat(registry.getStandardRestoreCost()).isEqualTo(Money.ofMajor(JPY, 67890));
|
||||||
.isEqualTo(Money.ofMajor(JPY, 67890));
|
assertThat(registry.getStandardRenewCost(START_OF_TIME)).isEqualTo(Money.ofMajor(JPY, 101112));
|
||||||
assertThat(Registry.get("xn--q9jyb4c").getStandardRenewCost(START_OF_TIME))
|
assertThat(registry.getServerStatusChangeCost()).isEqualTo(Money.ofMajor(JPY, 97865));
|
||||||
.isEqualTo(Money.ofMajor(JPY, 101112));
|
assertThat(registry.getRegistryLockOrUnlockBillingCost()).isEqualTo(Money.ofMajor(JPY, 9001));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -317,7 +317,7 @@ final class RegistryLockVerifyActionTest {
|
||||||
.setReason(Reason.SERVER_STATUS)
|
.setReason(Reason.SERVER_STATUS)
|
||||||
.setTargetId(domain.getForeignKey())
|
.setTargetId(domain.getForeignKey())
|
||||||
.setClientId(domain.getCurrentSponsorClientId())
|
.setClientId(domain.getCurrentSponsorClientId())
|
||||||
.setCost(Registry.get(domain.getTld()).getServerStatusChangeCost())
|
.setCost(Registry.get(domain.getTld()).getRegistryLockOrUnlockBillingCost())
|
||||||
.setEventTime(fakeClock.nowUtc())
|
.setEventTime(fakeClock.nowUtc())
|
||||||
.setBillingTime(fakeClock.nowUtc())
|
.setBillingTime(fakeClock.nowUtc())
|
||||||
.setParent(historyEntry)
|
.setParent(historyEntry)
|
||||||
|
|
|
@ -640,6 +640,7 @@ class google.registry.model.registry.Registry {
|
||||||
java.util.Set<java.lang.String> dnsWriters;
|
java.util.Set<java.lang.String> dnsWriters;
|
||||||
org.joda.money.CurrencyUnit currency;
|
org.joda.money.CurrencyUnit currency;
|
||||||
org.joda.money.Money createBillingCost;
|
org.joda.money.Money createBillingCost;
|
||||||
|
org.joda.money.Money registryLockOrUnlockBillingCost;
|
||||||
org.joda.money.Money restoreBillingCost;
|
org.joda.money.Money restoreBillingCost;
|
||||||
org.joda.money.Money serverStatusChangeBillingCost;
|
org.joda.money.Money serverStatusChangeBillingCost;
|
||||||
org.joda.time.DateTime claimsPeriodEnd;
|
org.joda.time.DateTime claimsPeriodEnd;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue