killbill-aplcache

Details

diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
index cb70411..04301a7 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
@@ -485,7 +485,8 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
             public Entitlement apply(@Nullable final Void dontcare) {
                 try {
                     final PlanPhaseSpecifier spec = new PlanPhaseSpecifier(productName, productCategory, billingPeriod, PriceListSet.DEFAULT_PRICELIST_NAME, null);
-                    final Entitlement entitlement = entitlementApi.createBaseEntitlement(accountId, spec, bundleExternalKey, callContext);
+                    final LocalDate effectiveDate = new LocalDate(clock.getUTCNow());
+                    final Entitlement entitlement = entitlementApi.createBaseEntitlement(accountId, spec, bundleExternalKey, effectiveDate, callContext);
                     assertNotNull(entitlement);
                     return entitlement;
                 } catch (EntitlementApiException e) {
@@ -510,7 +511,8 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
             public Entitlement apply(@Nullable final Void dontcare) {
                 try {
                     final PlanPhaseSpecifier spec = new PlanPhaseSpecifier(productName, productCategory, billingPeriod, PriceListSet.DEFAULT_PRICELIST_NAME, null);
-                    final Entitlement entitlement = entitlementApi.addEntitlement(basePlanId, spec, callContext);
+                    final LocalDate effectiveDate = new LocalDate(clock.getUTCNow());
+                    final Entitlement entitlement = entitlementApi.addEntitlement(basePlanId, spec, effectiveDate, callContext);
                     assertNotNull(entitlement);
                     return entitlement;
                 } catch (EntitlementApiException e) {
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 c4614ae..1ff7a58 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
@@ -39,7 +39,6 @@ import com.ning.billing.subscription.api.user.SubscriptionBaseApiException;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalCallContextFactory;
-import com.ning.billing.util.callcontext.TenantContext;
 import com.ning.billing.util.entity.EntityBase;
 import com.ning.billing.util.svcapi.junction.DefaultBlockingState;
 
@@ -54,12 +53,13 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
     protected final BlockingChecker checker;
     protected final UUID accountId;
     protected final String externalKey;
+    protected final EntitlementApi entitlementApi;
     protected final DateTimeZone accountTimeZone;
     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 InternalCallContextFactory internalCallContextFactory,
+                              final EntitlementApi entitlementApi, final InternalCallContextFactory internalCallContextFactory,
                               final BlockingStateDao blockingStateDao,
                               final Clock clock, final BlockingChecker checker) {
         super(subscriptionBase.getId(), subscriptionBase.getCreatedDate(), subscriptionBase.getUpdatedDate());
@@ -68,6 +68,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
         this.accountId = accountId;
         this.externalKey = externalKey;
         this.state = state;
+        this.entitlementApi = entitlementApi;
         this.entitlementBlockingState = entitlementBlockingState;
         this.accountTimeZone = accountTimeZone;
         this.internalCallContextFactory = internalCallContextFactory;
@@ -84,10 +85,10 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
              in.getState(),
              in.getEntitlementBlockingState(),
              in.getAccountTimeZone(),
+             in.getEntitlementApi(),
              in.getInternalCallContextFactory(),
              in.getBlockingStateDao(),
-             in.getClock(),
-             in.getChecker());
+             in.getClock(), in.getChecker());
     }
 
     // STEPH_ENT should be remove but beatrix tests need to be changed
@@ -103,6 +104,10 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
         return internalCallContextFactory;
     }
 
+    public EntitlementApi getEntitlementApi() {
+        return entitlementApi;
+    }
+
     public Clock getClock() {
         return clock;
     }
@@ -220,13 +225,13 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
 
 
     @Override
-    public boolean cancelEntitlementWithPolicy(final EntitlementActionPolicy entitlementPolicy, final CallContext callContext) throws EntitlementApiException {
+    public Entitlement cancelEntitlementWithPolicy(final EntitlementActionPolicy entitlementPolicy, final CallContext callContext) throws EntitlementApiException {
         final LocalDate cancellationDate = getLocalDateFromEntitlementPolicy(entitlementPolicy);
         return cancelEntitlementWithDate(cancellationDate, callContext);
     }
 
     @Override
-    public boolean cancelEntitlementWithDate(final LocalDate localCancelDate, final CallContext callContext) throws EntitlementApiException {
+    public Entitlement cancelEntitlementWithDate(final LocalDate localCancelDate, final CallContext callContext) throws EntitlementApiException {
 
         if (state == EntitlementState.CANCELLED) {
             throw new EntitlementApiException(ErrorCode.SUB_CANCEL_BAD_STATE, getId(), EntitlementState.CANCELLED);
@@ -236,7 +241,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
         try {
             subscriptionBase.cancel(null, callContext);
             blockingStateDao.setBlockingState(new DefaultBlockingState(getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_CANCELLED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, false, effectiveCancelDate), clock, contextWithValidAccountRecordId);
-            return localCancelDate.compareTo(new LocalDate(clock.getUTCNow())) <= 0;
+            return entitlementApi.getEntitlementForId(getId(), callContext);
         } catch (SubscriptionBaseApiException e) {
             throw new EntitlementApiException(e);
         }
@@ -244,13 +249,13 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
 
 
     @Override
-    public boolean cancelEntitlementWithPolicyOverrideBillingPolicy(final EntitlementActionPolicy entitlementPolicy, final BillingActionPolicy billingPolicy, final CallContext callContext) throws EntitlementApiException {
+    public Entitlement cancelEntitlementWithPolicyOverrideBillingPolicy(final EntitlementActionPolicy entitlementPolicy, final BillingActionPolicy billingPolicy, final CallContext callContext) throws EntitlementApiException {
         final LocalDate cancellationDate = getLocalDateFromEntitlementPolicy(entitlementPolicy);
         return cancelEntitlementWithDateOverrideBillingPolicy(cancellationDate, billingPolicy, callContext);
     }
 
     @Override
-    public boolean cancelEntitlementWithDateOverrideBillingPolicy(final LocalDate localCancelDate, final BillingActionPolicy billingPolicy, final CallContext callContext) throws EntitlementApiException {
+    public Entitlement cancelEntitlementWithDateOverrideBillingPolicy(final LocalDate localCancelDate, final BillingActionPolicy billingPolicy, final CallContext callContext) throws EntitlementApiException {
 
         if (state == EntitlementState.CANCELLED) {
             throw new EntitlementApiException(ErrorCode.SUB_CANCEL_BAD_STATE, getId(), EntitlementState.CANCELLED);
@@ -261,7 +266,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
         try {
             subscriptionBase.cancelWithPolicy(null, billingPolicy, callContext);
             blockingStateDao.setBlockingState(new DefaultBlockingState(getId(), BlockingStateType.SUBSCRIPTION, DefaultEntitlementApi.ENT_STATE_CANCELLED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, false, effectiveDate), clock, contextWithValidAccountRecordId);
-            return effectiveLocalDate.compareTo(new LocalDate(clock.getUTCNow())) <= 0;
+            return entitlementApi.getEntitlementForId(getId(), callContext);
         } catch (SubscriptionBaseApiException e) {
             throw new EntitlementApiException(e);
         }
@@ -290,7 +295,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
 
 
     @Override
-    public boolean changePlan(final String productName, final BillingPeriod billingPeriod, final String priceList, final LocalDate localDate, final CallContext callContext) throws EntitlementApiException {
+    public Entitlement changePlan(final String productName, final BillingPeriod billingPeriod, final String priceList, final LocalDate localDate, final CallContext callContext) throws EntitlementApiException {
 
         if (state != EntitlementState.ACTIVE) {
             throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), state);
@@ -300,7 +305,8 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
         final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(localDate, subscriptionBase.getStartDate(), context);
         try {
             checker.checkBlockedChange(subscriptionBase, context);
-            return subscriptionBase.changePlan(productName, billingPeriod, priceList, requestedDate, callContext);
+            subscriptionBase.changePlan(productName, billingPeriod, priceList, requestedDate, callContext);
+            return entitlementApi.getEntitlementForId(getId(), callContext);
         } catch (BlockingApiException e) {
             throw new EntitlementApiException(e, e.getCode(), e.getMessage());
         } catch (SubscriptionBaseApiException e) {
@@ -309,7 +315,7 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
     }
 
     @Override
-    public boolean changePlanOverrideBillingPolicy(final String productName, final BillingPeriod billingPeriod, final String priceList, final LocalDate localDate, final BillingActionPolicy actionPolicy, final CallContext callContext) throws EntitlementApiException {
+    public Entitlement changePlanOverrideBillingPolicy(final String productName, final BillingPeriod billingPeriod, final String priceList, final LocalDate localDate, final BillingActionPolicy actionPolicy, final CallContext callContext) throws EntitlementApiException {
 
         if (state != EntitlementState.ACTIVE) {
             throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), state);
@@ -319,7 +325,8 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
         final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(localDate, subscriptionBase.getStartDate(), context);
         try {
             checker.checkBlockedChange(subscriptionBase, context);
-            return subscriptionBase.changePlanWithPolicy(productName, billingPeriod, priceList, requestedDate, actionPolicy, callContext);
+            subscriptionBase.changePlanWithPolicy(productName, billingPeriod, priceList, requestedDate, actionPolicy, callContext);
+            return entitlementApi.getEntitlementForId(getId(), callContext);
         } catch (BlockingApiException e) {
             throw new EntitlementApiException(e, e.getCode(), e.getMessage());
         } catch (SubscriptionBaseApiException e) {
@@ -328,13 +335,13 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
     }
 
     @Override
-    public boolean block(final String serviceName, final LocalDate effectiveDate, final CallContext context) throws EntitlementApiException {
-        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    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 boolean unblock(final String serviceName, final LocalDate effectiveDate, final CallContext context) throws EntitlementApiException {
-        return false;  //To change body of implemented methods use File | Settings | File Templates.
+    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 ecfe8e4..a419fa0 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
@@ -87,13 +87,16 @@ public class DefaultEntitlementApi implements EntitlementApi {
 
 
     @Override
-    public Entitlement createBaseEntitlement(final UUID accountId, final PlanPhaseSpecifier planPhaseSpecifier, final String externalKey, final CallContext callContext) throws EntitlementApiException {
+    public Entitlement createBaseEntitlement(final UUID accountId, final PlanPhaseSpecifier planPhaseSpecifier, final String externalKey, final LocalDate effectiveDate, final CallContext callContext) throws EntitlementApiException {
         final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(accountId, callContext);
         try {
             final Account account = accountApi.getAccountById(accountId, contextWithValidAccountRecordId);
             final SubscriptionBaseBundle bundle = subscriptionInternalApi.createBundleForAccount(accountId, externalKey, contextWithValidAccountRecordId);
-            final SubscriptionBase subscription = subscriptionInternalApi.createSubscription(bundle.getId(), planPhaseSpecifier, clock.getUTCNow(), contextWithValidAccountRecordId);
-            return new DefaultEntitlement(dateHelper, subscription, accountId, bundle.getExternalKey(), EntitlementState.ACTIVE, null, account.getTimeZone(),
+
+            final DateTime referenceTime = clock.getUTCNow();
+            final DateTime requestedDate = dateHelper.fromLocalDateAndReferenceTime(effectiveDate, referenceTime, contextWithValidAccountRecordId);
+            final SubscriptionBase subscription = subscriptionInternalApi.createSubscription(bundle.getId(), planPhaseSpecifier, requestedDate, contextWithValidAccountRecordId);
+            return new DefaultEntitlement(dateHelper, subscription, accountId, bundle.getExternalKey(), EntitlementState.ACTIVE, null, account.getTimeZone(), this,
                                           internalCallContextFactory, blockingStateDao, clock, checker);
         } catch (SubscriptionBaseApiException e) {
             throw new EntitlementApiException(e);
@@ -103,7 +106,7 @@ public class DefaultEntitlementApi implements EntitlementApi {
     }
 
     @Override
-    public Entitlement addEntitlement(final UUID bundleId, final PlanPhaseSpecifier planPhaseSpecifier, final CallContext callContext) throws EntitlementApiException {
+    public Entitlement addEntitlement(final UUID bundleId, final PlanPhaseSpecifier planPhaseSpecifier, final LocalDate effectiveDate, final CallContext callContext) throws EntitlementApiException {
         final InternalCallContext context = internalCallContextFactory.createInternalCallContext(callContext);
         try {
             final SubscriptionBaseBundle bundle = subscriptionInternalApi.getBundleFromId(bundleId, context);
@@ -129,10 +132,10 @@ public class DefaultEntitlementApi implements EntitlementApi {
             }
 
 
-            final DateTime requestedDate = dateHelper.fromNowAndReferenceTime(baseSubscription.getStartDate(), contextWithValidAccountRecordId);
+            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(),
-                                          internalCallContextFactory, blockingStateDao, clock, checker);
+                                          this, internalCallContextFactory, blockingStateDao, clock, checker);
         } catch (SubscriptionBaseApiException e) {
             throw new EntitlementApiException(e);
         } catch (BlockingApiException e) {
@@ -169,7 +172,7 @@ public class DefaultEntitlementApi implements EntitlementApi {
             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(),
-                                          internalCallContextFactory, blockingStateDao, clock, checker);
+                                          this, internalCallContextFactory, blockingStateDao, clock, checker);
         } catch (SubscriptionBaseApiException e) {
             throw new EntitlementApiException(e);
         } catch (AccountApiException e) {
@@ -217,6 +220,7 @@ public class DefaultEntitlementApi implements EntitlementApi {
         try {
             final Account account = accountApi.getAccountById(accountId, context);
             final List<SubscriptionBase> subscriptions = subscriptionInternalApi.getSubscriptionsForBundle(bundleId, context);
+            final EntitlementApi thisEntitlementApi = this;
             return ImmutableList.<Entitlement>copyOf(Collections2.transform(subscriptions, new Function<SubscriptionBase, Entitlement>() {
                 @Nullable
                 @Override
@@ -228,6 +232,7 @@ public class DefaultEntitlementApi implements EntitlementApi {
                                                   getStateForEntitlement(input, currentState, account.getTimeZone(), context),
                                                   currentState,
                                                   account.getTimeZone(),
+                                                  thisEntitlementApi,
                                                   internalCallContextFactory, blockingStateDao, clock, checker);
                 }
             }));
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionApi.java
index e38318c..a825a88 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionApi.java
@@ -90,6 +90,20 @@ public class DefaultSubscriptionApi implements SubscriptionApi  {
     }
 
     @Override
+    public List<SubscriptionBundle> getSubscriptionBundlesForExternalKey(final String externalKey, final TenantContext context) throws SubscriptionApiException {
+
+        final InternalTenantContext internalContext = internalCallContextFactory.createInternalTenantContext(context);
+        final List<SubscriptionBaseBundle> bundles = subscriptionInternalApi.getBundlesForKey(externalKey, internalContext);
+
+        final  List<SubscriptionBundle> result = new ArrayList<SubscriptionBundle>(bundles.size());
+        for (SubscriptionBaseBundle cur : bundles) {
+            final SubscriptionBundle bundle = getSubscriptionBundleForAccountIdAndExternalKey(cur.getAccountId(), cur.getExternalKey(), context);
+            result.add(bundle);
+        }
+        return result;
+    }
+
+    @Override
     public List<SubscriptionBundle> getSubscriptionBundlesForAccountId(final UUID accountId, final TenantContext context) throws SubscriptionApiException {
         try {
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/EntitlementDateHelper.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/EntitlementDateHelper.java
index 9d31196..dce1902 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/EntitlementDateHelper.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/EntitlementDateHelper.java
@@ -21,40 +21,32 @@ public class EntitlementDateHelper {
         this.clock = clock;
     }
 
-
-    public DateTime fromLocalDateAndReferenceTime(final LocalDate requestedDate, final DateTime referenceDateTime, final InternalTenantContext callContext) throws EntitlementApiException {
+    public DateTime fromNowAndReferenceTime(final DateTime referenceDateTime, final InternalTenantContext callContext) throws EntitlementApiException {
         try {
-
             final Account account = accountApi.getAccountByRecordId(callContext.getAccountRecordId(), callContext);
-            return fromLocalDateAndReferenceTime(requestedDate, referenceDateTime, account.getTimeZone());
+            return fromNowAndReferenceTime(referenceDateTime, account.getTimeZone());
         } catch (AccountApiException e) {
             throw new EntitlementApiException(e);
         }
     }
 
-    public DateTime fromLocalDateAndReferenceTime(final LocalDate requestedDate, final DateTime referenceDateTime, final DateTimeZone accountTimeZone) throws EntitlementApiException {
-        final LocalDate localDateNowInAccountTimezone = new LocalDate(requestedDate, accountTimeZone);
-
-        // Datetime from local date in account timezone and with given reference time
-        final DateTime t1 = localDateNowInAccountTimezone.toDateTime(referenceDateTime.toLocalTime(), accountTimeZone);
-        // Datetime converted back in UTC
-        final DateTime t2 = new DateTime(t1, DateTimeZone.UTC);
-        return t2;
-
+    public DateTime fromNowAndReferenceTime(final DateTime referenceDateTime, final DateTimeZone accountTimeZone) {
+        final LocalDate localDateNowInAccountTimezone = new LocalDate(clock.getUTCNow(), accountTimeZone);
+        return fromLocalDateAndReferenceTime(localDateNowInAccountTimezone, referenceDateTime, accountTimeZone);
     }
 
-
-    public DateTime fromNowAndReferenceTime(final DateTime referenceDateTime, final InternalTenantContext callContext) throws EntitlementApiException {
+    public DateTime fromLocalDateAndReferenceTime(final LocalDate requestedDate, final DateTime referenceDateTime, final InternalTenantContext callContext) throws EntitlementApiException {
         try {
+
             final Account account = accountApi.getAccountByRecordId(callContext.getAccountRecordId(), callContext);
-            return fromNowAndReferenceTime(referenceDateTime, account.getTimeZone());
+            return fromLocalDateAndReferenceTime(requestedDate, referenceDateTime, account.getTimeZone());
         } catch (AccountApiException e) {
             throw new EntitlementApiException(e);
         }
     }
 
-    public DateTime fromNowAndReferenceTime(final DateTime referenceDateTime, final DateTimeZone accountTimeZone) {
-        final LocalDate localDateNowInAccountTimezone = new LocalDate(clock.getUTCNow(), accountTimeZone);
+    public DateTime fromLocalDateAndReferenceTime(final LocalDate requestedDate, final DateTime referenceDateTime, final DateTimeZone accountTimeZone) {
+        final LocalDate localDateNowInAccountTimezone = new LocalDate(requestedDate, accountTimeZone);
         // Datetime from local date in account timezone and with given reference time
         final DateTime t1 = localDateNowInAccountTimezone.toDateTime(referenceDateTime.toLocalTime(), accountTimeZone);
         // Datetime converted back in UTC
@@ -62,6 +54,8 @@ public class EntitlementDateHelper {
         return t2;
     }
 
+
+
     // STEPH_ENT test
     public boolean isBeforeOrEqualsNow(final DateTime inputDate, final DateTimeZone accountTimeZone) {
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlement.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlement.java
index 456d9eb..07893a9 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlement.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlement.java
@@ -36,7 +36,7 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
             final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
 
             // Create entitlement and check each field
-            final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), callContext);
+            final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), initialDate, callContext);
             assertEquals(entitlement.getState(), EntitlementState.ACTIVE);
 
             clock.addDays(5);
@@ -66,7 +66,7 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
             final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
 
             // Create entitlement and check each field
-            final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), callContext);
+            final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), initialDate, callContext);
             assertEquals(entitlement.getState(), EntitlementState.ACTIVE);
 
             clock.addDays(5);
@@ -102,14 +102,11 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
             final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
 
             // Create entitlement and check each field
-            final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), callContext);
+            final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), initialDate, callContext);
 
-            final boolean isCancelled = entitlement.cancelEntitlementWithPolicy(EntitlementActionPolicy.END_OF_TERM, callContext);
-            assertTrue(isCancelled);
-
-            final Entitlement entitlement2 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
-            assertEquals(entitlement2.getState(), EntitlementState.CANCELLED);
-            assertEquals(entitlement2.getEffectiveEndDate(), initialDate);
+            final Entitlement cancelledEntitlement = entitlement.cancelEntitlementWithPolicy(EntitlementActionPolicy.END_OF_TERM, callContext);
+            assertEquals(cancelledEntitlement.getState(), EntitlementState.CANCELLED);
+            assertEquals(cancelledEntitlement.getEffectiveEndDate(), initialDate);
 
         } catch (EntitlementApiException e) {
             Assert.fail("Test failed " + e.getMessage());
@@ -132,7 +129,7 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
             final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
 
             // Create entitlement and check each field
-            final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), callContext);
+            final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), initialDate, callContext);
 
             final DateTime ctd = clock.getUTCNow().plusDays(30).plusMonths(1);
             testListener.pushExpectedEvent(NextEvent.PHASE);
@@ -142,10 +139,7 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
             assertTrue(testListener.isCompleted(5000));
 
             final Entitlement entitlement2 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
-            final boolean isCancelled = entitlement2.cancelEntitlementWithPolicy(EntitlementActionPolicy.END_OF_TERM, callContext);
-            assertFalse(isCancelled);
-
-            final Entitlement entitlement3 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
+            final Entitlement entitlement3 = entitlement2.cancelEntitlementWithPolicy(EntitlementActionPolicy.END_OF_TERM, callContext);
             assertEquals(entitlement3.getState(), EntitlementState.ACTIVE);
             assertNull(entitlement3.getEffectiveEndDate());
 
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 4a7b482..b452405 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
@@ -40,7 +40,7 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
             final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
 
             // Create entitlement and check each field
-            final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), callContext);
+            final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), initialDate, callContext);
             assertEquals(entitlement.getAccountId(), account.getId());
             assertEquals(entitlement.getExternalKey(), account.getExternalKey());
 
@@ -140,11 +140,11 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
             final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, null);
 
             // Create entitlement and check each field
-            final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), callContext);
+            final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), initialDate, callContext);
 
             // Add ADD_ON
             final PlanPhaseSpecifier spec1 = new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
-            final Entitlement telescopicEntitlement = entitlementApi.addEntitlement(baseEntitlement.getBundleId(), spec1, callContext);
+            final Entitlement telescopicEntitlement = entitlementApi.addEntitlement(baseEntitlement.getBundleId(), spec1, initialDate, callContext);
 
             assertEquals(telescopicEntitlement.getAccountId(), account.getId());
             assertEquals(telescopicEntitlement.getExternalKey(), account.getExternalKey());
@@ -185,12 +185,12 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
             final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, null);
 
             // Create entitlement and check each field
-            final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), callContext);
+            final Entitlement baseEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), initialDate, callContext);
 
             clock.addDays(1);
-
+            final LocalDate effectiveDateSpec1 = new LocalDate(clock.getUTCNow(), account.getTimeZone());
             final PlanPhaseSpecifier spec1 = new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
-            final Entitlement telescopicEntitlement = entitlementApi.addEntitlement(baseEntitlement.getBundleId(), spec1, callContext);
+            final Entitlement telescopicEntitlement = entitlementApi.addEntitlement(baseEntitlement.getBundleId(), spec1, effectiveDateSpec1, callContext);
 
             // Block all entitlement in the bundle
             clock.addDays(5);
@@ -221,7 +221,7 @@ public class TestDefaultEntitlementApi extends EntitlementTestSuiteWithEmbeddedD
             // Try to add an ADD_ON, it should fail
             try {
                 final PlanPhaseSpecifier spec3 = new PlanPhaseSpecifier("Telescopic-Scope", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, null);
-                final Entitlement telescopicEntitlement3 = entitlementApi.addEntitlement(baseEntitlement.getBundleId(), spec1, callContext);
+                final Entitlement telescopicEntitlement3 = entitlementApi.addEntitlement(baseEntitlement.getBundleId(), spec1, effectiveDateSpec1, callContext);
             } catch (EntitlementApiException e) {
                 assertEquals(e.getCode(), ErrorCode.SUB_GET_NO_SUCH_BASE_SUBSCRIPTION.getCode());
             }
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/EntitlementResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/EntitlementResource.java
index 78157d5..4dbf7d2 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/EntitlementResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/EntitlementResource.java
@@ -50,6 +50,7 @@ import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.api.Entitlement;
+import com.ning.billing.entitlement.api.Entitlement.EntitlementState;
 import com.ning.billing.entitlement.api.EntitlementApi;
 import com.ning.billing.entitlement.api.EntitlementApiException;
 import com.ning.billing.jaxrs.json.CustomFieldJson;
