mirror of
https://github.com/google/nomulus.git
synced 2025-07-22 10:46:10 +02:00
Add renewal support for AT and internal registrations in DomainCreateFlow (#1591)
* Add renewal info to create flow * Improve PR
This commit is contained in:
parent
d0ebbde9ad
commit
fd9fe398ae
2 changed files with 229 additions and 10 deletions
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
package google.registry.flows.domain;
|
package google.registry.flows.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||||
import static google.registry.flows.FlowUtils.persistEntityChanges;
|
import static google.registry.flows.FlowUtils.persistEntityChanges;
|
||||||
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
|
||||||
|
@ -54,6 +55,7 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
|
||||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||||
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
|
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
|
||||||
|
|
||||||
|
import com.google.auto.value.AutoValue;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.net.InternetDomainName;
|
import com.google.common.net.InternetDomainName;
|
||||||
|
@ -80,6 +82,7 @@ import google.registry.model.billing.BillingEvent;
|
||||||
import google.registry.model.billing.BillingEvent.Flag;
|
import google.registry.model.billing.BillingEvent.Flag;
|
||||||
import google.registry.model.billing.BillingEvent.Reason;
|
import google.registry.model.billing.BillingEvent.Reason;
|
||||||
import google.registry.model.billing.BillingEvent.Recurring;
|
import google.registry.model.billing.BillingEvent.Recurring;
|
||||||
|
import google.registry.model.billing.BillingEvent.RenewalPriceBehavior;
|
||||||
import google.registry.model.domain.DomainBase;
|
import google.registry.model.domain.DomainBase;
|
||||||
import google.registry.model.domain.DomainCommand;
|
import google.registry.model.domain.DomainCommand;
|
||||||
import google.registry.model.domain.DomainCommand.Create;
|
import google.registry.model.domain.DomainCommand.Create;
|
||||||
|
@ -115,7 +118,9 @@ import google.registry.model.tld.Registry.TldType;
|
||||||
import google.registry.model.tld.label.ReservationType;
|
import google.registry.model.tld.label.ReservationType;
|
||||||
import google.registry.tmch.LordnTaskUtils;
|
import google.registry.tmch.LordnTaskUtils;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.joda.money.Money;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.Duration;
|
import org.joda.time.Duration;
|
||||||
|
|
||||||
|
@ -327,7 +332,10 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||||
now);
|
now);
|
||||||
// Create a new autorenew billing event and poll message starting at the expiration time.
|
// Create a new autorenew billing event and poll message starting at the expiration time.
|
||||||
BillingEvent.Recurring autorenewBillingEvent =
|
BillingEvent.Recurring autorenewBillingEvent =
|
||||||
createAutorenewBillingEvent(domainHistoryKey, registrationExpirationTime);
|
createAutorenewBillingEvent(
|
||||||
|
domainHistoryKey,
|
||||||
|
registrationExpirationTime,
|
||||||
|
getRenewalPriceInfo(isAnchorTenant, allocationToken, feesAndCredits));
|
||||||
PollMessage.Autorenew autorenewPollMessage =
|
PollMessage.Autorenew autorenewPollMessage =
|
||||||
createAutorenewPollMessage(domainHistoryKey, registrationExpirationTime);
|
createAutorenewPollMessage(domainHistoryKey, registrationExpirationTime);
|
||||||
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
|
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
|
||||||
|
@ -546,7 +554,9 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Recurring createAutorenewBillingEvent(
|
private Recurring createAutorenewBillingEvent(
|
||||||
Key<DomainHistory> domainHistoryKey, DateTime registrationExpirationTime) {
|
Key<DomainHistory> domainHistoryKey,
|
||||||
|
DateTime registrationExpirationTime,
|
||||||
|
RenewalPriceInfo renewalpriceInfo) {
|
||||||
return new BillingEvent.Recurring.Builder()
|
return new BillingEvent.Recurring.Builder()
|
||||||
.setReason(Reason.RENEW)
|
.setReason(Reason.RENEW)
|
||||||
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
||||||
|
@ -555,6 +565,8 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||||
.setEventTime(registrationExpirationTime)
|
.setEventTime(registrationExpirationTime)
|
||||||
.setRecurrenceEndTime(END_OF_TIME)
|
.setRecurrenceEndTime(END_OF_TIME)
|
||||||
.setParent(domainHistoryKey)
|
.setParent(domainHistoryKey)
|
||||||
|
.setRenewalPriceBehavior(renewalpriceInfo.renewalPriceBehavior())
|
||||||
|
.setRenewalPrice(renewalpriceInfo.renewalPrice())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,6 +623,48 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the {@link RenewalPriceBehavior} and the renewal price that needs be stored in the
|
||||||
|
* {@link Recurring} billing events.
|
||||||
|
*
|
||||||
|
* <p>By default, the renewal price is calculated during the process of renewal. Renewal price
|
||||||
|
* should be the createCost if and only if the renewal price behavior in the {@link
|
||||||
|
* AllocationToken} is 'SPECIFIED'.
|
||||||
|
*/
|
||||||
|
static RenewalPriceInfo getRenewalPriceInfo(
|
||||||
|
boolean isAnchorTenant,
|
||||||
|
Optional<AllocationToken> allocationToken,
|
||||||
|
FeesAndCredits feesAndCredits) {
|
||||||
|
if (isAnchorTenant) {
|
||||||
|
if (allocationToken.isPresent()) {
|
||||||
|
checkArgument(
|
||||||
|
allocationToken.get().getRenewalPriceBehavior() != RenewalPriceBehavior.SPECIFIED,
|
||||||
|
"Renewal price behavior cannot be SPECIFIED for anchor tenant");
|
||||||
|
}
|
||||||
|
return RenewalPriceInfo.create(RenewalPriceBehavior.NONPREMIUM, null);
|
||||||
|
} else if (allocationToken.isPresent()
|
||||||
|
&& allocationToken.get().getRenewalPriceBehavior() == RenewalPriceBehavior.SPECIFIED) {
|
||||||
|
return RenewalPriceInfo.create(
|
||||||
|
RenewalPriceBehavior.SPECIFIED, feesAndCredits.getCreateCost());
|
||||||
|
} else {
|
||||||
|
return RenewalPriceInfo.create(RenewalPriceBehavior.DEFAULT, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A class to store renewal info used in {@link Recurring} billing events. */
|
||||||
|
@AutoValue
|
||||||
|
public abstract static class RenewalPriceInfo {
|
||||||
|
static DomainCreateFlow.RenewalPriceInfo create(
|
||||||
|
RenewalPriceBehavior renewalPriceBehavior, @Nullable Money renewalPrice) {
|
||||||
|
return new AutoValue_DomainCreateFlow_RenewalPriceInfo(renewalPriceBehavior, renewalPrice);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract RenewalPriceBehavior renewalPriceBehavior();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public abstract Money renewalPrice();
|
||||||
|
}
|
||||||
|
|
||||||
private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
|
private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
|
||||||
Optional<FeeCreateCommandExtension> feeCreate, FeesAndCredits feesAndCredits) {
|
Optional<FeeCreateCommandExtension> feeCreate, FeesAndCredits feesAndCredits) {
|
||||||
return feeCreate.isPresent()
|
return feeCreate.isPresent()
|
||||||
|
|
|
@ -21,6 +21,9 @@ import static google.registry.flows.FlowTestCase.UserPrivileges.SUPERUSER;
|
||||||
import static google.registry.model.billing.BillingEvent.Flag.ANCHOR_TENANT;
|
import static google.registry.model.billing.BillingEvent.Flag.ANCHOR_TENANT;
|
||||||
import static google.registry.model.billing.BillingEvent.Flag.RESERVED;
|
import static google.registry.model.billing.BillingEvent.Flag.RESERVED;
|
||||||
import static google.registry.model.billing.BillingEvent.Flag.SUNRISE;
|
import static google.registry.model.billing.BillingEvent.Flag.SUNRISE;
|
||||||
|
import static google.registry.model.billing.BillingEvent.RenewalPriceBehavior.DEFAULT;
|
||||||
|
import static google.registry.model.billing.BillingEvent.RenewalPriceBehavior.NONPREMIUM;
|
||||||
|
import static google.registry.model.billing.BillingEvent.RenewalPriceBehavior.SPECIFIED;
|
||||||
import static google.registry.model.domain.fee.Fee.FEE_EXTENSION_URIS;
|
import static google.registry.model.domain.fee.Fee.FEE_EXTENSION_URIS;
|
||||||
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
|
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
|
||||||
import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE;
|
import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE;
|
||||||
|
@ -83,6 +86,7 @@ import google.registry.flows.ResourceFlowTestCase;
|
||||||
import google.registry.flows.domain.DomainCreateFlow.AnchorTenantCreatePeriodException;
|
import google.registry.flows.domain.DomainCreateFlow.AnchorTenantCreatePeriodException;
|
||||||
import google.registry.flows.domain.DomainCreateFlow.MustHaveSignedMarksInCurrentPhaseException;
|
import google.registry.flows.domain.DomainCreateFlow.MustHaveSignedMarksInCurrentPhaseException;
|
||||||
import google.registry.flows.domain.DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException;
|
import google.registry.flows.domain.DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException;
|
||||||
|
import google.registry.flows.domain.DomainCreateFlow.RenewalPriceInfo;
|
||||||
import google.registry.flows.domain.DomainCreateFlow.SignedMarksOnlyDuringSunriseException;
|
import google.registry.flows.domain.DomainCreateFlow.SignedMarksOnlyDuringSunriseException;
|
||||||
import google.registry.flows.domain.DomainFlowTmchUtils.FoundMarkExpiredException;
|
import google.registry.flows.domain.DomainFlowTmchUtils.FoundMarkExpiredException;
|
||||||
import google.registry.flows.domain.DomainFlowTmchUtils.FoundMarkNotYetValidException;
|
import google.registry.flows.domain.DomainFlowTmchUtils.FoundMarkNotYetValidException;
|
||||||
|
@ -149,9 +153,12 @@ import google.registry.flows.exceptions.ResourceCreateContentionException;
|
||||||
import google.registry.model.billing.BillingEvent;
|
import google.registry.model.billing.BillingEvent;
|
||||||
import google.registry.model.billing.BillingEvent.Flag;
|
import google.registry.model.billing.BillingEvent.Flag;
|
||||||
import google.registry.model.billing.BillingEvent.Reason;
|
import google.registry.model.billing.BillingEvent.Reason;
|
||||||
|
import google.registry.model.billing.BillingEvent.RenewalPriceBehavior;
|
||||||
import google.registry.model.domain.DomainBase;
|
import google.registry.model.domain.DomainBase;
|
||||||
import google.registry.model.domain.DomainHistory;
|
import google.registry.model.domain.DomainHistory;
|
||||||
import google.registry.model.domain.GracePeriod;
|
import google.registry.model.domain.GracePeriod;
|
||||||
|
import google.registry.model.domain.fee.BaseFee.FeeType;
|
||||||
|
import google.registry.model.domain.fee.Fee;
|
||||||
import google.registry.model.domain.launch.LaunchNotice;
|
import google.registry.model.domain.launch.LaunchNotice;
|
||||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||||
|
@ -177,6 +184,7 @@ import google.registry.testing.TestOfyAndSql;
|
||||||
import google.registry.testing.TestOfyOnly;
|
import google.registry.testing.TestOfyOnly;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import org.joda.money.Money;
|
import org.joda.money.Money;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
@ -258,13 +266,20 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||||
DomainBase domain = reloadResourceByForeignKey();
|
DomainBase domain = reloadResourceByForeignKey();
|
||||||
|
|
||||||
boolean isAnchorTenant = expectedBillingFlags.contains(ANCHOR_TENANT);
|
boolean isAnchorTenant = expectedBillingFlags.contains(ANCHOR_TENANT);
|
||||||
// Calculate the total creation cost.
|
// Set up the creation cost.
|
||||||
Money creationCost =
|
FeesAndCredits feesAndCredits =
|
||||||
isAnchorTenant
|
new FeesAndCredits.Builder()
|
||||||
? Money.of(USD, 0)
|
.setCurrency(USD)
|
||||||
: isDomainPremium(getUniqueIdFromCommand(), clock.nowUtc())
|
.addFeeOrCredit(
|
||||||
? Money.of(USD, 200)
|
Fee.create(
|
||||||
: Money.of(USD, 26);
|
isAnchorTenant
|
||||||
|
? BigDecimal.valueOf(0)
|
||||||
|
: isDomainPremium(getUniqueIdFromCommand(), clock.nowUtc())
|
||||||
|
? BigDecimal.valueOf(200)
|
||||||
|
: BigDecimal.valueOf(26),
|
||||||
|
FeeType.CREATE,
|
||||||
|
isDomainPremium(getUniqueIdFromCommand(), clock.nowUtc())))
|
||||||
|
.build();
|
||||||
Money eapFee =
|
Money eapFee =
|
||||||
Money.of(
|
Money.of(
|
||||||
Registry.get(domainTld).getCurrency(),
|
Registry.get(domainTld).getCurrency(),
|
||||||
|
@ -284,13 +299,16 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||||
.hasType(HistoryEntry.Type.DOMAIN_CREATE)
|
.hasType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||||
.and()
|
.and()
|
||||||
.hasPeriodYears(2);
|
.hasPeriodYears(2);
|
||||||
|
RenewalPriceInfo renewalPriceInfo =
|
||||||
|
DomainCreateFlow.getRenewalPriceInfo(
|
||||||
|
isAnchorTenant, Optional.ofNullable(allocationToken), feesAndCredits);
|
||||||
// There should be one bill for the create and one for the recurring autorenew event.
|
// There should be one bill for the create and one for the recurring autorenew event.
|
||||||
BillingEvent.OneTime createBillingEvent =
|
BillingEvent.OneTime createBillingEvent =
|
||||||
new BillingEvent.OneTime.Builder()
|
new BillingEvent.OneTime.Builder()
|
||||||
.setReason(Reason.CREATE)
|
.setReason(Reason.CREATE)
|
||||||
.setTargetId(getUniqueIdFromCommand())
|
.setTargetId(getUniqueIdFromCommand())
|
||||||
.setRegistrarId("TheRegistrar")
|
.setRegistrarId("TheRegistrar")
|
||||||
.setCost(creationCost)
|
.setCost(feesAndCredits.getCreateCost())
|
||||||
.setPeriodYears(2)
|
.setPeriodYears(2)
|
||||||
.setEventTime(clock.nowUtc())
|
.setEventTime(clock.nowUtc())
|
||||||
.setBillingTime(billingTime)
|
.setBillingTime(billingTime)
|
||||||
|
@ -308,6 +326,8 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||||
.setEventTime(domain.getRegistrationExpirationTime())
|
.setEventTime(domain.getRegistrationExpirationTime())
|
||||||
.setRecurrenceEndTime(END_OF_TIME)
|
.setRecurrenceEndTime(END_OF_TIME)
|
||||||
.setParent(historyEntry)
|
.setParent(historyEntry)
|
||||||
|
.setRenewalPriceBehavior(renewalPriceInfo.renewalPriceBehavior())
|
||||||
|
.setRenewalPrice(renewalPriceInfo.renewalPrice())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
ImmutableSet.Builder<BillingEvent> expectedBillingEvents =
|
ImmutableSet.Builder<BillingEvent> expectedBillingEvents =
|
||||||
|
@ -1159,6 +1179,28 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||||
assertAllocationTokenWasRedeemed("abcDEF23456");
|
assertAllocationTokenWasRedeemed("abcDEF23456");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testSuccess_internalRegistrationWithSpecifiedRenewalPrice() throws Exception {
|
||||||
|
allocationToken =
|
||||||
|
persistResource(
|
||||||
|
new AllocationToken.Builder()
|
||||||
|
.setToken("abc123")
|
||||||
|
.setTokenType(SINGLE_USE)
|
||||||
|
.setDomainName("resdom.tld")
|
||||||
|
.setRenewalPriceBehavior(SPECIFIED)
|
||||||
|
.build());
|
||||||
|
// Despite the domain being FULLY_BLOCKED, the non-superuser create succeeds the domain is also
|
||||||
|
// RESERVED_FOR_SPECIFIC_USE and the correct allocation token is passed.
|
||||||
|
setEppInput(
|
||||||
|
"domain_create_allocationtoken.xml", ImmutableMap.of("DOMAIN", "resdom.tld", "YEARS", "2"));
|
||||||
|
persistContactsAndHosts();
|
||||||
|
runFlowAssertResponse(
|
||||||
|
loadFile("domain_create_response.xml", ImmutableMap.of("DOMAIN", "resdom.tld")));
|
||||||
|
assertSuccessfulCreate("tld", ImmutableSet.of(RESERVED), allocationToken);
|
||||||
|
assertNoLordn();
|
||||||
|
assertAllocationTokenWasRedeemed("abc123");
|
||||||
|
}
|
||||||
|
|
||||||
@TestOfyAndSql
|
@TestOfyAndSql
|
||||||
void testFailure_anchorTenant_notTwoYearPeriod() {
|
void testFailure_anchorTenant_notTwoYearPeriod() {
|
||||||
setEppInput("domain_create_anchor_tenant_invalid_years.xml");
|
setEppInput("domain_create_anchor_tenant_invalid_years.xml");
|
||||||
|
@ -2594,4 +2636,127 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
||||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
||||||
DatabaseHelper.removeDatabaseMigrationSchedule();
|
DatabaseHelper.removeDatabaseMigrationSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetRenewalPriceInfo_isAnchorTenantWithoutToken_returnsNonPremiumAndNullPrice() {
|
||||||
|
assertThat(
|
||||||
|
DomainCreateFlow.getRenewalPriceInfo(
|
||||||
|
true,
|
||||||
|
Optional.empty(),
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(BigDecimal.valueOf(0), FeeType.CREATE, false))
|
||||||
|
.build()))
|
||||||
|
.isEqualTo(RenewalPriceInfo.create(NONPREMIUM, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetRenewalPriceInfo_isAnchorTenantWithDefaultToken_returnsNonPremiumAndNullPrice() {
|
||||||
|
assertThat(
|
||||||
|
DomainCreateFlow.getRenewalPriceInfo(
|
||||||
|
true,
|
||||||
|
Optional.of(allocationToken),
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(BigDecimal.valueOf(0), FeeType.CREATE, false))
|
||||||
|
.build()))
|
||||||
|
.isEqualTo(RenewalPriceInfo.create(NONPREMIUM, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetRenewalPriceInfo_isNotAnchorTenantWithDefaultToken_returnsDefaultAndNullPrice() {
|
||||||
|
assertThat(
|
||||||
|
DomainCreateFlow.getRenewalPriceInfo(
|
||||||
|
false,
|
||||||
|
Optional.of(allocationToken),
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(BigDecimal.valueOf(100), FeeType.CREATE, false))
|
||||||
|
.build()))
|
||||||
|
.isEqualTo(RenewalPriceInfo.create(DEFAULT, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetRenewalPriceInfo_isNotAnchorTenantWithoutToken_returnsDefaultAndNullPrice() {
|
||||||
|
assertThat(
|
||||||
|
DomainCreateFlow.getRenewalPriceInfo(
|
||||||
|
false,
|
||||||
|
Optional.empty(),
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(BigDecimal.valueOf(100), FeeType.CREATE, false))
|
||||||
|
.build()))
|
||||||
|
.isEqualTo(RenewalPriceInfo.create(DEFAULT, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void
|
||||||
|
testGetRenewalPriceInfo_isNotAnchorTenantWithSpecifiedInToken_returnsSpecifiedAndCreatePrice() {
|
||||||
|
AllocationToken token =
|
||||||
|
persistResource(
|
||||||
|
new AllocationToken.Builder()
|
||||||
|
.setToken("abc123")
|
||||||
|
.setTokenType(SINGLE_USE)
|
||||||
|
.setRenewalPriceBehavior(SPECIFIED)
|
||||||
|
.build());
|
||||||
|
assertThat(
|
||||||
|
DomainCreateFlow.getRenewalPriceInfo(
|
||||||
|
false,
|
||||||
|
Optional.of(token),
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(BigDecimal.valueOf(100), FeeType.CREATE, false))
|
||||||
|
.build()))
|
||||||
|
.isEqualTo(RenewalPriceInfo.create(SPECIFIED, Money.of(USD, 100)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetRenewalPriceInfo_isAnchorTenantWithSpecifiedStateInToken_throwsError() {
|
||||||
|
IllegalArgumentException thrown =
|
||||||
|
assertThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() ->
|
||||||
|
DomainCreateFlow.getRenewalPriceInfo(
|
||||||
|
true,
|
||||||
|
Optional.of(
|
||||||
|
persistResource(
|
||||||
|
new AllocationToken.Builder()
|
||||||
|
.setToken("abc123")
|
||||||
|
.setTokenType(SINGLE_USE)
|
||||||
|
.setRenewalPriceBehavior(SPECIFIED)
|
||||||
|
.build())),
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(BigDecimal.valueOf(0), FeeType.CREATE, true))
|
||||||
|
.build()));
|
||||||
|
assertThat(thrown)
|
||||||
|
.hasMessageThat()
|
||||||
|
.isEqualTo("Renewal price behavior cannot be SPECIFIED for anchor tenant");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetRenewalPriceInfo_withInvalidRenewalPriceBehavior_throwsError() {
|
||||||
|
IllegalArgumentException thrown =
|
||||||
|
assertThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() ->
|
||||||
|
DomainCreateFlow.getRenewalPriceInfo(
|
||||||
|
true,
|
||||||
|
Optional.of(
|
||||||
|
persistResource(
|
||||||
|
new AllocationToken.Builder()
|
||||||
|
.setToken("abc123")
|
||||||
|
.setTokenType(SINGLE_USE)
|
||||||
|
.setRenewalPriceBehavior(RenewalPriceBehavior.valueOf("INVALID"))
|
||||||
|
.build())),
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(BigDecimal.valueOf(0), FeeType.CREATE, true))
|
||||||
|
.build()));
|
||||||
|
assertThat(thrown)
|
||||||
|
.hasMessageThat()
|
||||||
|
.isEqualTo(
|
||||||
|
"No enum constant"
|
||||||
|
+ " google.registry.model.billing.BillingEvent.RenewalPriceBehavior.INVALID");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue