killbill-aplcache

entitlement: Fix bug where we ignore the effectiveDate of the

11/2/2015 11:53:39 PM

Details

diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java
index 44cfbc1..59d7909 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java
@@ -453,12 +453,6 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
                     throw new EntitlementApiException(ErrorCode.SUB_CHANGE_NON_ACTIVE, getId(), getState());
                 }
 
-                final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
-                try {
-                    checker.checkBlockedChange(getSubscriptionBase(), context);
-                } catch (BlockingApiException e) {
-                    throw new EntitlementApiException(e, e.getCode(), e.getMessage());
-                }
 
                 final DateTime effectiveChangeDate;
                 try {
@@ -467,6 +461,13 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
                     throw new EntitlementApiException(e);
                 }
 
+                final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
+                try {
+                    checker.checkBlockedChange(getSubscriptionBase(), effectiveChangeDate, context);
+                } catch (BlockingApiException e) {
+                    throw new EntitlementApiException(e, e.getCode(), e.getMessage());
+                }
+
                 blockAddOnsIfRequired(effectiveChangeDate, callContext, context);
 
                 return entitlementApi.getEntitlementForId(getId(), callContext);
@@ -502,12 +503,6 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
                 }
 
                 final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
-                try {
-                    checker.checkBlockedChange(getSubscriptionBase(), context);
-                } catch (BlockingApiException e) {
-                    throw new EntitlementApiException(e, e.getCode(), e.getMessage());
-                }
-
                 final DateTime effectiveChangeDate = dateHelper.fromLocalDateAndReferenceTime(updatedPluginContext.getEffectiveDate(), getSubscriptionBase().getStartDate(), context);
                 try {
                     getSubscriptionBase().changePlanWithDate(productName, billingPeriod, priceList, overrides, effectiveChangeDate, callContext);
@@ -515,6 +510,13 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
                     throw new EntitlementApiException(e);
                 }
 
+                try {
+                    checker.checkBlockedChange(getSubscriptionBase(), effectiveChangeDate, context);
+                } catch (BlockingApiException e) {
+                    throw new EntitlementApiException(e, e.getCode(), e.getMessage());
+                }
+
+
                 blockAddOnsIfRequired(effectiveChangeDate, callContext, context);
 
                 return entitlementApi.getEntitlementForId(getId(), callContext);
@@ -550,11 +552,6 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
                 }
 
                 final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
-                try {
-                    checker.checkBlockedChange(getSubscriptionBase(), context);
-                } catch (BlockingApiException e) {
-                    throw new EntitlementApiException(e, e.getCode(), e.getMessage());
-                }
 
                 final DateTime effectiveChangeDate;
                 try {
@@ -563,6 +560,12 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
                     throw new EntitlementApiException(e);
                 }
 
+                try {
+                    checker.checkBlockedChange(getSubscriptionBase(), effectiveChangeDate, context);
+                } catch (BlockingApiException e) {
+                    throw new EntitlementApiException(e, e.getCode(), e.getMessage());
+                }
+
                 blockAddOnsIfRequired(effectiveChangeDate, callContext, context);
 
                 return entitlementApi.getEntitlementForId(getId(), callContext);
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/block/BlockingChecker.java b/entitlement/src/main/java/org/killbill/billing/entitlement/block/BlockingChecker.java
index 903df5a..c3d416e 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/block/BlockingChecker.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/block/BlockingChecker.java
@@ -19,6 +19,7 @@ package org.killbill.billing.entitlement.block;
 import java.util.List;
 import java.util.UUID;
 
+import org.joda.time.DateTime;
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.entitlement.api.Blockable;
 import org.killbill.billing.entitlement.api.BlockingApiException;
@@ -47,11 +48,11 @@ public interface BlockingChecker {
     public BlockingAggregator getBlockedStatus(List<BlockingState> currentAccountEntitlementStatePerService, List<BlockingState> currentBundleEntitlementStatePerService,
                                                List<BlockingState> currentSubscriptionEntitlementStatePerService, InternalTenantContext internalTenantContext);
 
-    public BlockingAggregator getBlockedStatus(final UUID blockableId, final BlockingStateType type, final InternalTenantContext context) throws BlockingApiException;
+    public BlockingAggregator getBlockedStatus(final UUID blockableId, final BlockingStateType type, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException;
 
-    public void checkBlockedChange(Blockable blockable, InternalTenantContext context) throws BlockingApiException;
+    public void checkBlockedChange(Blockable blockable, final DateTime upToDate, InternalTenantContext context) throws BlockingApiException;
 
-    public void checkBlockedEntitlement(Blockable blockable, InternalTenantContext context) throws BlockingApiException;
+    public void checkBlockedEntitlement(Blockable blockable, final DateTime upToDate, InternalTenantContext context) throws BlockingApiException;
 
-    public void checkBlockedBilling(Blockable blockable, InternalTenantContext context) throws BlockingApiException;
+    public void checkBlockedBilling(Blockable blockable, final DateTime upToDate, InternalTenantContext context) throws BlockingApiException;
 }
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/block/DefaultBlockingChecker.java b/entitlement/src/main/java/org/killbill/billing/entitlement/block/DefaultBlockingChecker.java
index 538bed0..d468dbd 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/block/DefaultBlockingChecker.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/block/DefaultBlockingChecker.java
@@ -21,6 +21,7 @@ import java.util.UUID;
 
 import javax.annotation.Nullable;
 
+import org.joda.time.DateTime;
 import org.killbill.billing.ErrorCode;
 import org.killbill.billing.account.api.Account;
 import org.killbill.billing.callcontext.InternalTenantContext;
@@ -120,67 +121,67 @@ public class DefaultBlockingChecker implements BlockingChecker {
         this.dao = dao;
     }
 
-    private DefaultBlockingAggregator getBlockedStateSubscriptionId(final UUID subscriptionId, final InternalTenantContext context) throws BlockingApiException {
+    private DefaultBlockingAggregator getBlockedStateSubscriptionId(final UUID subscriptionId, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
         final SubscriptionBase subscription;
         try {
             subscription = subscriptionApi.getSubscriptionFromId(subscriptionId, context);
-            return getBlockedStateSubscription(subscription, context);
+            return getBlockedStateSubscription(subscription, upToDate, context);
         } catch (SubscriptionBaseApiException e) {
             throw new BlockingApiException(e, ErrorCode.fromCode(e.getCode()));
         }
     }
 
-    private DefaultBlockingAggregator getBlockedStateSubscription(final SubscriptionBase subscription, final InternalTenantContext context) throws BlockingApiException {
+    private DefaultBlockingAggregator getBlockedStateSubscription(final SubscriptionBase subscription, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
         final DefaultBlockingAggregator result = new DefaultBlockingAggregator();
         if (subscription != null) {
-            final DefaultBlockingAggregator subscriptionState = getBlockedStateForId(subscription.getId(), BlockingStateType.SUBSCRIPTION, context);
+            final DefaultBlockingAggregator subscriptionState = getBlockedStateForId(subscription.getId(), BlockingStateType.SUBSCRIPTION, upToDate, context);
             if (subscriptionState != null) {
                 result.or(subscriptionState);
             }
             if (subscription.getBundleId() != null) {
                 // Recursive call to also fetch account state
-                result.or(getBlockedStateBundleId(subscription.getBundleId(), context));
+                result.or(getBlockedStateBundleId(subscription.getBundleId(), upToDate, context));
             }
         }
         return result;
     }
 
-    private DefaultBlockingAggregator getBlockedStateBundleId(final UUID bundleId, final InternalTenantContext context) throws BlockingApiException {
+    private DefaultBlockingAggregator getBlockedStateBundleId(final UUID bundleId, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
 
         final SubscriptionBaseBundle bundle;
         try {
             bundle = subscriptionApi.getBundleFromId(bundleId, context);
-            return getBlockedStateBundle(bundle, context);
+            return getBlockedStateBundle(bundle, upToDate, context);
         } catch (SubscriptionBaseApiException e) {
             throw new BlockingApiException(e, ErrorCode.fromCode(e.getCode()));
         }
     }
 
-    private DefaultBlockingAggregator getBlockedStateBundle(final SubscriptionBaseBundle bundle, final InternalTenantContext context) {
-        final DefaultBlockingAggregator result = getBlockedStateAccountId(bundle.getAccountId(), context);
-        final DefaultBlockingAggregator bundleState = getBlockedStateForId(bundle.getId(), BlockingStateType.SUBSCRIPTION_BUNDLE, context);
+    private DefaultBlockingAggregator getBlockedStateBundle(final SubscriptionBaseBundle bundle, final DateTime upToDate, final InternalTenantContext context) {
+        final DefaultBlockingAggregator result = getBlockedStateAccountId(bundle.getAccountId(), upToDate, context);
+        final DefaultBlockingAggregator bundleState = getBlockedStateForId(bundle.getId(), BlockingStateType.SUBSCRIPTION_BUNDLE, upToDate, context);
         if (bundleState != null) {
             result.or(bundleState);
         }
         return result;
     }
 
-    private DefaultBlockingAggregator getBlockedStateAccount(final Account account, final InternalTenantContext context) {
+    private DefaultBlockingAggregator getBlockedStateAccount(final Account account, final DateTime upToDate, final InternalTenantContext context) {
         if (account != null) {
-            return getBlockedStateForId(account.getId(), BlockingStateType.ACCOUNT, context);
+            return getBlockedStateForId(account.getId(), BlockingStateType.ACCOUNT, upToDate, context);
         }
         return new DefaultBlockingAggregator();
     }
 
-    private DefaultBlockingAggregator getBlockedStateAccountId(final UUID accountId, final InternalTenantContext context) {
-        return getBlockedStateForId(accountId, BlockingStateType.ACCOUNT, context);
+    private DefaultBlockingAggregator getBlockedStateAccountId(final UUID accountId, final DateTime upToDate, final InternalTenantContext context) {
+        return getBlockedStateForId(accountId, BlockingStateType.ACCOUNT, upToDate, context);
     }
 
-    private DefaultBlockingAggregator getBlockedStateForId(@Nullable final UUID blockableId, final BlockingStateType blockingStateType, final InternalTenantContext context) {
+    private DefaultBlockingAggregator getBlockedStateForId(@Nullable final UUID blockableId, final BlockingStateType blockingStateType, final DateTime upToDate, final InternalTenantContext context) {
         // Last states across services
         final List<BlockingState> blockableState;
         if (blockableId != null) {
-            blockableState = dao.getBlockingState(blockableId, blockingStateType, context);
+            blockableState = dao.getBlockingState(blockableId, blockingStateType, upToDate, context);
         } else {
             blockableState = ImmutableList.<BlockingState>of();
         }
@@ -196,13 +197,13 @@ public class DefaultBlockingChecker implements BlockingChecker {
     }
 
     @Override
-    public BlockingAggregator getBlockedStatus(final UUID blockableId, final BlockingStateType type, final InternalTenantContext context) throws BlockingApiException {
+    public BlockingAggregator getBlockedStatus(final UUID blockableId, final BlockingStateType type, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
         if (type == BlockingStateType.SUBSCRIPTION) {
-            return getBlockedStateSubscriptionId(blockableId, context);
+            return getBlockedStateSubscriptionId(blockableId, upToDate, context);
         } else if (type == BlockingStateType.SUBSCRIPTION_BUNDLE) {
-            return getBlockedStateBundleId(blockableId, context);
+            return getBlockedStateBundleId(blockableId, upToDate, context);
         } else { // BlockingStateType.ACCOUNT {
-            return getBlockedStateAccountId(blockableId, context);
+            return getBlockedStateAccountId(blockableId, upToDate, context);
         }
     }
 
@@ -215,34 +216,34 @@ public class DefaultBlockingChecker implements BlockingChecker {
     }
 
     @Override
-    public void checkBlockedChange(final Blockable blockable, final InternalTenantContext context) throws BlockingApiException {
-        if (blockable instanceof SubscriptionBase && getBlockedStateSubscription((SubscriptionBase) blockable, context).isBlockChange()) {
+    public void checkBlockedChange(final Blockable blockable, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
+        if (blockable instanceof SubscriptionBase && getBlockedStateSubscription((SubscriptionBase) blockable, upToDate, context).isBlockChange()) {
             throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_CHANGE, TYPE_SUBSCRIPTION, blockable.getId().toString());
-        } else if (blockable instanceof SubscriptionBaseBundle && getBlockedStateBundle((SubscriptionBaseBundle) blockable, context).isBlockChange()) {
+        } else if (blockable instanceof SubscriptionBaseBundle && getBlockedStateBundle((SubscriptionBaseBundle) blockable, upToDate, context).isBlockChange()) {
             throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_CHANGE, TYPE_BUNDLE, blockable.getId().toString());
-        } else if (blockable instanceof Account && getBlockedStateAccount((Account) blockable, context).isBlockChange()) {
+        } else if (blockable instanceof Account && getBlockedStateAccount((Account) blockable, upToDate, context).isBlockChange()) {
             throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_CHANGE, TYPE_ACCOUNT, blockable.getId().toString());
         }
     }
 
     @Override
-    public void checkBlockedEntitlement(final Blockable blockable, final InternalTenantContext context) throws BlockingApiException {
-        if (blockable instanceof SubscriptionBase && getBlockedStateSubscription((SubscriptionBase) blockable, context).isBlockEntitlement()) {
+    public void checkBlockedEntitlement(final Blockable blockable, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
+        if (blockable instanceof SubscriptionBase && getBlockedStateSubscription((SubscriptionBase) blockable, upToDate, context).isBlockEntitlement()) {
             throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_ENTITLEMENT, TYPE_SUBSCRIPTION, blockable.getId().toString());
-        } else if (blockable instanceof SubscriptionBaseBundle && getBlockedStateBundle((SubscriptionBaseBundle) blockable, context).isBlockEntitlement()) {
+        } else if (blockable instanceof SubscriptionBaseBundle && getBlockedStateBundle((SubscriptionBaseBundle) blockable, upToDate, context).isBlockEntitlement()) {
             throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_ENTITLEMENT, TYPE_BUNDLE, blockable.getId().toString());
-        } else if (blockable instanceof Account && getBlockedStateAccount((Account) blockable, context).isBlockEntitlement()) {
+        } else if (blockable instanceof Account && getBlockedStateAccount((Account) blockable, upToDate, context).isBlockEntitlement()) {
             throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_ENTITLEMENT, TYPE_ACCOUNT, blockable.getId().toString());
         }
     }
 
     @Override
-    public void checkBlockedBilling(final Blockable blockable, final InternalTenantContext context) throws BlockingApiException {
-        if (blockable instanceof SubscriptionBase && getBlockedStateSubscription((SubscriptionBase) blockable, context).isBlockBilling()) {
+    public void checkBlockedBilling(final Blockable blockable, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
+        if (blockable instanceof SubscriptionBase && getBlockedStateSubscription((SubscriptionBase) blockable, upToDate, context).isBlockBilling()) {
             throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_BILLING, TYPE_SUBSCRIPTION, blockable.getId().toString());
-        } else if (blockable instanceof SubscriptionBaseBundle && getBlockedStateBundle((SubscriptionBaseBundle) blockable, context).isBlockBilling()) {
+        } else if (blockable instanceof SubscriptionBaseBundle && getBlockedStateBundle((SubscriptionBaseBundle) blockable, upToDate, context).isBlockBilling()) {
             throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_BILLING, TYPE_BUNDLE, blockable.getId().toString());
-        } else if (blockable instanceof Account && getBlockedStateAccount((Account) blockable, context).isBlockBilling()) {
+        } else if (blockable instanceof Account && getBlockedStateAccount((Account) blockable, upToDate, context).isBlockBilling()) {
             throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION, ACTION_BILLING, TYPE_ACCOUNT, blockable.getId().toString());
         }
     }
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/dao/BlockingStateDao.java b/entitlement/src/main/java/org/killbill/billing/entitlement/dao/BlockingStateDao.java
index c2d8c7f..493b519 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/dao/BlockingStateDao.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/dao/BlockingStateDao.java
@@ -19,6 +19,7 @@ package org.killbill.billing.entitlement.dao;
 import java.util.List;
 import java.util.UUID;
 
+import org.joda.time.DateTime;
 import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.clock.Clock;
@@ -48,7 +49,7 @@ public interface BlockingStateDao extends EntityDao<BlockingStateModelDao, Block
      * @param context           call context
      * @return list of current blocking states for that blockable object
      */
-    public List<BlockingState> getBlockingState(UUID blockableId, BlockingStateType blockingStateType, InternalTenantContext context);
+    public List<BlockingState> getBlockingState(UUID blockableId, BlockingStateType blockingStateType, DateTime upToDate, InternalTenantContext context);
 
     /**
      * Return all events (past and future) across all services) for a given callcontext (account_record_id)
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/dao/DefaultBlockingStateDao.java b/entitlement/src/main/java/org/killbill/billing/entitlement/dao/DefaultBlockingStateDao.java
index dcbce47..9b72f19 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/dao/DefaultBlockingStateDao.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/dao/DefaultBlockingStateDao.java
@@ -26,6 +26,7 @@ import java.util.UUID;
 
 import javax.annotation.Nullable;
 
+import org.joda.time.DateTime;
 import org.killbill.billing.ErrorCode;
 import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.callcontext.InternalTenantContext;
@@ -102,12 +103,12 @@ public class DefaultBlockingStateDao extends EntityDaoBase<BlockingStateModelDao
     }
 
     @Override
-    public List<BlockingState> getBlockingState(final UUID blockableId, final BlockingStateType blockingStateType, final InternalTenantContext context) {
+    public List<BlockingState> getBlockingState(final UUID blockableId, final BlockingStateType blockingStateType, final DateTime upToDate, final InternalTenantContext context) {
         return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<BlockingState>>() {
             @Override
             public List<BlockingState> inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
                 // Upper bound time limit is now
-                final Date upTo = clock.getUTCNow().toDate();
+                final Date upTo = upToDate.toDate();
                 final List<BlockingStateModelDao> models = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingState(blockableId, upTo, context);
                 final Collection<BlockingStateModelDao> modelsFiltered = filterBlockingStates(models, blockingStateType);
                 return new ArrayList<BlockingState>(Collections2.transform(modelsFiltered, new Function<BlockingStateModelDao, BlockingState>() {
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/dao/ProxyBlockingStateDao.java b/entitlement/src/main/java/org/killbill/billing/entitlement/dao/ProxyBlockingStateDao.java
index b404562..92f6fb0 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/dao/ProxyBlockingStateDao.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/dao/ProxyBlockingStateDao.java
@@ -218,8 +218,8 @@ public class ProxyBlockingStateDao implements BlockingStateDao {
     }
 
     @Override
-    public List<BlockingState> getBlockingState(final UUID blockableId, final BlockingStateType blockingStateType, final InternalTenantContext context) {
-        return delegate.getBlockingState(blockableId, blockingStateType, context);
+    public List<BlockingState> getBlockingState(final UUID blockableId, final BlockingStateType blockingStateType, final DateTime upToDate, final InternalTenantContext context) {
+        return delegate.getBlockingState(blockableId, blockingStateType, upToDate, context);
     }
 
     @Override
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/engine/core/EntitlementUtils.java b/entitlement/src/main/java/org/killbill/billing/entitlement/engine/core/EntitlementUtils.java
index da4ccaa..6be5e37 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/engine/core/EntitlementUtils.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/engine/core/EntitlementUtils.java
@@ -89,11 +89,11 @@ public class EntitlementUtils {
      * @param context call context
      */
     public void setBlockingStateAndPostBlockingTransitionEvent(final BlockingState state, final InternalCallContext context) {
-        final BlockingAggregator previousState = getBlockingStateFor(state.getBlockedId(), state.getType(), context);
+        final BlockingAggregator previousState = getBlockingStateFor(state.getBlockedId(), state.getType(), clock.getUTCNow(), context);
 
         dao.setBlockingState(state, clock, context);
 
-        final BlockingAggregator currentState = getBlockingStateFor(state.getBlockedId(), state.getType(), context);
+        final BlockingAggregator currentState = getBlockingStateFor(state.getBlockedId(), state.getType(), state.getEffectiveDate(), context);
         if (previousState != null && currentState != null) {
             postBlockingTransitionEvent(state.getId(), state.getEffectiveDate(), state.getBlockedId(), state.getType(), state.getService(), previousState, currentState, context);
         }
@@ -118,9 +118,9 @@ public class EntitlementUtils {
     }
 
 
-    private BlockingAggregator getBlockingStateFor(final UUID blockableId, final BlockingStateType type, final InternalCallContext context) {
+    private BlockingAggregator getBlockingStateFor(final UUID blockableId, final BlockingStateType type, final DateTime effectiveDate, final InternalCallContext context) {
         try {
-            return blockingChecker.getBlockedStatus(blockableId, type, context);
+            return blockingChecker.getBlockedStatus(blockableId, type, effectiveDate, context);
         } catch (BlockingApiException e) {
             log.warn("Failed to retrieve blocking state for {} {}", blockableId, type);
             return null;
diff --git a/entitlement/src/test/java/org/killbill/billing/entitlement/block/MockBlockingChecker.java b/entitlement/src/test/java/org/killbill/billing/entitlement/block/MockBlockingChecker.java
index 0213916..9453136 100644
--- a/entitlement/src/test/java/org/killbill/billing/entitlement/block/MockBlockingChecker.java
+++ b/entitlement/src/test/java/org/killbill/billing/entitlement/block/MockBlockingChecker.java
@@ -19,6 +19,7 @@ package org.killbill.billing.entitlement.block;
 import java.util.List;
 import java.util.UUID;
 
+import org.joda.time.DateTime;
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.entitlement.api.Blockable;
 import org.killbill.billing.entitlement.api.BlockingApiException;
@@ -33,19 +34,19 @@ public class MockBlockingChecker implements BlockingChecker {
     }
 
     @Override
-    public BlockingAggregator getBlockedStatus(final UUID blockableId, final BlockingStateType type, final InternalTenantContext context) throws BlockingApiException {
+    public BlockingAggregator getBlockedStatus(final UUID blockableId, final BlockingStateType type, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
         return null;
     }
 
     @Override
-    public void checkBlockedChange(final Blockable blockable, final InternalTenantContext context) throws BlockingApiException {
+    public void checkBlockedChange(final Blockable blockable, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
     }
 
     @Override
-    public void checkBlockedEntitlement(final Blockable blockable, final InternalTenantContext context) throws BlockingApiException {
+    public void checkBlockedEntitlement(final Blockable blockable, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
     }
 
     @Override
-    public void checkBlockedBilling(final Blockable blockable, final InternalTenantContext context) throws BlockingApiException {
+    public void checkBlockedBilling(final Blockable blockable, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
     }
 }
diff --git a/entitlement/src/test/java/org/killbill/billing/entitlement/block/TestBlockingChecker.java b/entitlement/src/test/java/org/killbill/billing/entitlement/block/TestBlockingChecker.java
index 01a857c..03fabcb 100644
--- a/entitlement/src/test/java/org/killbill/billing/entitlement/block/TestBlockingChecker.java
+++ b/entitlement/src/test/java/org/killbill/billing/entitlement/block/TestBlockingChecker.java
@@ -89,17 +89,17 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
         setStateAccount(false, false, false);
         setStateBundle(false, false, false);
         setStateSubscription(false, false, false);
-        blockingChecker.checkBlockedChange(subscription, internalCallContext);
-        blockingChecker.checkBlockedEntitlement(subscription, internalCallContext);
-        blockingChecker.checkBlockedBilling(subscription, internalCallContext);
+        blockingChecker.checkBlockedChange(subscription, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedEntitlement(subscription, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedBilling(subscription, clock.getUTCNow(), internalCallContext);
 
         //BLOCKED SUBSCRIPTION
         clock.addDays(1);
         setStateSubscription(true, false, false);
-        blockingChecker.checkBlockedEntitlement(subscription, internalCallContext);
-        blockingChecker.checkBlockedBilling(subscription, internalCallContext);
+        blockingChecker.checkBlockedEntitlement(subscription, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedBilling(subscription, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedChange(subscription, internalCallContext);
+            blockingChecker.checkBlockedChange(subscription, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -107,10 +107,10 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
 
         clock.addDays(1);
         setStateSubscription(false, true, false);
-        blockingChecker.checkBlockedChange(subscription, internalCallContext);
-        blockingChecker.checkBlockedBilling(subscription, internalCallContext);
+        blockingChecker.checkBlockedChange(subscription, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedBilling(subscription, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedEntitlement(subscription, internalCallContext);
+            blockingChecker.checkBlockedEntitlement(subscription, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -118,10 +118,10 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
 
         clock.addDays(1);
         setStateSubscription(false, false, true);
-        blockingChecker.checkBlockedChange(subscription, internalCallContext);
-        blockingChecker.checkBlockedEntitlement(subscription, internalCallContext);
+        blockingChecker.checkBlockedChange(subscription, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedEntitlement(subscription, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedBilling(subscription, internalCallContext);
+            blockingChecker.checkBlockedBilling(subscription, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -131,10 +131,10 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
         clock.addDays(1);
         setStateSubscription(false, false, false);
         setStateBundle(true, false, false);
-        blockingChecker.checkBlockedEntitlement(subscription, internalCallContext);
-        blockingChecker.checkBlockedBilling(subscription, internalCallContext);
+        blockingChecker.checkBlockedEntitlement(subscription, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedBilling(subscription, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedChange(subscription, internalCallContext);
+            blockingChecker.checkBlockedChange(subscription, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -142,10 +142,10 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
 
         clock.addDays(1);
         setStateBundle(false, true, false);
-        blockingChecker.checkBlockedChange(subscription, internalCallContext);
-        blockingChecker.checkBlockedBilling(subscription, internalCallContext);
+        blockingChecker.checkBlockedChange(subscription, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedBilling(subscription, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedEntitlement(subscription, internalCallContext);
+            blockingChecker.checkBlockedEntitlement(subscription, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -153,10 +153,10 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
 
         clock.addDays(1);
         setStateBundle(false, false, true);
-        blockingChecker.checkBlockedChange(subscription, internalCallContext);
-        blockingChecker.checkBlockedEntitlement(subscription, internalCallContext);
+        blockingChecker.checkBlockedChange(subscription, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedEntitlement(subscription, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedBilling(subscription, internalCallContext);
+            blockingChecker.checkBlockedBilling(subscription, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -167,10 +167,10 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
         setStateSubscription(false, false, false);
         setStateBundle(false, false, false);
         setStateAccount(true, false, false);
-        blockingChecker.checkBlockedEntitlement(subscription, internalCallContext);
-        blockingChecker.checkBlockedBilling(subscription, internalCallContext);
+        blockingChecker.checkBlockedEntitlement(subscription, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedBilling(subscription, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedChange(subscription, internalCallContext);
+            blockingChecker.checkBlockedChange(subscription, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -178,10 +178,10 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
 
         clock.addDays(1);
         setStateAccount(false, true, false);
-        blockingChecker.checkBlockedChange(subscription, internalCallContext);
-        blockingChecker.checkBlockedBilling(subscription, internalCallContext);
+        blockingChecker.checkBlockedChange(subscription, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedBilling(subscription, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedEntitlement(subscription, internalCallContext);
+            blockingChecker.checkBlockedEntitlement(subscription, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -189,10 +189,10 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
 
         clock.addDays(1);
         setStateAccount(false, false, true);
-        blockingChecker.checkBlockedChange(subscription, internalCallContext);
-        blockingChecker.checkBlockedEntitlement(subscription, internalCallContext);
+        blockingChecker.checkBlockedChange(subscription, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedEntitlement(subscription, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedBilling(subscription, internalCallContext);
+            blockingChecker.checkBlockedBilling(subscription, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -204,18 +204,18 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
         setStateAccount(false, false, false);
         setStateBundle(false, false, false);
         setStateSubscription(false, false, false);
-        blockingChecker.checkBlockedChange(bundle, internalCallContext);
-        blockingChecker.checkBlockedEntitlement(bundle, internalCallContext);
-        blockingChecker.checkBlockedBilling(bundle, internalCallContext);
+        blockingChecker.checkBlockedChange(bundle, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedEntitlement(bundle, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedBilling(bundle, clock.getUTCNow(), internalCallContext);
 
         //BLOCKED BUNDLE
         clock.addDays(1);
         setStateSubscription(false, false, false);
         setStateBundle(true, false, false);
-        blockingChecker.checkBlockedEntitlement(bundle, internalCallContext);
-        blockingChecker.checkBlockedBilling(bundle, internalCallContext);
+        blockingChecker.checkBlockedEntitlement(bundle, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedBilling(bundle, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedChange(bundle, internalCallContext);
+            blockingChecker.checkBlockedChange(bundle, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -223,10 +223,10 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
 
         clock.addDays(1);
         setStateBundle(false, true, false);
-        blockingChecker.checkBlockedChange(bundle, internalCallContext);
-        blockingChecker.checkBlockedBilling(bundle, internalCallContext);
+        blockingChecker.checkBlockedChange(bundle, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedBilling(bundle, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedEntitlement(bundle, internalCallContext);
+            blockingChecker.checkBlockedEntitlement(bundle, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -234,10 +234,10 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
 
         clock.addDays(1);
         setStateBundle(false, false, true);
-        blockingChecker.checkBlockedChange(bundle, internalCallContext);
-        blockingChecker.checkBlockedEntitlement(bundle, internalCallContext);
+        blockingChecker.checkBlockedChange(bundle, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedEntitlement(bundle, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedBilling(bundle, internalCallContext);
+            blockingChecker.checkBlockedBilling(bundle, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -248,10 +248,10 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
         setStateSubscription(false, false, false);
         setStateBundle(false, false, false);
         setStateAccount(true, false, false);
-        blockingChecker.checkBlockedEntitlement(bundle, internalCallContext);
-        blockingChecker.checkBlockedBilling(bundle, internalCallContext);
+        blockingChecker.checkBlockedEntitlement(bundle, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedBilling(bundle, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedChange(bundle, internalCallContext);
+            blockingChecker.checkBlockedChange(bundle, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -259,10 +259,10 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
 
         clock.addDays(1);
         setStateAccount(false, true, false);
-        blockingChecker.checkBlockedChange(bundle, internalCallContext);
-        blockingChecker.checkBlockedBilling(bundle, internalCallContext);
+        blockingChecker.checkBlockedChange(bundle, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedBilling(bundle, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedEntitlement(bundle, internalCallContext);
+            blockingChecker.checkBlockedEntitlement(bundle, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -270,10 +270,10 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
 
         clock.addDays(1);
         setStateAccount(false, false, true);
-        blockingChecker.checkBlockedChange(bundle, internalCallContext);
-        blockingChecker.checkBlockedEntitlement(bundle, internalCallContext);
+        blockingChecker.checkBlockedChange(bundle, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedEntitlement(bundle, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedBilling(bundle, internalCallContext);
+            blockingChecker.checkBlockedBilling(bundle, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -286,19 +286,19 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
         setStateAccount(false, false, false);
         setStateBundle(false, false, false);
         setStateSubscription(false, false, false);
-        blockingChecker.checkBlockedChange(account, internalCallContext);
-        blockingChecker.checkBlockedEntitlement(account, internalCallContext);
-        blockingChecker.checkBlockedBilling(account, internalCallContext);
+        blockingChecker.checkBlockedChange(account, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedEntitlement(account, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedBilling(account, clock.getUTCNow(), internalCallContext);
 
         //BLOCKED ACCOUNT
         clock.addDays(1);
         setStateSubscription(false, false, false);
         setStateBundle(false, false, false);
         setStateAccount(true, false, false);
-        blockingChecker.checkBlockedEntitlement(account, internalCallContext);
-        blockingChecker.checkBlockedBilling(account, internalCallContext);
+        blockingChecker.checkBlockedEntitlement(account, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedBilling(account, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedChange(account, internalCallContext);
+            blockingChecker.checkBlockedChange(account, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -306,10 +306,10 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
 
         clock.addDays(1);
         setStateAccount(false, true, false);
-        blockingChecker.checkBlockedChange(account, internalCallContext);
-        blockingChecker.checkBlockedBilling(account, internalCallContext);
+        blockingChecker.checkBlockedChange(account, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedBilling(account, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedEntitlement(account, internalCallContext);
+            blockingChecker.checkBlockedEntitlement(account, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
@@ -317,10 +317,10 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
 
         clock.addDays(1);
         setStateAccount(false, false, true);
-        blockingChecker.checkBlockedChange(account, internalCallContext);
-        blockingChecker.checkBlockedEntitlement(account, internalCallContext);
+        blockingChecker.checkBlockedChange(account, clock.getUTCNow(), internalCallContext);
+        blockingChecker.checkBlockedEntitlement(account, clock.getUTCNow(), internalCallContext);
         try {
-            blockingChecker.checkBlockedBilling(account, internalCallContext);
+            blockingChecker.checkBlockedBilling(account, clock.getUTCNow(), internalCallContext);
             Assert.fail("The call should have been blocked!");
         } catch (BlockingApiException e) {
             //Expected behavior
diff --git a/entitlement/src/test/java/org/killbill/billing/entitlement/dao/MockBlockingStateDao.java b/entitlement/src/test/java/org/killbill/billing/entitlement/dao/MockBlockingStateDao.java
index 475f626..e36f469 100644
--- a/entitlement/src/test/java/org/killbill/billing/entitlement/dao/MockBlockingStateDao.java
+++ b/entitlement/src/test/java/org/killbill/billing/entitlement/dao/MockBlockingStateDao.java
@@ -24,6 +24,7 @@ import java.util.UUID;
 
 import javax.annotation.Nullable;
 
+import org.joda.time.DateTime;
 import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.clock.Clock;
@@ -60,7 +61,7 @@ public class MockBlockingStateDao extends MockEntityDaoBase<BlockingStateModelDa
     }
 
     @Override
-    public List<BlockingState> getBlockingState(final UUID blockableId, final BlockingStateType blockingStateType, final InternalTenantContext context) {
+    public List<BlockingState> getBlockingState(final UUID blockableId, final BlockingStateType blockingStateType, final DateTime upToDate, final InternalTenantContext context) {
         final List<BlockingState> blockingStatesForId = blockingStates.get(blockableId);
         if (blockingStatesForId == null) {
             return new ArrayList<BlockingState>();