@@ -115,7 +116,7 @@ public class EntitlementResource extends JaxRsResourceBase {
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON)
     public Response createEntitlement(final EntitlementJsonNoEvents entitlement,
-                                      //@QueryParam(QUERY_REQUESTED_DT) final String requestedDate,
+                                      @QueryParam(QUERY_REQUESTED_DT) final String requestedDate,
                                       @QueryParam(QUERY_CALL_COMPLETION) @DefaultValue("false") final Boolean callCompletion,
                                       @QueryParam(QUERY_CALL_TIMEOUT) @DefaultValue("3") final long timeoutSec,
                                       @HeaderParam(HDR_CREATED_BY) final String createdBy,
@@ -123,7 +124,7 @@ public class EntitlementResource extends JaxRsResourceBase {
                                       @HeaderParam(HDR_COMMENT) final String comment,
                                       @javax.ws.rs.core.Context final HttpServletRequest request) throws EntitlementApiException, AccountApiException {
         final CallContext callContext = context.createContext(createdBy, reason, comment, request);
-
+        final DateTime inputDate = (requestedDate != null) ? DATE_TIME_FORMATTER.parseDateTime(requestedDate) : null;
         final EntitlementCallCompletionCallback<Entitlement> callback = new EntitlementCallCompletionCallback<Entitlement>() {
             @Override
             public Entitlement doOperation(final CallContext ctx) throws InterruptedException, TimeoutException, EntitlementApiException {
@@ -135,10 +136,11 @@ public class EntitlementResource extends JaxRsResourceBase {
 
 
                 final UUID accountId = entitlement.getAccountId() != null ? UUID.fromString(entitlement.getAccountId()) : null;
+                final LocalDate inputLocalDate = toLocalDate(accountId, inputDate, callContext);
                 final UUID bundleId = entitlement.getBundleId() != null ? UUID.fromString(entitlement.getBundleId()) : null;
                 return (entitlement.getProductCategory().equals(ProductCategory.ADD_ON.toString())) ?
-                       entitlementApi.addEntitlement(bundleId, spec, callContext) :
-                       entitlementApi.createBaseEntitlement(accountId, spec, entitlement.getExternalKey(), callContext);
+                       entitlementApi.addEntitlement(bundleId, spec, inputLocalDate, callContext) :
+                       entitlementApi.createBaseEntitlement(accountId, spec, entitlement.getExternalKey(), inputLocalDate, callContext);
             }
 
             @Override
@@ -185,12 +187,16 @@ public class EntitlementResource extends JaxRsResourceBase {
 
                 final Entitlement current = entitlementApi.getEntitlementForId(uuid, callContext);
                 final LocalDate inputLocalDate = toLocalDate(current.getAccountId(), inputDate, callContext);
+                final Entitlement newEntitlement;
                 if (policyString == null) {
-                    isImmediateOp = current.changePlan(entitlement.getProductName(), BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList(), inputLocalDate, ctx);
+                    newEntitlement = current.changePlan(entitlement.getProductName(), BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList(), inputLocalDate, ctx);
                 } else {
                     final BillingActionPolicy policy = BillingActionPolicy.valueOf(policyString.toUpperCase());
-                    isImmediateOp = current.changePlanOverrideBillingPolicy(entitlement.getProductName(), BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList(), inputLocalDate, policy, ctx);
+                    newEntitlement  = current.changePlanOverrideBillingPolicy(entitlement.getProductName(), BillingPeriod.valueOf(entitlement.getBillingPeriod()), entitlement.getPriceList(), inputLocalDate, policy, ctx);
                 }
+                isImmediateOp = newEntitlement.getProduct().getName().equals(entitlement.getProductName()) &&
+                                newEntitlement.getPlan().getBillingPeriod() == BillingPeriod.valueOf(entitlement.getBillingPeriod()) &&
+                                newEntitlement.getPriceList().getName().equals(entitlement.getPriceList());
                 return Response.status(Status.OK).build();
             }
 
@@ -256,12 +262,14 @@ public class EntitlementResource extends JaxRsResourceBase {
                 final DateTime inputDate = (requestedDate != null) ? DATE_TIME_FORMATTER.parseDateTime(requestedDate) : null;
                 final LocalDate inputLocalDate = toLocalDate(current.getAccountId(), inputDate, callContext);
 
+                final Entitlement newEntitlement;
                 if (policyString == null) {
-                    isImmediateOp = current.cancelEntitlementWithDate(inputLocalDate, ctx);
+                    newEntitlement = current.cancelEntitlementWithDate(inputLocalDate, ctx);
                 } else {
                     final BillingActionPolicy policy = BillingActionPolicy.valueOf(policyString.toUpperCase());
-                    isImmediateOp = current.cancelEntitlementWithDateOverrideBillingPolicy(inputLocalDate, policy, ctx);
+                    newEntitlement = current.cancelEntitlementWithDateOverrideBillingPolicy(inputLocalDate, policy, ctx);
                 }
+                isImmediateOp = newEntitlement.getState() == EntitlementState.ACTIVE;
                 return Response.status(Status.OK).build();
             }
 
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
index 6c53b52..621c67b 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
@@ -191,11 +191,26 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
         return Response.status(Response.Status.OK).build();
     }
 
-    protected LocalDate toLocalDate(final UUID accountId, final DateTime inputDate, final TenantContext context) throws AccountApiException {
-        if (inputDate == null) {
-            return null;
+    protected LocalDate toLocalDate(final UUID accountId, final DateTime inputDate, final TenantContext context)  {
+        Account account = null;
+        try {
+            account = accountId != null ? accountUserApi.getAccountById(accountId, context) : null;
+        } catch (AccountApiException e) {
+            log.info("Failed to retrieve account for id " + accountId );
+        }
+
+        if (account == null && inputDate == null) {
+            // We have no inputDate and so accountTimeZone so we default to LocalDate as seen in UTC
+            return new LocalDate();
+        } else if (account == null && inputDate != null) {
+            // We were given a date but can't get timezone, default in UTC
+            return new LocalDate(inputDate);
+        } else if (account != null && inputDate == null) {
+            // We have no inputDate but for accountTimeZone so default to LocalDate as seen in account timezone
+            return new LocalDate(account.getTimeZone());
+        } else {
+            // Precise LocalDate as requested
+            return new LocalDate(inputDate, account.getTimeZone());
         }
-        final Account account = accountUserApi.getAccountById(accountId, context);
-        return new LocalDate(inputDate, account.getTimeZone());
     }
 }