killbill-memoizeit
Changes
subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java 7(+5 -2)
Details
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java b/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java
index b92c6d1..e257c39 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/user/DefaultSubscriptionBaseApiService.java
@@ -392,10 +392,10 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
final PlanChangeResult planChangeResult;
try {
final InternalTenantContext internalCallContext = createTenantContextFromBundleId(subscription.getBundleId(), context);
- final Plan currentPlan = subscription.getCurrentPlan();
+ final Plan currentPlan = subscription.getCurrentOrPendingPlan();
final PlanPhaseSpecifier fromPlanPhase = new PlanPhaseSpecifier(currentPlan.getName(),
- subscription.getCurrentPhase().getPhaseType());
+ subscription.getCurrentOrPendingPhase().getPhaseType());
planChangeResult = catalogService.getFullCatalog(true, true, internalCallContext).planChange(fromPlanPhase, toPlanPhase, effectiveDate);
} catch (final CatalogApiException e) {
throw new SubscriptionBaseApiException(e);
@@ -496,8 +496,11 @@ public class DefaultSubscriptionBaseApiService implements SubscriptionBaseApiSer
final Collection<SubscriptionBaseEvent> addOnCancelEvents,
final PhaseType initialPhaseType,
final InternalTenantContext internalTenantContext) throws CatalogApiException, SubscriptionBaseApiException {
+
final TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnChange(subscription, newPlan, effectiveDate, initialPhaseType, internalTenantContext);
+ validateEntitlementState(subscription, effectiveDate);
+
final SubscriptionBaseEvent changeEvent = new ApiEventChange(new ApiEventBuilder()
.setSubscriptionId(subscription.getId())
.setEventPlan(newPlan.getName())
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/api/user/TestSubscriptionHelper.java b/subscription/src/test/java/org/killbill/billing/subscription/api/user/TestSubscriptionHelper.java
index dcb1c5b..1886d07 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/api/user/TestSubscriptionHelper.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/api/user/TestSubscriptionHelper.java
@@ -32,12 +32,17 @@ import org.killbill.billing.account.api.AccountUserApi;
import org.killbill.billing.api.TestApiListener;
import org.killbill.billing.api.TestApiListener.NextEvent;
import org.killbill.billing.callcontext.InternalCallContext;
+import org.killbill.billing.catalog.api.BillingActionPolicy;
import org.killbill.billing.catalog.api.BillingPeriod;
import org.killbill.billing.catalog.api.Duration;
import org.killbill.billing.catalog.api.PhaseType;
+import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
import org.killbill.billing.catalog.api.PlanPhaseSpecifier;
import org.killbill.billing.catalog.api.ProductCategory;
import org.killbill.billing.catalog.api.TimeUnit;
+import org.killbill.billing.entitlement.api.SubscriptionEventType;
+import org.killbill.billing.invoice.api.DryRunArguments;
+import org.killbill.billing.invoice.api.DryRunType;
import org.killbill.billing.subscription.api.SubscriptionBaseInternalApi;
import org.killbill.billing.subscription.engine.dao.SubscriptionDao;
import org.killbill.billing.subscription.events.SubscriptionBaseEvent;
@@ -58,25 +63,58 @@ public class TestSubscriptionHelper {
private final Logger log = LoggerFactory.getLogger(TestSubscriptionHelper.class);
- private final AccountUserApi accountApi;
private final SubscriptionBaseInternalApi subscriptionApi;
private final Clock clock;
private final InternalCallContext internalCallContext;
- private final CallContext callContext;
private final TestApiListener testListener;
private final SubscriptionDao dao;
@Inject
- public TestSubscriptionHelper(final AccountUserApi accountApi, final SubscriptionBaseInternalApi subscriptionApi, final Clock clock, final InternalCallContext internallCallContext, final CallContext callContext, final TestApiListener testListener, final SubscriptionDao dao) {
- this.accountApi = accountApi;
+ public TestSubscriptionHelper(final SubscriptionBaseInternalApi subscriptionApi, final Clock clock, final InternalCallContext internallCallContext, final CallContext callContext, final TestApiListener testListener, final SubscriptionDao dao) {
this.subscriptionApi = subscriptionApi;
this.clock = clock;
this.internalCallContext = internallCallContext;
- this.callContext = callContext;
this.testListener = testListener;
this.dao = dao;
}
+ public DryRunArguments createDryRunArguments(final UUID subscriptionId, final UUID bundleId, final PlanPhaseSpecifier spec, final LocalDate requestedDate, final SubscriptionEventType type, final BillingActionPolicy billingActionPolicy) {
+ return new DryRunArguments() {
+ @Override
+ public DryRunType getDryRunType() {
+ return DryRunType.SUBSCRIPTION_ACTION;
+ }
+ @Override
+ public PlanPhaseSpecifier getPlanPhaseSpecifier() {
+ return spec;
+ }
+ @Override
+ public SubscriptionEventType getAction() {
+ return type;
+ }
+ @Override
+ public UUID getSubscriptionId() {
+ return subscriptionId;
+ }
+ @Override
+ public LocalDate getEffectiveDate() {
+ return requestedDate;
+ }
+ @Override
+ public UUID getBundleId() {
+ return bundleId;
+ }
+ @Override
+ public BillingActionPolicy getBillingActionPolicy() {
+ return billingActionPolicy;
+ }
+ @Override
+ public List<PlanPhasePriceOverride> getPlanPhasePriceOverrides() {
+ return null;
+ }
+ };
+ }
+
public DefaultSubscriptionBase createSubscription(final SubscriptionBaseBundle bundle, final String productName, final BillingPeriod term, final String planSet, final DateTime requestedDate)
throws SubscriptionBaseApiException {
return createSubscriptionWithBundle(bundle.getId(), productName, term, planSet, requestedDate);
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/api/user/TestUserApiChangePlan.java b/subscription/src/test/java/org/killbill/billing/subscription/api/user/TestUserApiChangePlan.java
index eb5a01d..62e0be1 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/api/user/TestUserApiChangePlan.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/api/user/TestUserApiChangePlan.java
@@ -18,6 +18,7 @@ package org.killbill.billing.subscription.api.user;
import org.joda.time.DateTime;
import org.joda.time.Interval;
+import org.joda.time.LocalDate;
import org.killbill.billing.ErrorCode;
import org.killbill.billing.api.TestApiListener.NextEvent;
import org.killbill.billing.catalog.api.BillingActionPolicy;
@@ -31,7 +32,10 @@ import org.killbill.billing.catalog.api.PlanSpecifier;
import org.killbill.billing.catalog.api.PriceListSet;
import org.killbill.billing.catalog.api.ProductCategory;
import org.killbill.billing.entitlement.api.Entitlement;
+import org.killbill.billing.entitlement.api.SubscriptionEventType;
+import org.killbill.billing.invoice.api.DryRunArguments;
import org.killbill.billing.subscription.SubscriptionTestSuiteWithEmbeddedDB;
+import org.killbill.billing.subscription.api.SubscriptionBase;
import org.killbill.billing.subscription.api.SubscriptionBillingApiException;
import org.killbill.billing.subscription.events.SubscriptionBaseEvent;
import org.killbill.billing.subscription.events.user.ApiEvent;
@@ -477,7 +481,13 @@ public class TestUserApiChangePlan extends SubscriptionTestSuiteWithEmbeddedDB {
final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Pistol", baseTerm, basePriceList, null);
+
// First try with default api (no date -> IMM) => Call should fail because subscription is PENDING
+ final DryRunArguments dryRunArguments1 = testUtil.createDryRunArguments(subscription.getId(), subscription.getBundleId(), spec, null, SubscriptionEventType.CHANGE, null);
+ final List<SubscriptionBase> result1 = subscriptionInternalApi.getSubscriptionsForBundle(bundle.getId(), dryRunArguments1, internalCallContext);
+
+ // Check we are seeing the right PENDING transition (pistol-monthly), not the START but the CHANGE on the same date
+ assertEquals(((DefaultSubscriptionBase) result1.get(0)).getCurrentOrPendingPlan().getName(), "pistol-monthly");
try {
subscription.changePlan(spec, null, callContext);
fail("Change plan should have failed : subscription PENDING");
@@ -487,13 +497,26 @@ public class TestUserApiChangePlan extends SubscriptionTestSuiteWithEmbeddedDB {
// Second try with date prior to startDate => Call should fail because subscription is PENDING
try {
+ final DryRunArguments dryRunArguments2 = testUtil.createDryRunArguments(subscription.getId(), subscription.getBundleId(), spec, new LocalDate(startDate.minusDays(1)), SubscriptionEventType.CHANGE, null);
+ subscriptionInternalApi.getSubscriptionsForBundle(bundle.getId(), dryRunArguments2, internalCallContext);
+ fail("Change plan should have failed : subscription PENDING");
+ } catch (final SubscriptionBaseApiException e) {
+ assertEquals(e.getCode(), ErrorCode.SUB_CHANGE_NON_ACTIVE.getCode());
+ }
+ try {
subscription.changePlanWithDate(spec, null, startDate.minusDays(1), callContext);
fail("Change plan should have failed : subscription PENDING");
} catch (final SubscriptionBaseApiException e) {
assertEquals(e.getCode(), ErrorCode.SUB_INVALID_REQUESTED_DATE.getCode());
}
- // Second try with date equals to startDate Call should succeed, but no event because action in future
+ // Third try with date equals to startDate Call should succeed, but no event because action in future
+ final DryRunArguments dryRunArguments3 = testUtil.createDryRunArguments(subscription.getId(), subscription.getBundleId(), spec, internalCallContext.toLocalDate(startDate), SubscriptionEventType.CHANGE, null);
+ final List<SubscriptionBase> result2 = subscriptionInternalApi.getSubscriptionsForBundle(bundle.getId(), dryRunArguments3, internalCallContext);
+ // Check we are seeing the right PENDING transition (pistol-monthly), not the START but the CHANGE on the same date
+ assertEquals(((DefaultSubscriptionBase) result2.get(0)).getCurrentOrPendingPlan().getName(), "pistol-monthly");
+
+
subscription.changePlanWithDate(spec, null, startDate, callContext);
assertListenerStatus();