killbill-memoizeit
Changes
entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlementApi.java 62(+61 -1)
Details
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlement.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlement.java
index 7485e19..705b7e7 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlement.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlement.java
@@ -49,7 +49,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
protected final InternalCallContextFactory internalCallContextFactory;
protected final Clock clock;
protected final EntitlementState state;
- protected final BlockingState entitlementBlockingState;
+ protected final LocalDate effectiveEndDate;
protected final BlockingChecker checker;
protected final UUID accountId;
protected final String externalKey;
@@ -58,7 +58,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
protected final BlockingStateDao blockingStateDao;
public DefaultEntitlement(final EntitlementDateHelper dateHelper, final SubscriptionBase subscriptionBase, final UUID accountId,
- final String externalKey, final EntitlementState state, final BlockingState entitlementBlockingState, final DateTimeZone accountTimeZone,
+ final String externalKey, final EntitlementState state, final LocalDate effectiveEndDate, final DateTimeZone accountTimeZone,
final EntitlementApi entitlementApi, final InternalCallContextFactory internalCallContextFactory,
final BlockingStateDao blockingStateDao,
final Clock clock, final BlockingChecker checker) {
@@ -68,8 +68,8 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
this.accountId = accountId;
this.externalKey = externalKey;
this.state = state;
+ this.effectiveEndDate = effectiveEndDate;
this.entitlementApi = entitlementApi;
- this.entitlementBlockingState = entitlementBlockingState;
this.accountTimeZone = accountTimeZone;
this.internalCallContextFactory = internalCallContextFactory;
this.clock = clock;
@@ -83,7 +83,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
in.getAccountId(),
in.getExternalKey(),
in.getState(),
- in.getEntitlementBlockingState(),
+ in.getEffectiveEndDate(),
in.getAccountTimeZone(),
in.getEntitlementApi(),
in.getInternalCallContextFactory(),
@@ -91,7 +91,6 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
in.getClock(), in.getChecker());
}
- // STEPH_ENT should be remove but beatrix tests need to be changed
public SubscriptionBase getSubscriptionBase() {
return subscriptionBase;
}
@@ -112,10 +111,6 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
return clock;
}
- public BlockingState getEntitlementBlockingState() {
- return entitlementBlockingState;
- }
-
public BlockingChecker getChecker() {
return checker;
}
@@ -165,17 +160,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
@Override
public LocalDate getEffectiveEndDate() {
- if (entitlementBlockingState != null && entitlementBlockingState.getStateName().equals(DefaultEntitlementApi.ENT_STATE_CANCELLED)) {
- return new LocalDate(entitlementBlockingState.getEffectiveDate(), accountTimeZone);
- }
- return null;
- //return subscriptionBase.getEndDate() != null ? new LocalDate(subscriptionBase.getEndDate(), accountTimeZone) : null;
- }
-
- @Override
- public LocalDate getRequestedEndDate() {
- // STEPH_ENT
- return null; //subscriptionBase.;
+ return effectiveEndDate;
}
@Override
@@ -333,15 +318,4 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
throw new EntitlementApiException(e);
}
}
-
- @Override
- public Entitlement block(final String serviceName, final LocalDate effectiveDate, final CallContext context) throws EntitlementApiException {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- @Override
- public Entitlement unblock(final String serviceName, final LocalDate effectiveDate, final CallContext context) throws EntitlementApiException {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
-
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlementApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlementApi.java
index f9d0366..ba0121c 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlementApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlementApi.java
@@ -46,6 +46,8 @@ import com.ning.billing.entitlement.block.BlockingChecker;
import com.ning.billing.entitlement.block.BlockingChecker.BlockingAggregator;
import com.ning.billing.entitlement.dao.BlockingStateDao;
import com.ning.billing.subscription.api.SubscriptionBase;
+import com.ning.billing.subscription.api.transfer.SubscriptionBaseTransferApi;
+import com.ning.billing.subscription.api.transfer.SubscriptionBaseTransferApiException;
import com.ning.billing.subscription.api.user.SubscriptionBaseApiException;
import com.ning.billing.subscription.api.user.SubscriptionBaseBundle;
import com.ning.billing.util.callcontext.CallContext;
@@ -70,6 +72,7 @@ public class DefaultEntitlementApi implements EntitlementApi {
public static final String ENT_STATE_CANCELLED = "ENT_CANCELLED";
private final SubscriptionBaseInternalApi subscriptionInternalApi;
+ private final SubscriptionBaseTransferApi subscriptionTransferApi;
private final AccountInternalApi accountApi;
private final Clock clock;
private final InternalCallContextFactory internalCallContextFactory;
@@ -79,10 +82,11 @@ public class DefaultEntitlementApi implements EntitlementApi {
private final PersistentBus eventBus;
@Inject
- public DefaultEntitlementApi(PersistentBus eventBus, final InternalCallContextFactory internalCallContextFactory, final SubscriptionBaseInternalApi subscriptionInternalApi, final AccountInternalApi accountApi, final BlockingStateDao blockingStateDao, final Clock clock, final BlockingChecker checker) {
+ public DefaultEntitlementApi(final PersistentBus eventBus, final InternalCallContextFactory internalCallContextFactory, final SubscriptionBaseTransferApi subscriptionTransferApi, final SubscriptionBaseInternalApi subscriptionInternalApi, final AccountInternalApi accountApi, final BlockingStateDao blockingStateDao, final Clock clock, final BlockingChecker checker) {
this.eventBus = eventBus;
this.internalCallContextFactory = internalCallContextFactory;
this.subscriptionInternalApi = subscriptionInternalApi;
+ this.subscriptionTransferApi = subscriptionTransferApi;
this.accountApi = accountApi;
this.clock = clock;
this.checker = checker;
@@ -122,9 +126,9 @@ public class DefaultEntitlementApi implements EntitlementApi {
final BlockingState currentBaseState = blockingStateDao.getBlockingStateForService(baseSubscription.getId(), EntitlementService.ENTITLEMENT_SERVICE_NAME, contextWithValidAccountRecordId);
final Account account = accountApi.getAccountById(bundle.getAccountId(), context);
-
+ final LocalDate baseEntitlementEffectiveEndDate = getEffectiveEndDate(bundle.getAccountId(), baseSubscription, account.getTimeZone(), contextWithValidAccountRecordId);
// Check if there is a BP and if it is active
- final EntitlementState baseEntitlementState = getStateForEntitlement(baseSubscription, currentBaseState, account.getTimeZone(), contextWithValidAccountRecordId);
+ final EntitlementState baseEntitlementState = getStateForEntitlement(baseEntitlementEffectiveEndDate, baseSubscription, account.getTimeZone(), contextWithValidAccountRecordId);
if (baseSubscription.getCategory() != ProductCategory.BASE ||
baseEntitlementState != EntitlementState.ACTIVE) {
throw new EntitlementApiException(ErrorCode.SUB_GET_NO_SUCH_BASE_SUBSCRIPTION, baseSubscription.getBundleId());
@@ -139,7 +143,8 @@ public class DefaultEntitlementApi implements EntitlementApi {
final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(effectiveDate, baseSubscription.getStartDate(), contextWithValidAccountRecordId);
final SubscriptionBase subscription = subscriptionInternalApi.createSubscription(baseSubscription.getBundleId(), planPhaseSpecifier, requestedDate, context);
- return new DefaultEntitlement(dateHelper, subscription, bundle.getAccountId(), bundle.getExternalKey(), getStateForEntitlement(subscription, currentBaseState, account.getTimeZone(), context), null, account.getTimeZone(),
+
+ return new DefaultEntitlement(dateHelper, subscription, bundle.getAccountId(), bundle.getExternalKey(), baseEntitlementState, null, account.getTimeZone(),
this, internalCallContextFactory, blockingStateDao, clock, checker);
} catch (SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
@@ -176,7 +181,12 @@ public class DefaultEntitlementApi implements EntitlementApi {
final Account account = accountApi.getAccountById(bundle.getAccountId(), context);
final BlockingState currentState = blockingStateDao.getBlockingStateForService(subscription.getId(), EntitlementService.ENTITLEMENT_SERVICE_NAME, context);
- return new DefaultEntitlement(dateHelper, subscription, bundle.getAccountId(), bundle.getExternalKey(), getStateForEntitlement(subscription, currentState, account.getTimeZone(), context), currentState, account.getTimeZone(),
+
+ final LocalDate entitlementEffectiveEndDate = getEffectiveEndDate(bundle.getAccountId(), subscription, account.getTimeZone(), context);
+ final EntitlementState entitlementState = getStateForEntitlement(entitlementEffectiveEndDate, subscription, account.getTimeZone(), context);
+
+
+ return new DefaultEntitlement(dateHelper, subscription, bundle.getAccountId(), bundle.getExternalKey(), entitlementState, entitlementEffectiveEndDate, account.getTimeZone(),
this, internalCallContextFactory, blockingStateDao, clock, checker);
} catch (SubscriptionBaseApiException e) {
throw new EntitlementApiException(e);
@@ -231,11 +241,12 @@ public class DefaultEntitlementApi implements EntitlementApi {
@Override
public Entitlement apply(@Nullable final SubscriptionBase input) {
- final BlockingState currentState = blockingStateDao.getBlockingStateForService(input.getId(), EntitlementService.ENTITLEMENT_SERVICE_NAME, context);
+ final LocalDate effectiveEndDate = getEffectiveEndDate(accountId, input, account.getTimeZone(), context);
+ final EntitlementState entitlementState = getStateForEntitlement(effectiveEndDate, input, account.getTimeZone(), context);
return new DefaultEntitlement(dateHelper, input, accountId, externalKey,
- getStateForEntitlement(input, currentState, account.getTimeZone(), context),
- currentState,
+ entitlementState,
+ effectiveEndDate,
account.getTimeZone(),
thisEntitlementApi,
internalCallContextFactory, blockingStateDao, clock, checker);
@@ -247,12 +258,34 @@ public class DefaultEntitlementApi implements EntitlementApi {
}
- private EntitlementState getStateForEntitlement(final SubscriptionBase subscriptionBase, final BlockingState currentState, final DateTimeZone accountTimeZone, final InternalTenantContext context) {
+ private LocalDate getEffectiveEndDate(final UUID accountId, final SubscriptionBase subscriptionBase, final DateTimeZone accountTimeZone, final InternalTenantContext context) {
+
+ LocalDate result = null;
+
+ final BlockingState subEntitlementState = blockingStateDao.getBlockingStateForService(subscriptionBase.getId(), EntitlementService.ENTITLEMENT_SERVICE_NAME, context);
+ if (subEntitlementState != null && subEntitlementState.getStateName().equals(ENT_STATE_CANCELLED)) {
+ result = new LocalDate(subEntitlementState.getEffectiveDate(), accountTimeZone);
+ }
+
+ final BlockingState bundleEntitlementState = blockingStateDao.getBlockingStateForService(subscriptionBase.getBundleId(), EntitlementService.ENTITLEMENT_SERVICE_NAME, context);
+ if (bundleEntitlementState != null && bundleEntitlementState .getStateName().equals(ENT_STATE_CANCELLED)) {
+ final LocalDate localDate = new LocalDate(bundleEntitlementState.getEffectiveDate(), accountTimeZone);
+ result = result == null || result.compareTo(localDate) < 0 ? localDate : result;
+ }
+
+ final BlockingState accountEntitlementState = blockingStateDao.getBlockingStateForService(accountId, EntitlementService.ENTITLEMENT_SERVICE_NAME, context);
+ if (accountEntitlementState != null && accountEntitlementState .getStateName().equals(ENT_STATE_CANCELLED)) {
+ final LocalDate localDate = new LocalDate(accountEntitlementState.getEffectiveDate(), accountTimeZone);
+ result = result == null || result.compareTo(localDate) < 0 ? localDate : result;
+ }
+ return result;
+ }
+
+ private EntitlementState getStateForEntitlement(final LocalDate entitlementEndDate, final SubscriptionBase subscriptionBase, final DateTimeZone accountTimeZone, final InternalTenantContext context) {
// Current state for the ENTITLEMENT_SERVICE_NAME is set to cancelled
- if (currentState != null &&
- currentState.getStateName().equals(ENT_STATE_CANCELLED) &&
- dateHelper.isBeforeOrEqualsToday(currentState.getEffectiveDate(), accountTimeZone)) {
+ if (entitlementEndDate != null &&
+ entitlementEndDate.compareTo(new LocalDate(clock.getUTCNow(), accountTimeZone)) <= 0) {
return EntitlementState.CANCELLED;
}
@@ -355,13 +388,38 @@ public class DefaultEntitlementApi implements EntitlementApi {
@Override
public UUID transferEntitlements(final UUID sourceAccountId, final UUID destAccountId, final String externalKey, final LocalDate effectiveDate, final CallContext context) throws EntitlementApiException {
- return null;
+ return transferEntitlementsOverrideBillingPolicy(sourceAccountId, destAccountId, externalKey, effectiveDate, BillingActionPolicy.IMMEDIATE, context);
}
@Override
public UUID transferEntitlementsOverrideBillingPolicy(final UUID sourceAccountId, final UUID destAccountId, final String externalKey, final LocalDate effectiveDate, final BillingActionPolicy billingPolicy, final CallContext context) throws EntitlementApiException {
- return null;
- }
+ final boolean cancelImm;
+ switch (billingPolicy) {
+ case IMMEDIATE:
+ cancelImm = true;
+ break;
+ case END_OF_TERM:
+ cancelImm = false;
+ break;
+ default:
+ throw new RuntimeException("Unexpected billing policy " + billingPolicy);
+ }
+ final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(sourceAccountId, context);
+ try {
+ final SubscriptionBaseBundle bundle = subscriptionInternalApi.getBundleForAccountAndKey(sourceAccountId, externalKey, contextWithValidAccountRecordId);
+ final SubscriptionBase baseSubscription = subscriptionInternalApi.getBaseSubscription(bundle.getId(), contextWithValidAccountRecordId);
+
+ final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(effectiveDate, baseSubscription.getStartDate(), contextWithValidAccountRecordId);
+ final SubscriptionBaseBundle newBundle = subscriptionTransferApi.transferBundle(sourceAccountId, destAccountId, externalKey, requestedDate, true, cancelImm, context);
+ blockingStateDao.setBlockingState(new DefaultBlockingState(bundle.getId(), BlockingStateType.BUNDLE, DefaultEntitlementApi.ENT_STATE_CANCELLED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, false, requestedDate), clock, contextWithValidAccountRecordId);
+
+ return newBundle.getId();
+ } catch (SubscriptionBaseTransferApiException e) {
+ throw new EntitlementApiException(e);
+ } catch (SubscriptionBaseApiException e) {
+ throw new EntitlementApiException(e);
+ }
+ }
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlementApi.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlementApi.java
index 617e7d6..e41d2da 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlementApi.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlementApi.java
@@ -3,7 +3,9 @@ package com.ning.billing.entitlement.api;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
+import java.util.UUID;
+import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -11,6 +13,8 @@ import org.testng.annotations.Test;
import com.ning.billing.ErrorCode;
import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountApiException;
+import com.ning.billing.api.TestApiListener.NextEvent;
+import com.ning.billing.catalog.api.BillingActionPolicy;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.PlanPhaseSpecifier;
import com.ning.billing.catalog.api.PriceListSet;
@@ -19,8 +23,11 @@ import com.ning.billing.entitlement.EntitlementTestSuiteWithEmbeddedDB;
import com.ning.billing.entitlement.api.Entitlement.EntitlementSourceType;
import com.ning.billing.entitlement.api.Entitlement.EntitlementState;
+import com.google.common.io.BaseEncoding;
+
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedDB {
@@ -252,4 +259,57 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
Assert.fail("Test failed " + e.getMessage());
}
}
-}
+
+
+
+ @Test(groups = "slow")
+ public void testTransferBundle() {
+
+ try {
+
+ final LocalDate initialDate = new LocalDate(2013, 8, 7);
+ clock.setDay(initialDate);
+
+ final Account accountSrc = accountApi.createAccount(getAccountData(7), callContext);
+
+ final Account accountDesc = accountApi.createAccount(getAccountData(15), callContext);
+
+ final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, null);
+
+ // Create entitlement
+ final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(accountSrc.getId(), spec, accountSrc.getExternalKey(), initialDate, callContext);
+
+ final DateTime ctd = clock.getUTCNow().plusDays(30).plusMonths(1);
+ testListener.pushExpectedEvent(NextEvent.PHASE);
+ clock.addDays(32);
+ // Set manually since no invoice
+ subscriptionInternalApi.setChargedThroughDate(baseEntitlement.getId(), ctd, internalCallContext);
+ assertTrue(testListener.isCompleted(5000));
+
+ // Transfer bundle to dest acccount
+ final LocalDate effectiveDate = new LocalDate(clock.getUTCNow(), accountSrc.getTimeZone());
+ testListener.pushExpectedEvent(NextEvent.TRANSFER);
+ final UUID newBundleId = entitlementApi.transferEntitlementsOverrideBillingPolicy(accountSrc.getId(), accountDesc.getId(), baseEntitlement.getExternalKey(), effectiveDate, BillingActionPolicy.END_OF_TERM, callContext);
+ assertTrue(testListener.isCompleted(5000));
+
+ final Entitlement oldBaseEntitlement = entitlementApi.getAllEntitlementsForAccountIdAndExternalKey(accountSrc.getId(), accountSrc.getExternalKey(), callContext).get(0);
+ assertEquals(oldBaseEntitlement.getEffectiveEndDate(), effectiveDate);
+ assertEquals(oldBaseEntitlement.getState(), EntitlementState.CANCELLED);
+
+ final List<Entitlement> entitlements = entitlementApi.getAllEntitlementsForBundle(newBundleId, callContext);
+ assertEquals(entitlements.size(), 1);
+
+ final Entitlement newBaseEntitlement = entitlements.get(0);
+ assertEquals(newBaseEntitlement.getState(), EntitlementState.ACTIVE);
+ assertEquals(newBaseEntitlement.getEffectiveStartDate(), effectiveDate);
+ assertEquals(newBaseEntitlement.getEffectiveEndDate(), null);
+
+ } catch (AccountApiException e) {
+ Assert.fail("Test failed " + e.getMessage());
+ } catch (EntitlementApiException e) {
+ Assert.fail("Test failed " + e.getMessage());
+ }
+ }
+
+
+ }
diff --git a/subscription/src/main/java/com/ning/billing/subscription/api/transfer/DefaultSubscriptionBaseTransferApi.java b/subscription/src/main/java/com/ning/billing/subscription/api/transfer/DefaultSubscriptionBaseTransferApi.java
index 4dea370..ef05793 100644
--- a/subscription/src/main/java/com/ning/billing/subscription/api/transfer/DefaultSubscriptionBaseTransferApi.java
+++ b/subscription/src/main/java/com/ning/billing/subscription/api/transfer/DefaultSubscriptionBaseTransferApi.java
@@ -271,7 +271,7 @@ public class DefaultSubscriptionBaseTransferApi extends SubscriptionApiBase impl
// Atomically cancel all subscription on old account and create new bundle, subscriptions, events for new account
dao.transfer(sourceAccountId, destAccountId, bundleMigrationData, transferCancelDataList, fromInternalCallContext, toInternalCallContext);
- return bundle;
+ return bundleMigrationData.getData();
} catch (SubscriptionBaseRepairException e) {
throw new SubscriptionBaseTransferApiException(e);
}
diff --git a/util/src/test/java/com/ning/billing/mock/glue/MockSubscriptionModule.java b/util/src/test/java/com/ning/billing/mock/glue/MockSubscriptionModule.java
index 79ac9cf..9e5c5fc 100644
--- a/util/src/test/java/com/ning/billing/mock/glue/MockSubscriptionModule.java
+++ b/util/src/test/java/com/ning/billing/mock/glue/MockSubscriptionModule.java
@@ -51,6 +51,7 @@ public class MockSubscriptionModule extends AbstractModule implements Subscripti
installSubscriptionMigrationApi();
installSubscriptionInternalApi();
installSubscriptionTimelineApi();
+ installSubscriptionTransferApi();
}
@Override