mirror of
https://github.com/google/nomulus.git
synced 2025-07-27 04:58:37 +02:00
Add renewal cost logic to DomainPricingLogic (#1610)
* Add renew cost calculation to DomainPricingLogic * Fix typos and change assertions
This commit is contained in:
parent
3a7ac669f5
commit
64fba55f06
6 changed files with 467 additions and 11 deletions
|
@ -33,7 +33,7 @@ import org.joda.time.DateTime;
|
||||||
*/
|
*/
|
||||||
public class DomainPricingCustomLogic extends BaseFlowCustomLogic {
|
public class DomainPricingCustomLogic extends BaseFlowCustomLogic {
|
||||||
|
|
||||||
protected DomainPricingCustomLogic(
|
public DomainPricingCustomLogic(
|
||||||
EppInput eppInput, SessionMetadata sessionMetadata, FlowMetadata flowMetadata) {
|
EppInput eppInput, SessionMetadata sessionMetadata, FlowMetadata flowMetadata) {
|
||||||
super(eppInput, sessionMetadata, flowMetadata);
|
super(eppInput, sessionMetadata, flowMetadata);
|
||||||
}
|
}
|
||||||
|
|
|
@ -680,7 +680,7 @@ public class DomainFlowUtils {
|
||||||
break;
|
break;
|
||||||
case RENEW:
|
case RENEW:
|
||||||
builder.setAvailIfSupported(true);
|
builder.setAvailIfSupported(true);
|
||||||
fees = pricingLogic.getRenewPrice(registry, domainNameString, now, years).getFees();
|
fees = pricingLogic.getRenewPrice(registry, domainNameString, now, years, null).getFees();
|
||||||
break;
|
break;
|
||||||
case RESTORE:
|
case RESTORE:
|
||||||
// The minimum allowable period per the EPP spec is 1, so, strangely, 1 year still has to be
|
// The minimum allowable period per the EPP spec is 1, so, strangely, 1 year still has to be
|
||||||
|
|
|
@ -14,8 +14,11 @@
|
||||||
|
|
||||||
package google.registry.flows.domain;
|
package google.registry.flows.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.zeroInCurrency;
|
import static google.registry.flows.domain.DomainFlowUtils.zeroInCurrency;
|
||||||
import static google.registry.pricing.PricingEngineProxy.getPricesForDomainName;
|
import static google.registry.pricing.PricingEngineProxy.getPricesForDomainName;
|
||||||
|
import static google.registry.util.DomainNameUtils.getTldFromDomainName;
|
||||||
|
import static google.registry.util.PreconditionsUtils.checkArgumentPresent;
|
||||||
|
|
||||||
import com.google.common.net.InternetDomainName;
|
import com.google.common.net.InternetDomainName;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
|
@ -27,15 +30,16 @@ import google.registry.flows.custom.DomainPricingCustomLogic.RenewPriceParameter
|
||||||
import google.registry.flows.custom.DomainPricingCustomLogic.RestorePriceParameters;
|
import google.registry.flows.custom.DomainPricingCustomLogic.RestorePriceParameters;
|
||||||
import google.registry.flows.custom.DomainPricingCustomLogic.TransferPriceParameters;
|
import google.registry.flows.custom.DomainPricingCustomLogic.TransferPriceParameters;
|
||||||
import google.registry.flows.custom.DomainPricingCustomLogic.UpdatePriceParameters;
|
import google.registry.flows.custom.DomainPricingCustomLogic.UpdatePriceParameters;
|
||||||
|
import google.registry.model.billing.BillingEvent.Recurring;
|
||||||
import google.registry.model.domain.fee.BaseFee;
|
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.Fee;
|
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.tld.Registry;
|
import google.registry.model.tld.Registry;
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import org.joda.money.CurrencyUnit;
|
import org.joda.money.CurrencyUnit;
|
||||||
import org.joda.money.Money;
|
import org.joda.money.Money;
|
||||||
|
@ -102,18 +106,63 @@ public final class DomainPricingLogic {
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a new renew price for the pricer. */
|
/** Returns a new renewal cost for the pricer. */
|
||||||
@SuppressWarnings("unused")
|
FeesAndCredits getRenewPrice(
|
||||||
FeesAndCredits getRenewPrice(Registry registry, String domainName, DateTime dateTime, int years)
|
Registry registry,
|
||||||
|
String domainName,
|
||||||
|
DateTime dateTime,
|
||||||
|
int years,
|
||||||
|
@Nullable Recurring recurringBillingEvent)
|
||||||
throws EppException {
|
throws EppException {
|
||||||
|
checkArgument(years > 0, "Number of years must be positive");
|
||||||
|
Money renewCost;
|
||||||
|
boolean isRenewCostPremiumPrice;
|
||||||
|
// recurring billing event is null if the domain is still available. Billing events are created
|
||||||
|
// in the process of domain creation.
|
||||||
|
if (recurringBillingEvent == null) {
|
||||||
DomainPrices domainPrices = getPricesForDomainName(domainName, dateTime);
|
DomainPrices domainPrices = getPricesForDomainName(domainName, dateTime);
|
||||||
BigDecimal renewCost = domainPrices.getRenewCost().multipliedBy(years).getAmount();
|
renewCost = domainPrices.getRenewCost().multipliedBy(years);
|
||||||
|
isRenewCostPremiumPrice = domainPrices.isPremium();
|
||||||
|
} else {
|
||||||
|
switch (recurringBillingEvent.getRenewalPriceBehavior()) {
|
||||||
|
case DEFAULT:
|
||||||
|
DomainPrices domainPrices = getPricesForDomainName(domainName, dateTime);
|
||||||
|
renewCost = domainPrices.getRenewCost().multipliedBy(years);
|
||||||
|
isRenewCostPremiumPrice = domainPrices.isPremium();
|
||||||
|
break;
|
||||||
|
// if the renewal price behavior is specified, then the renewal price should be the same
|
||||||
|
// as the creation price, which is stored in the billing event as the renewal price
|
||||||
|
case SPECIFIED:
|
||||||
|
checkArgumentPresent(
|
||||||
|
recurringBillingEvent.getRenewalPrice(),
|
||||||
|
"Unexpected behavior: renewal price cannot be null when renewal behavior is"
|
||||||
|
+ " SPECIFIED");
|
||||||
|
renewCost = recurringBillingEvent.getRenewalPrice().get().multipliedBy(years);
|
||||||
|
isRenewCostPremiumPrice = false;
|
||||||
|
break;
|
||||||
|
// if the renewal price behavior is nonpremium, it means that the domain should be renewed
|
||||||
|
// at standard price of domains at the time, even if the domain is premium
|
||||||
|
case NONPREMIUM:
|
||||||
|
renewCost =
|
||||||
|
Registry.get(getTldFromDomainName(domainName))
|
||||||
|
.getStandardRenewCost(dateTime)
|
||||||
|
.multipliedBy(years);
|
||||||
|
isRenewCostPremiumPrice = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format(
|
||||||
|
"Unknown RenewalPriceBehavior enum value: %s",
|
||||||
|
recurringBillingEvent.getRenewalPriceBehavior()));
|
||||||
|
}
|
||||||
|
}
|
||||||
return customLogic.customizeRenewPrice(
|
return customLogic.customizeRenewPrice(
|
||||||
RenewPriceParameters.newBuilder()
|
RenewPriceParameters.newBuilder()
|
||||||
.setFeesAndCredits(
|
.setFeesAndCredits(
|
||||||
new FeesAndCredits.Builder()
|
new FeesAndCredits.Builder()
|
||||||
.setCurrency(registry.getCurrency())
|
.setCurrency(renewCost.getCurrencyUnit())
|
||||||
.addFeeOrCredit(Fee.create(renewCost, FeeType.RENEW, domainPrices.isPremium()))
|
.addFeeOrCredit(
|
||||||
|
Fee.create(renewCost.getAmount(), FeeType.RENEW, isRenewCostPremiumPrice))
|
||||||
.build())
|
.build())
|
||||||
.setRegistry(registry)
|
.setRegistry(registry)
|
||||||
.setDomainName(InternetDomainName.from(domainName))
|
.setDomainName(InternetDomainName.from(domainName))
|
||||||
|
|
|
@ -155,7 +155,8 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||||
Optional<FeeRenewCommandExtension> feeRenew =
|
Optional<FeeRenewCommandExtension> feeRenew =
|
||||||
eppInput.getSingleExtension(FeeRenewCommandExtension.class);
|
eppInput.getSingleExtension(FeeRenewCommandExtension.class);
|
||||||
FeesAndCredits feesAndCredits =
|
FeesAndCredits feesAndCredits =
|
||||||
pricingLogic.getRenewPrice(Registry.get(existingDomain.getTld()), targetId, now, years);
|
pricingLogic.getRenewPrice(
|
||||||
|
Registry.get(existingDomain.getTld()), targetId, now, years, null);
|
||||||
validateFeeChallenge(targetId, now, feeRenew, feesAndCredits);
|
validateFeeChallenge(targetId, now, feeRenew, feesAndCredits);
|
||||||
flowCustomLogic.afterValidation(
|
flowCustomLogic.afterValidation(
|
||||||
AfterValidationParameters.newBuilder()
|
AfterValidationParameters.newBuilder()
|
||||||
|
|
|
@ -45,6 +45,7 @@ import google.registry.testing.TestOfyAndSql;
|
||||||
import org.joda.money.Money;
|
import org.joda.money.Money;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
|
||||||
|
/** Unit tests for {@link DomainFlowUtils}. */
|
||||||
@DualDatabaseTest
|
@DualDatabaseTest
|
||||||
class DomainFlowUtilsTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase> {
|
class DomainFlowUtilsTest extends ResourceFlowTestCase<DomainInfoFlow, DomainBase> {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,405 @@
|
||||||
|
// Copyright 2022 The Nomulus Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package google.registry.flows.domain;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static com.google.common.truth.Truth8.assertThat;
|
||||||
|
import static google.registry.model.billing.BillingEvent.Flag.AUTO_RENEW;
|
||||||
|
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.BaseFee.FeeType.RENEW;
|
||||||
|
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_CREATE;
|
||||||
|
import static google.registry.testing.DatabaseHelper.createTld;
|
||||||
|
import static google.registry.testing.DatabaseHelper.newDomainBase;
|
||||||
|
import static google.registry.testing.DatabaseHelper.persistPremiumList;
|
||||||
|
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||||
|
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||||
|
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||||
|
import static org.joda.money.CurrencyUnit.USD;
|
||||||
|
import static org.joda.time.DateTimeZone.UTC;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.ImmutableSortedMap;
|
||||||
|
import google.registry.flows.EppException;
|
||||||
|
import google.registry.flows.FlowMetadata;
|
||||||
|
import google.registry.flows.HttpSessionMetadata;
|
||||||
|
import google.registry.flows.SessionMetadata;
|
||||||
|
import google.registry.flows.custom.DomainPricingCustomLogic;
|
||||||
|
import google.registry.model.billing.BillingEvent;
|
||||||
|
import google.registry.model.billing.BillingEvent.Reason;
|
||||||
|
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.DomainHistory;
|
||||||
|
import google.registry.model.domain.fee.Fee;
|
||||||
|
import google.registry.model.eppinput.EppInput;
|
||||||
|
import google.registry.model.tld.Registry;
|
||||||
|
import google.registry.testing.AppEngineExtension;
|
||||||
|
import google.registry.testing.DualDatabaseTest;
|
||||||
|
import google.registry.testing.FakeClock;
|
||||||
|
import google.registry.testing.FakeHttpSession;
|
||||||
|
import google.registry.testing.TestOfyAndSql;
|
||||||
|
import google.registry.util.Clock;
|
||||||
|
import java.util.Optional;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import org.joda.money.Money;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
|
||||||
|
/** Unit tests for {@link DomainPricingLogic}. */
|
||||||
|
@DualDatabaseTest
|
||||||
|
public class DomainPricingLogicTest {
|
||||||
|
DomainPricingLogic domainPricingLogic = new DomainPricingLogic();
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
public final AppEngineExtension appEngine =
|
||||||
|
AppEngineExtension.builder().withDatastoreAndCloudSql().build();
|
||||||
|
|
||||||
|
@Inject Clock clock = new FakeClock(DateTime.now(UTC));
|
||||||
|
@Mock EppInput eppInput;
|
||||||
|
SessionMetadata sessionMetadata;
|
||||||
|
@Mock FlowMetadata flowMetadata;
|
||||||
|
Registry registry;
|
||||||
|
DomainBase domain;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void beforeEach() throws Exception {
|
||||||
|
createTld("example");
|
||||||
|
sessionMetadata = new HttpSessionMetadata(new FakeHttpSession());
|
||||||
|
domainPricingLogic.customLogic =
|
||||||
|
new DomainPricingCustomLogic(eppInput, sessionMetadata, flowMetadata);
|
||||||
|
registry =
|
||||||
|
persistResource(
|
||||||
|
Registry.get("example")
|
||||||
|
.asBuilder()
|
||||||
|
.setRenewBillingCostTransitions(
|
||||||
|
ImmutableSortedMap.of(
|
||||||
|
START_OF_TIME, Money.of(USD, 1), clock.nowUtc(), Money.of(USD, 10)))
|
||||||
|
.setPremiumList(persistPremiumList("tld2", USD, "premium,USD 100"))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** helps to set up the domain info and returns a recurring billing event for testing */
|
||||||
|
private Recurring persistDomainAndSetRecurringBillingEvent(
|
||||||
|
String domainName, RenewalPriceBehavior renewalPriceBehavior, Optional<Money> renewalPrice) {
|
||||||
|
domain =
|
||||||
|
persistResource(
|
||||||
|
newDomainBase(domainName)
|
||||||
|
.asBuilder()
|
||||||
|
.setCreationTimeForTest(DateTime.parse("1999-01-05T00:00:00Z"))
|
||||||
|
.build());
|
||||||
|
DomainHistory historyEntry =
|
||||||
|
persistResource(
|
||||||
|
new DomainHistory.Builder()
|
||||||
|
.setRegistrarId(domain.getCreationRegistrarId())
|
||||||
|
.setType(DOMAIN_CREATE)
|
||||||
|
.setModificationTime(DateTime.parse("1999-01-05T00:00:00Z"))
|
||||||
|
.setDomain(domain)
|
||||||
|
.build());
|
||||||
|
Recurring recurring =
|
||||||
|
persistResource(
|
||||||
|
new BillingEvent.Recurring.Builder()
|
||||||
|
.setParent(historyEntry)
|
||||||
|
.setRegistrarId(domain.getCreationRegistrarId())
|
||||||
|
.setEventTime((DateTime.parse("1999-01-05T00:00:00Z")))
|
||||||
|
.setFlags(ImmutableSet.of(AUTO_RENEW))
|
||||||
|
.setId(2L)
|
||||||
|
.setReason(Reason.RENEW)
|
||||||
|
.setRenewalPriceBehavior(renewalPriceBehavior)
|
||||||
|
.setRenewalPrice(renewalPrice.isPresent() ? renewalPrice.get() : null)
|
||||||
|
.setRecurrenceEndTime(END_OF_TIME)
|
||||||
|
.setTargetId(domain.getDomainName())
|
||||||
|
.build());
|
||||||
|
persistResource(domain.asBuilder().setAutorenewBillingEvent(recurring.createVKey()).build());
|
||||||
|
return recurring;
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_oneYear_standardDomain_noBilling_isStandardPrice()
|
||||||
|
throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(registry, "standard.example", clock.nowUtc(), 1, null))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 10).getAmount(), RENEW, false))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_multiYear_standardDomain_noBilling_isStandardPrice()
|
||||||
|
throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(registry, "standard.example", clock.nowUtc(), 5, null))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 50).getAmount(), RENEW, false))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_oneYear_premiumDomain_noBilling_isPremiumPrice()
|
||||||
|
throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(registry, "premium.example", clock.nowUtc(), 1, null))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 100).getAmount(), RENEW, true))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_multiYear_premiumDomain_noBilling_isPremiumPrice()
|
||||||
|
throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(registry, "premium.example", clock.nowUtc(), 5, null))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 500).getAmount(), RENEW, true))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_oneYear_premiumDomain_default_isPremiumPrice() throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(
|
||||||
|
registry,
|
||||||
|
"premium.example",
|
||||||
|
clock.nowUtc(),
|
||||||
|
1,
|
||||||
|
persistDomainAndSetRecurringBillingEvent(
|
||||||
|
"premium.example", DEFAULT, Optional.empty())))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 100).getAmount(), RENEW, true))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_multiYear_premiumDomain_default_isPremiumCost() throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(
|
||||||
|
registry,
|
||||||
|
"premium.example",
|
||||||
|
clock.nowUtc(),
|
||||||
|
5,
|
||||||
|
persistDomainAndSetRecurringBillingEvent(
|
||||||
|
"premium.example", DEFAULT, Optional.empty())))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 500).getAmount(), RENEW, true))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_oneYear_standardDomain_default_isNonPremiumPrice()
|
||||||
|
throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(
|
||||||
|
registry,
|
||||||
|
"standard.example",
|
||||||
|
clock.nowUtc(),
|
||||||
|
1,
|
||||||
|
persistDomainAndSetRecurringBillingEvent(
|
||||||
|
"premium.example", DEFAULT, Optional.empty())))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 10).getAmount(), RENEW, false))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_multiYear_standardDomain_default_isNonPremiumCost()
|
||||||
|
throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(
|
||||||
|
registry,
|
||||||
|
"standard.example",
|
||||||
|
clock.nowUtc(),
|
||||||
|
5,
|
||||||
|
persistDomainAndSetRecurringBillingEvent(
|
||||||
|
"standard.example", DEFAULT, Optional.empty())))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 50).getAmount(), RENEW, false))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_oneYear_premiumDomain_anchorTenant_isNonPremiumPrice()
|
||||||
|
throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(
|
||||||
|
registry,
|
||||||
|
"premium.example",
|
||||||
|
clock.nowUtc(),
|
||||||
|
1,
|
||||||
|
persistDomainAndSetRecurringBillingEvent(
|
||||||
|
"premium.example", NONPREMIUM, Optional.empty())))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 10).getAmount(), RENEW, false))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_multiYear_premiumDomain_anchorTenant_isNonPremiumCost()
|
||||||
|
throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(
|
||||||
|
registry,
|
||||||
|
"premium.example",
|
||||||
|
clock.nowUtc(),
|
||||||
|
5,
|
||||||
|
persistDomainAndSetRecurringBillingEvent(
|
||||||
|
"premium.example", NONPREMIUM, Optional.empty())))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 50).getAmount(), RENEW, false))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_oneYear_standardDomain_anchorTenant_isNonPremiumPrice()
|
||||||
|
throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(
|
||||||
|
registry,
|
||||||
|
"standard.example",
|
||||||
|
clock.nowUtc(),
|
||||||
|
1,
|
||||||
|
persistDomainAndSetRecurringBillingEvent(
|
||||||
|
"standard.example", NONPREMIUM, Optional.empty())))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 10).getAmount(), RENEW, false))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_multiYear_standardDomain_anchorTenant_isNonPremiumCost()
|
||||||
|
throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(
|
||||||
|
registry,
|
||||||
|
"standard.example",
|
||||||
|
clock.nowUtc(),
|
||||||
|
5,
|
||||||
|
persistDomainAndSetRecurringBillingEvent(
|
||||||
|
"standard.example", NONPREMIUM, Optional.empty())))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 50).getAmount(), RENEW, false))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_oneYear_standardDomain_internalRegistration_isSpecifiedPrice()
|
||||||
|
throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(
|
||||||
|
registry,
|
||||||
|
"standard.example",
|
||||||
|
clock.nowUtc(),
|
||||||
|
1,
|
||||||
|
persistDomainAndSetRecurringBillingEvent(
|
||||||
|
"standard.example", SPECIFIED, Optional.of(Money.of(USD, 1)))))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 1).getAmount(), RENEW, false))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_multiYear_standardDomain_internalRegistration_isSpecifiedPrice()
|
||||||
|
throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(
|
||||||
|
registry,
|
||||||
|
"standard.example",
|
||||||
|
clock.nowUtc(),
|
||||||
|
5,
|
||||||
|
persistDomainAndSetRecurringBillingEvent(
|
||||||
|
"standard.example", SPECIFIED, Optional.of(Money.of(USD, 1)))))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 5).getAmount(), RENEW, false))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_oneYear_premiumDomain_internalRegistration_isSpecifiedPrice()
|
||||||
|
throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(
|
||||||
|
registry,
|
||||||
|
"premium.example",
|
||||||
|
clock.nowUtc(),
|
||||||
|
1,
|
||||||
|
persistDomainAndSetRecurringBillingEvent(
|
||||||
|
"premium.example", SPECIFIED, Optional.of(Money.of(USD, 17)))))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 17).getAmount(), RENEW, false))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_multiYear_premiumDomain_internalRegistration_isSpecifiedPrice()
|
||||||
|
throws EppException {
|
||||||
|
assertThat(
|
||||||
|
domainPricingLogic.getRenewPrice(
|
||||||
|
registry,
|
||||||
|
"premium.example",
|
||||||
|
clock.nowUtc(),
|
||||||
|
5,
|
||||||
|
persistDomainAndSetRecurringBillingEvent(
|
||||||
|
"premium.example", SPECIFIED, Optional.of(Money.of(USD, 17)))))
|
||||||
|
.isEqualTo(
|
||||||
|
new FeesAndCredits.Builder()
|
||||||
|
.setCurrency(USD)
|
||||||
|
.addFeeOrCredit(Fee.create(Money.of(USD, 85).getAmount(), RENEW, false))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testGetDomainRenewPrice_negativeYear_throwsException() throws EppException {
|
||||||
|
IllegalArgumentException thrown =
|
||||||
|
assertThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() ->
|
||||||
|
domainPricingLogic.getRenewPrice(
|
||||||
|
registry, "standard.example", clock.nowUtc(), -1, null));
|
||||||
|
assertThat(thrown).hasMessageThat().isEqualTo("Number of years must be positive");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue