killbill-aplcache

Reafctoring for blocking state DAO to now accept a service name

8/11/2013 8:18:22 PM

Changes

Details

diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
index a715188..41bea4a 100644
--- a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
@@ -235,6 +235,12 @@ public class DefaultAccount extends EntityBase implements Account {
         return new DefaultMutableAccountData(this);
     }
 
+    @Override
+    public BlockingState getBlockingState() {
+        // STEPH_ENT How to return blocking state??????
+        return null;
+    }
+
     /**
      * @param currentAccount existing account data
      * @return merged account data
@@ -414,9 +420,4 @@ public class DefaultAccount extends EntityBase implements Account {
         return result;
     }
 
-    @Override
-    public BlockingState getBlockingState() {
-        // STEPH_ENT How to return blocking state??????
-        return null;
-    }
 }
diff --git a/api/src/main/java/com/ning/billing/entitlement/EntitlementService.java b/api/src/main/java/com/ning/billing/entitlement/EntitlementService.java
new file mode 100644
index 0000000..14a09b6
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/entitlement/EntitlementService.java
@@ -0,0 +1,10 @@
+package com.ning.billing.entitlement;
+
+import com.ning.billing.lifecycle.KillbillService;
+
+public interface EntitlementService extends KillbillService {
+
+    public static final String ENTITLEMENT_SERVICE_NAME = "entitlement-service";
+
+    public String getName();
+}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueBase.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueBase.java
index 4e6d124..f310386 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueBase.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueBase.java
@@ -27,6 +27,7 @@ import com.ning.billing.account.api.Account;
 import com.ning.billing.beatrix.integration.BeatrixIntegrationModule;
 import com.ning.billing.beatrix.integration.TestIntegrationBase;
 import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.overdue.OverdueService;
 import com.ning.billing.subscription.api.user.SubscriptionBaseBundle;
 import com.ning.billing.overdue.config.OverdueConfig;
 import com.ning.billing.payment.api.PaymentMethodPlugin;
@@ -79,11 +80,11 @@ public abstract class TestOverdueBase extends TestIntegrationBase {
             await().atMost(10, SECONDS).until(new Callable<Boolean>() {
                 @Override
                 public Boolean call() throws Exception {
-                    return expected.equals(blockingApi.getBlockingStateFor(bundle, internalCallContext).getStateName());
+                    return expected.equals(blockingApi.getBlockingStateForService(bundle, OverdueService.OVERDUE_SERVICE_NAME, internalCallContext).getStateName());
                 }
             });
         } catch (Exception e) {
-            Assert.assertEquals(blockingApi.getBlockingStateFor(bundle, internalCallContext).getStateName(), expected, "Got exception: " + e.toString());
+            Assert.assertEquals(blockingApi.getBlockingStateForService(bundle, OverdueService.OVERDUE_SERVICE_NAME, internalCallContext).getStateName(), expected, "Got exception: " + e.toString());
         }
     }
 }
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 42c4027..289fc5b 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
@@ -128,6 +128,9 @@ 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.
     }
 
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 dce7088..855f8e1 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
@@ -33,17 +33,20 @@ import com.ning.billing.catalog.api.BillingActionPolicy;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.clock.Clock;
+import com.ning.billing.entitlement.EntitlementService;
 import com.ning.billing.entitlement.block.BlockingChecker;
+import com.ning.billing.entitlement.dao.BlockingStateDao;
 import com.ning.billing.subscription.api.SubscriptionBase;
+import com.ning.billing.subscription.api.user.SubscriptionBaseApiException;
 import com.ning.billing.subscription.api.user.SubscriptionBaseBundle;
 import com.ning.billing.subscription.api.user.SubscriptionState;
-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.InternalTenantContext;
 import com.ning.billing.util.callcontext.TenantContext;
 import com.ning.billing.util.svcapi.account.AccountInternalApi;
+import com.ning.billing.util.svcapi.junction.DefaultBlockingState;
 import com.ning.billing.util.svcapi.subscription.SubscriptionBaseInternalApi;
 import com.ning.billing.util.timezone.DateAndTimeZoneContext;
 
@@ -53,19 +56,25 @@ import com.google.common.collect.ImmutableList;
 
 public class DefaultEntitlementApi implements EntitlementApi {
 
+    public final String ENT_STATE_BLOCKED = "ENT_BLOCKED";
+    public final String ENT_STATE_CLEAR = "ENT_CLEAR";
+
     private final SubscriptionBaseInternalApi subscriptionInternalApi;
     private final AccountInternalApi accountApi;
     private final Clock clock;
     private final InternalCallContextFactory internalCallContextFactory;
     private final BlockingChecker checker;
+    private final BlockingStateDao blockingStateDao;
+
 
     @Inject
-    public DefaultEntitlementApi(final InternalCallContextFactory internalCallContextFactory, final SubscriptionBaseInternalApi subscriptionInternalApi, final AccountInternalApi accountApi, final Clock clock, final BlockingChecker checker) {
+    public DefaultEntitlementApi(final InternalCallContextFactory internalCallContextFactory, final SubscriptionBaseInternalApi subscriptionInternalApi, final AccountInternalApi accountApi, final BlockingStateDao blockingStateDao, final Clock clock, final BlockingChecker checker) {
         this.internalCallContextFactory = internalCallContextFactory;
         this.subscriptionInternalApi = subscriptionInternalApi;
         this.accountApi = accountApi;
         this.clock = clock;
         this.checker = checker;
+        this.blockingStateDao = blockingStateDao;
     }
 
 
@@ -93,26 +102,19 @@ public class DefaultEntitlementApi implements EntitlementApi {
             }
 
             final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(bundle.getAccountId(), callContext);
+            checker.checkBlockedChange(baseSubscription, contextWithValidAccountRecordId);
 
             final DateTime requestedDate = fromNowAndReferenceTime(baseSubscription.getStartDate(), contextWithValidAccountRecordId);
             final SubscriptionBase subscription = subscriptionInternalApi.createSubscription(baseSubscription.getBundleId(), planPhaseSpecifier, requestedDate, context);
             return new DefaultEntitlement(accountApi, subscription, bundle.getAccountId(), bundle.getExternalKey(), internalCallContextFactory, clock, checker);
         } catch (SubscriptionBaseApiException e) {
             throw new EntitlementApiException(e);
+        } catch (BlockingApiException e) {
+            throw new EntitlementApiException(e);
         }
     }
 
     @Override
-    public void block(final UUID bundleId, final String serviceName, final LocalDate effectiveDate, final CallContext context) throws EntitlementApiException {
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public void unblock(final UUID bundleId, final String serviceName, final LocalDate effectiveDate, final CallContext context) throws EntitlementApiException {
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
     public Entitlement getEntitlementForId(final UUID uuid, final TenantContext tenantContext) throws EntitlementApiException {
         final InternalTenantContext context = internalCallContextFactory.createInternalTenantContext(tenantContext);
         try {
@@ -125,14 +127,13 @@ public class DefaultEntitlementApi implements EntitlementApi {
     }
 
     @Override
-    public List<Entitlement> getAllEntitlementsForBundle(final UUID bundleId, final TenantContext tenantContext) /* throws EntitlementApiException */ {
+    public List<Entitlement> getAllEntitlementsForBundle(final UUID bundleId, final TenantContext tenantContext) throws EntitlementApiException {
         final InternalTenantContext context = internalCallContextFactory.createInternalTenantContext(tenantContext);
         try {
             final SubscriptionBaseBundle bundle = subscriptionInternalApi.getBundleFromId(bundleId, context);
             return getAllEntitlementsForBundleId(bundleId, bundle.getAccountId(), bundle.getExternalKey(), context);
         } catch (SubscriptionBaseApiException e) {
-            //throw new EntitlementApiException(e);
-            return ImmutableList.<Entitlement>of();
+            throw new EntitlementApiException(e);
         }
     }
 
@@ -160,7 +161,7 @@ public class DefaultEntitlementApi implements EntitlementApi {
         return result;
     }
 
-    private List<Entitlement> getAllEntitlementsForBundleId(final UUID bundleId, final UUID accountId, final String externalKey, final InternalTenantContext context)  {
+    private List<Entitlement> getAllEntitlementsForBundleId(final UUID bundleId, final UUID accountId, final String externalKey, final InternalTenantContext context) {
         final List<SubscriptionBase> subscriptions = subscriptionInternalApi.getSubscriptionsForBundle(bundleId, context);
         return ImmutableList.<Entitlement>copyOf(Collections2.transform(subscriptions, new Function<SubscriptionBase, Entitlement>() {
             @Nullable
@@ -171,16 +172,36 @@ public class DefaultEntitlementApi implements EntitlementApi {
         }));
     }
 
+    @Override
+    public void block(final UUID bundleId, final String serviceName, final LocalDate effectiveDate, final CallContext context) throws EntitlementApiException {
+        final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContext(context);
+        final BlockingState currentState =  blockingStateDao.getBlockingStateForService(bundleId, EntitlementService.ENTITLEMENT_SERVICE_NAME, internalContext);
+        if (currentState != null && currentState.getStateName().equals(ENT_STATE_BLOCKED)) {
+            throw new EntitlementApiException(ErrorCode.ENT_ALREADY_BLOCKED, bundleId);
+        }
+        blockingStateDao.setBlockingState(new DefaultBlockingState(bundleId, BlockingStateType.BUNDLE, ENT_STATE_BLOCKED, EntitlementService.ENTITLEMENT_SERVICE_NAME, true, true, true), clock, internalContext);
+    }
+
+    @Override
+    public void unblock(final UUID bundleId, final String serviceName, final LocalDate effectiveDate, final CallContext context) throws EntitlementApiException {
+        final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContext(context);
+        final BlockingState currentState =  blockingStateDao.getBlockingStateForService(bundleId, EntitlementService.ENTITLEMENT_SERVICE_NAME, internalContext);
+        if (currentState == null || currentState.getStateName().equals(ENT_STATE_CLEAR)) {
+            // Nothing to do.
+            return;
+        }
+        blockingStateDao.setBlockingState(new DefaultBlockingState(bundleId, BlockingStateType.BUNDLE, ENT_STATE_CLEAR, EntitlementService.ENTITLEMENT_SERVICE_NAME, false, false, false), clock, internalContext);
+    }
 
 
     @Override
     public UUID transferEntitlements(final UUID sourceAccountId, final UUID destAccountId, final String externalKey, final LocalDate effectiveDate, final CallContext context) throws EntitlementApiException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+        return null;
     }
 
     @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;  //To change body of implemented methods use File | Settings | File Templates.
+        return null;
     }
 
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/svcs/DefaultInternalBlockingApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/svcs/DefaultInternalBlockingApi.java
index cc78b1c..89e27c7 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/svcs/DefaultInternalBlockingApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/svcs/DefaultInternalBlockingApi.java
@@ -17,7 +17,10 @@
 package com.ning.billing.entitlement.api.svcs;
 
 import com.google.inject.Inject;
+
+import com.ning.billing.account.api.Account;
 import com.ning.billing.clock.Clock;
+import com.ning.billing.entitlement.api.BlockingStateType;
 import com.ning.billing.entitlement.dao.BlockingStateDao;
 import com.ning.billing.entitlement.api.Blockable;
 import com.ning.billing.entitlement.api.BlockingState;
@@ -41,31 +44,40 @@ public class DefaultInternalBlockingApi implements BlockingInternalApi {
     }
 
     @Override
-    public BlockingState getBlockingStateFor(final Blockable overdueable, final InternalTenantContext context) {
-        BlockingState state = dao.getBlockingStateFor(overdueable.getId(), context);
+    public BlockingState getBlockingStateForService(final Blockable overdueable, final String serviceName, final InternalTenantContext context) {
+        BlockingState state = dao.getBlockingStateForService(overdueable.getId(), serviceName, context);
         if (state == null) {
-            state = DefaultBlockingState.getClearState();
+            state = DefaultBlockingState.getClearState(getBlockingStateType(overdueable));
         }
         return state;
     }
 
     @Override
-    public BlockingState getBlockingStateFor(final UUID overdueableId, final InternalTenantContext context) {
-        return dao.getBlockingStateFor(overdueableId, context);
+    public BlockingState getBlockingStateForService(final UUID overdueableId, final String serviceName, final InternalTenantContext context) {
+        return dao.getBlockingStateForService(overdueableId, serviceName, context);
     }
 
     @Override
-    public List<BlockingState> getBlockingHistory(final Blockable overdueable, final InternalTenantContext context) {
-        return dao.getBlockingHistoryFor(overdueable.getId(), context);
+    public List<BlockingState> getBlockingHistoryForService(final Blockable overdueable, final String serviceName, final InternalTenantContext context) {
+        return dao.getBlockingHistoryForService(overdueable.getId(), serviceName, context);
     }
 
     @Override
-    public List<BlockingState> getBlockingHistory(final UUID overdueableId, final InternalTenantContext context) {
-        return dao.getBlockingHistoryFor(overdueableId, context);
+    public List<BlockingState> getBlockingHistoryForService(final UUID overdueableId, final String serviceName, final InternalTenantContext context) {
+        return dao.getBlockingHistoryForService(overdueableId, serviceName, context);
     }
 
     @Override
-    public <T extends Blockable> void setBlockingState(final BlockingState state, final InternalCallContext context) {
+    public void setBlockingState(final BlockingState state, final InternalCallContext context) {
         dao.setBlockingState(state, clock, context);
     }
+
+    BlockingStateType getBlockingStateType(final Blockable overdueable) {
+        if (overdueable instanceof Account) {
+            return BlockingStateType.ACCOUNT;
+        }
+        // STEPH this is here to ve rify there are no service trying to block on something different than ACCOUNT level
+        // All the other entities
+        throw new RuntimeException("Unexpected blockable type");
+    }
 }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/block/DefaultBlockingChecker.java b/entitlement/src/main/java/com/ning/billing/entitlement/block/DefaultBlockingChecker.java
index 655b5ec..aafe0de 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/block/DefaultBlockingChecker.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/block/DefaultBlockingChecker.java
@@ -16,6 +16,7 @@
 
 package com.ning.billing.entitlement.block;
 
+import java.util.List;
 import java.util.UUID;
 
 import com.ning.billing.ErrorCode;
@@ -74,7 +75,7 @@ public class DefaultBlockingChecker implements BlockingChecker {
 
     private static final Object TYPE_SUBSCRIPTION = "Subscription";
     private static final Object TYPE_BUNDLE = "Bundle";
-    private static final Object TYPE_ACCOUNT = "ACCOUNT";
+    private static final Object TYPE_ACCOUNT = "Account";
 
     private static final Object ACTION_CHANGE = "Change";
     private static final Object ACTION_ENTITLEMENT = "Entitlement";
@@ -139,8 +140,10 @@ public class DefaultBlockingChecker implements BlockingChecker {
     private BlockingAggregator getBlockedStateForId(final UUID blockableId, final InternalTenantContext context) {
         final BlockingAggregator result = new BlockingAggregator();
         if (blockableId != null) {
-            final BlockingState blockableState = dao.getBlockingStateFor(blockableId, context);
-            result.or(blockableState);
+            final List<BlockingState> blockableState = dao.getBlockingState(blockableId, context);
+            for (BlockingState cur : blockableState) {
+                result.or(cur);
+            }
         }
         return result;
     }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateDao.java
index 01265d5..453c915 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateDao.java
@@ -27,9 +27,50 @@ import com.ning.billing.clock.Clock;
 
 public interface BlockingStateDao {
 
-    public BlockingState getBlockingStateFor(UUID blockableId, InternalTenantContext context);
+    /**
+     * Returns the current state for that specific service
+     *
+     * @param blockableId
+     * @param serviceName
+     * @param context
+     * @return
+     */
+    public BlockingState getBlockingStateForService(UUID blockableId, String serviceName, InternalTenantContext context);
 
-    public List<BlockingState> getBlockingHistoryFor(UUID blockableId, InternalTenantContext context);
+    /**
+     * Returns the current state across all the services
+     *
+     * @param blockableId
+     * @param context
+     * @return
+     */
+    public List<BlockingState> getBlockingState(UUID blockableId, InternalTenantContext context);
 
-    <T extends Blockable> void setBlockingState(BlockingState state, Clock clock, InternalCallContext context);
+    /**
+     * Returns the state history  for that specific service
+     *
+     * @param blockableId
+     * @param serviceName
+     * @param context
+     * @return
+     */
+    public List<BlockingState> getBlockingHistoryForService(UUID blockableId, String serviceName, InternalTenantContext context);
+
+    /**
+     * Returns the state history across all the services
+     *
+     * @param blockableId
+     * @param context
+     * @return
+     */
+    public List<BlockingState> getBlockingHistory(UUID blockableId, InternalTenantContext context);
+
+    /**
+     * Sets a new state for a specific service
+     *
+     * @param state
+     * @param clock
+     * @param context
+     */
+    void setBlockingState(BlockingState state, Clock clock, InternalCallContext context);
 }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateModelDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateModelDao.java
index ab9bac0..8db83b7 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateModelDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateModelDao.java
@@ -21,6 +21,7 @@ import java.util.UUID;
 import org.joda.time.DateTime;
 
 import com.ning.billing.entitlement.api.BlockingState;
+import com.ning.billing.entitlement.api.BlockingStateType;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.dao.TableName;
 import com.ning.billing.util.entity.EntityBase;
@@ -30,16 +31,18 @@ import com.ning.billing.util.svcapi.junction.DefaultBlockingState;
 public class BlockingStateModelDao extends EntityBase implements EntityModelDao<BlockingState>{
 
     private final UUID blockableId;
+    private final BlockingStateType type;
     private final String state;
     private final String service;
     private final Boolean blockChange;
     private final Boolean blockEntitlement;
     private final Boolean blockBilling;
 
-    public BlockingStateModelDao(final UUID id, final UUID blockableId, final String state, final String service, final Boolean blockChange, final Boolean blockEntitlement,
+    public BlockingStateModelDao(final UUID id, final UUID blockableId, final BlockingStateType blockingStateType, final String state, final String service, final Boolean blockChange, final Boolean blockEntitlement,
                                  final Boolean blockBilling, final DateTime createDate, final DateTime updateDate) {
         super(id, createDate, updateDate);
         this.blockableId = blockableId;
+        this.type = blockingStateType;
         this.state = state;
         this.service = service;
         this.blockChange = blockChange;
@@ -48,7 +51,7 @@ public class BlockingStateModelDao extends EntityBase implements EntityModelDao<
     }
 
     public BlockingStateModelDao(final BlockingState src, InternalCallContext context) {
-        this(src.getId(), src.getBlockedId(), src.getStateName(), src.getService(), src.isBlockChange(),
+        this(src.getId(), src.getBlockedId(), src.getType(), src.getStateName(), src.getService(), src.isBlockChange(),
              src.isBlockEntitlement(), src.isBlockBilling(), context.getCreatedDate(), context.getUpdatedDate());
     }
 
@@ -76,11 +79,15 @@ public class BlockingStateModelDao extends EntityBase implements EntityModelDao<
         return blockBilling;
     }
 
+    public BlockingStateType getType() {
+        return type;
+    }
+
     public static BlockingState toBlockingState(BlockingStateModelDao src) {
         if (src == null) {
             return null;
         }
-        return new DefaultBlockingState(src.getId(), src.getBlockableId(),src.getState(), src.getService(), src.getBlockChange(), src.getBlockEntitlement(), src.getBlockBilling(),
+        return new DefaultBlockingState(src.getId(), src.getBlockableId(), src.getType(), src.getState(), src.getService(), src.getBlockChange(), src.getBlockEntitlement(), src.getBlockBilling(),
                                  src.getCreatedDate(), src.getUpdatedDate());
     }
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateSqlDao.java
index e929237..a7f6a83 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/dao/BlockingStateSqlDao.java
@@ -30,6 +30,7 @@ import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
 import org.skife.jdbi.v2.tweak.ResultSetMapper;
 
 import com.ning.billing.entitlement.api.BlockingState;
+import com.ning.billing.entitlement.api.BlockingStateType;
 import com.ning.billing.util.callcontext.InternalTenantContext;
 import com.ning.billing.util.dao.MapperBase;
 import com.ning.billing.util.entity.dao.EntitySqlDao;
@@ -41,11 +42,24 @@ import com.ning.billing.util.svcapi.junction.DefaultBlockingState;
 public interface BlockingStateSqlDao extends EntitySqlDao<BlockingStateModelDao, BlockingState> {
 
     @SqlQuery
-    public BlockingStateModelDao getBlockingStateFor(@Bind("blockableId") UUID blockableId, @BindBean final InternalTenantContext context);
+    public abstract BlockingStateModelDao getBlockingStateForService(@Bind("blockableId") UUID blockableId,
+                                                                     @Bind("service") String serviceName,
+                                                                     @BindBean final InternalTenantContext context);
 
     @SqlQuery
-    public abstract List<BlockingStateModelDao> getBlockingHistoryFor(@Bind("blockableId") UUID blockableId,
-                                                                      @BindBean final InternalTenantContext context);
+    public abstract List<BlockingStateModelDao> getBlockingState(@Bind("blockableId") UUID blockableId,
+                                                                 @BindBean final InternalTenantContext context);
+
+
+    @SqlQuery
+    public abstract List<BlockingStateModelDao> getBlockingHistoryForService(@Bind("blockableId") UUID blockableId,
+                                                                             @Bind("service") String serviceName,
+                                                                             @BindBean final InternalTenantContext context);
+
+
+    @SqlQuery
+    public abstract List<BlockingStateModelDao> getBlockingHistory(@Bind("blockableId") UUID blockableId,
+                                                                   @BindBean final InternalTenantContext context);
 
     public class BlockingHistorySqlMapper extends MapperBase implements ResultSetMapper<BlockingStateModelDao> {
 
@@ -61,16 +75,18 @@ public interface BlockingStateSqlDao extends EntitySqlDao<BlockingStateModelDao,
             final boolean blockEntitlement;
             final boolean blockBilling;
             final DateTime createdDate;
+            final BlockingStateType type;
 
             id = UUID.fromString(r.getString("id"));
             blockableId = UUID.fromString(r.getString("blockable_id"));
             stateName = r.getString("state") == null ? DefaultBlockingState.CLEAR_STATE_NAME : r.getString("state");
             service = r.getString("service");
+            type = BlockingStateType.valueOf(r.getString("type"));
             blockChange = r.getBoolean("block_change");
             blockEntitlement = r.getBoolean("block_entitlement");
             blockBilling = r.getBoolean("block_billing");
             createdDate = getDateTime(r, "created_date");
-            return new BlockingStateModelDao(id, blockableId, stateName, service, blockChange, blockEntitlement, blockBilling, createdDate, createdDate);
+            return new BlockingStateModelDao(id, blockableId, type, stateName, service, blockChange, blockEntitlement, blockBilling, createdDate, createdDate);
         }
     }
 }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/dao/DefaultBlockingStateDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/dao/DefaultBlockingStateDao.java
index 6bc741a..8c2ef5e 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/dao/DefaultBlockingStateDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/dao/DefaultBlockingStateDao.java
@@ -50,11 +50,11 @@ public class DefaultBlockingStateDao implements BlockingStateDao {
     }
 
     @Override
-    public BlockingState getBlockingStateFor(final UUID blockableId, final InternalTenantContext context) {
+    public BlockingState getBlockingStateForService(final UUID blockableId, final String serviceName, final InternalTenantContext context) {
         return transactionalSqlDao.execute(  new EntitySqlDaoTransactionWrapper<BlockingState>() {
             @Override
             public BlockingState inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
-                final BlockingStateModelDao model = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingStateFor(blockableId, context);
+                final BlockingStateModelDao model = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingStateForService(blockableId, serviceName, context);
                 return BlockingStateModelDao.toBlockingState(model);
 
             }
@@ -62,11 +62,43 @@ public class DefaultBlockingStateDao implements BlockingStateDao {
     }
 
     @Override
-    public List<BlockingState> getBlockingHistoryFor(final UUID blockableId, final InternalTenantContext context) {
+    public List<BlockingState> getBlockingState(final UUID blockableId, final InternalTenantContext context) {
+        return transactionalSqlDao.execute(  new EntitySqlDaoTransactionWrapper<List<BlockingState>>() {
+            @Override
+            public List<BlockingState> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
+                final  List<BlockingStateModelDao> models = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingState(blockableId, context);
+                return new ArrayList<BlockingState>(Collections2.transform(models, new Function<BlockingStateModelDao, BlockingState>() {
+                    @Override
+                    public BlockingState apply(@Nullable final BlockingStateModelDao src) {
+                        return BlockingStateModelDao.toBlockingState(src);
+                    }
+                }));
+            }
+        });
+    }
+
+    @Override
+    public List<BlockingState> getBlockingHistoryForService(final UUID blockableId, final String serviceName, final InternalTenantContext context) {
+        return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<BlockingState>>() {
+            @Override
+            public List<BlockingState> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
+                final List<BlockingStateModelDao> models = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingHistoryForService(blockableId, serviceName, context);
+                return new ArrayList<BlockingState>(Collections2.transform(models, new Function<BlockingStateModelDao, BlockingState>() {
+                    @Override
+                    public BlockingState apply(@Nullable final BlockingStateModelDao src) {
+                        return BlockingStateModelDao.toBlockingState(src);
+                    }
+                }));
+            }
+        });
+    }
+
+    @Override
+    public List<BlockingState> getBlockingHistory(final UUID blockableId, final InternalTenantContext context) {
         return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<BlockingState>>() {
             @Override
             public List<BlockingState> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
-                final List<BlockingStateModelDao> models = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingHistoryFor(blockableId, context);
+                final List<BlockingStateModelDao> models = entitySqlDaoWrapperFactory.become(BlockingStateSqlDao.class).getBlockingHistory(blockableId, context);
                 return new ArrayList<BlockingState>(Collections2.transform(models, new Function<BlockingStateModelDao, BlockingState>() {
                     @Override
                     public BlockingState apply(@Nullable final BlockingStateModelDao src) {
@@ -78,7 +110,7 @@ public class DefaultBlockingStateDao implements BlockingStateDao {
     }
 
     @Override
-    public <T extends Blockable> void setBlockingState(final BlockingState state, final Clock clock, final InternalCallContext context) {
+    public void setBlockingState(final BlockingState state, final Clock clock, final InternalCallContext context) {
         transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
             @Override
             public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/DefaultEntitlementService.java b/entitlement/src/main/java/com/ning/billing/entitlement/DefaultEntitlementService.java
new file mode 100644
index 0000000..3ae34f1
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/DefaultEntitlementService.java
@@ -0,0 +1,9 @@
+package com.ning.billing.entitlement;
+
+public class DefaultEntitlementService implements EntitlementService {
+
+    @Override
+    public String getName() {
+        return EntitlementService.ENTITLEMENT_SERVICE_NAME;
+    }
+}
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/dao/BlockingStateSqlDao.sql.stg b/entitlement/src/main/resources/com/ning/billing/entitlement/dao/BlockingStateSqlDao.sql.stg
index 66a246f..79b5491 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/dao/BlockingStateSqlDao.sql.stg
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/dao/BlockingStateSqlDao.sql.stg
@@ -26,12 +26,14 @@ tableValues() ::= <<
 , :createdDate
 >>
 
-getBlockingStateFor() ::= <<
+
+getBlockingStateForService() ::= <<
 select
 <allTableFields()>
 from
 <tableName()>
 where blockable_id = :blockableId
+and service = :service
 <AND_CHECK_TENANT()>
 -- We want the current state, hence the order desc and limit 1
 order by record_id desc
@@ -39,14 +41,36 @@ limit 1
 ;
 >>
 
-getBlockingHistoryFor() ::= <<
+getBlockingState() ::= <<
+ select
+ <allTableFields()>
+ from
+ <tableName()>
+ where blockable_id = :blockableId
+ <AND_CHECK_TENANT()>
+ order by record_id asc
+ ;
+ >>
+
+getBlockingHistoryForService() ::= <<
+select
+<allTableFields()>
+from
+<tableName()>
+where blockable_id = :blockableId
+and service = :service
+<AND_CHECK_TENANT()>
+order by record_id asc
+;
+>>
+
+getBlockingHistory() ::= <<
 select
 <allTableFields()>
 from
 <tableName()>
 where blockable_id = :blockableId
 <AND_CHECK_TENANT()>
--- We want the current state, hence the order desc and limit 1
 order by record_id asc
 ;
 >>
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
new file mode 100644
index 0000000..d3809bd
--- /dev/null
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlementApi.java
@@ -0,0 +1,4 @@
+package com.ning.billing.entitlement.api;
+
+public class TestDefaultEntitlementApi {
+}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/block/TestBlockingApi.java b/entitlement/src/test/java/com/ning/billing/entitlement/block/TestBlockingApi.java
index 6e21392..44b506e 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/block/TestBlockingApi.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/block/TestBlockingApi.java
@@ -26,6 +26,7 @@ import org.testng.annotations.Test;
 
 import com.ning.billing.entitlement.EntitlementTestSuiteWithEmbeddedDB;
 import com.ning.billing.entitlement.api.BlockingState;
+import com.ning.billing.entitlement.api.BlockingStateType;
 import com.ning.billing.subscription.api.user.SubscriptionBaseBundle;
 import com.ning.billing.util.svcapi.junction.DefaultBlockingState;
 
@@ -47,19 +48,21 @@ public class TestBlockingApi extends EntitlementTestSuiteWithEmbeddedDB {
         final boolean blockEntitlement = false;
         final boolean blockBilling = false;
 
-        final BlockingState state1 = new DefaultBlockingState(uuid, overdueStateName, service, blockChange, blockEntitlement, blockBilling);
+        final BlockingState state1 = new DefaultBlockingState(uuid, BlockingStateType.ACCOUNT,overdueStateName, service, blockChange, blockEntitlement, blockBilling);
         blockingInternalApi.setBlockingState(state1, internalCallContext);
         clock.setDeltaFromReality(1000 * 3600 * 24);
 
         final String overdueStateName2 = "NoReallyThisCantGoOn";
-        final BlockingState state2 = new DefaultBlockingState(uuid, overdueStateName2, service, blockChange, blockEntitlement, blockBilling);
+        final BlockingState state2 = new DefaultBlockingState(uuid, BlockingStateType.ACCOUNT, overdueStateName2, service, blockChange, blockEntitlement, blockBilling);
         blockingInternalApi.setBlockingState(state2, internalCallContext);
 
         final SubscriptionBaseBundle bundle = Mockito.mock(SubscriptionBaseBundle.class);
         Mockito.when(bundle.getId()).thenReturn(uuid);
 
-        Assert.assertEquals(blockingInternalApi.getBlockingStateFor(bundle, internalCallContext).getStateName(), overdueStateName2);
-        Assert.assertEquals(blockingInternalApi.getBlockingStateFor(bundle.getId(), internalCallContext).getStateName(), overdueStateName2);
+        Assert.assertEquals(blockingInternalApi.getBlockingStateForService(bundle, service, internalCallContext).getStateName(), overdueStateName2);
+        Assert.assertEquals(blockingInternalApi.getBlockingStateForService(bundle.getId(), service, internalCallContext).getStateName(), overdueStateName2);
+
+
     }
 
     @Test(groups = "slow")
@@ -72,20 +75,20 @@ public class TestBlockingApi extends EntitlementTestSuiteWithEmbeddedDB {
         final boolean blockEntitlement = false;
         final boolean blockBilling = false;
 
-        final BlockingState state1 = new DefaultBlockingState(uuid, overdueStateName, service, blockChange, blockEntitlement, blockBilling);
+        final BlockingState state1 = new DefaultBlockingState(uuid, BlockingStateType.ACCOUNT, overdueStateName, service, blockChange, blockEntitlement, blockBilling);
         blockingInternalApi.setBlockingState(state1, internalCallContext);
 
         clock.setDeltaFromReality(1000 * 3600 * 24);
 
         final String overdueStateName2 = "NoReallyThisCantGoOn";
-        final BlockingState state2 = new DefaultBlockingState(uuid, overdueStateName2, service, blockChange, blockEntitlement, blockBilling);
+        final BlockingState state2 = new DefaultBlockingState(uuid, BlockingStateType.ACCOUNT, overdueStateName2, service, blockChange, blockEntitlement, blockBilling);
         blockingInternalApi.setBlockingState(state2, internalCallContext);
 
         final SubscriptionBaseBundle bundle = Mockito.mock(SubscriptionBaseBundle.class);
         Mockito.when(bundle.getId()).thenReturn(uuid);
 
-        final List<BlockingState> history1 = blockingInternalApi.getBlockingHistory(bundle, internalCallContext);
-        final List<BlockingState> history2 = blockingInternalApi.getBlockingHistory(bundle.getId(), internalCallContext);
+        final List<BlockingState> history1 = blockingInternalApi.getBlockingHistoryForService(bundle, service, internalCallContext);
+        final List<BlockingState> history2 = blockingInternalApi.getBlockingHistoryForService(bundle.getId(), service, internalCallContext);
 
         Assert.assertEquals(history1.size(), 2);
         Assert.assertEquals(history1.get(0).getStateName(), overdueStateName);
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/block/TestBlockingChecker.java b/entitlement/src/test/java/com/ning/billing/entitlement/block/TestBlockingChecker.java
index edf490d..174ed07 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/block/TestBlockingChecker.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/block/TestBlockingChecker.java
@@ -19,6 +19,7 @@ package com.ning.billing.entitlement.block;
 import java.util.UUID;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.entitlement.EntitlementTestSuiteNoDB;
+import com.ning.billing.entitlement.api.BlockingStateType;
 import com.ning.billing.entitlement.dao.MockBlockingStateDao;
 import com.ning.billing.entitlement.api.BlockingApiException;
 import com.ning.billing.entitlement.api.BlockingState;
@@ -66,18 +67,18 @@ public class TestBlockingChecker extends EntitlementTestSuiteNoDB {
     }
 
     private void setStateBundle(final boolean bC, final boolean bE, final boolean bB) {
-        final BlockingState bundleState = new DefaultBlockingState(bundle.getId(), "state", "test-service", bC, bE, bB);
+        final BlockingState bundleState = new DefaultBlockingState(bundle.getId(), BlockingStateType.ACCOUNT,"state", "test-service", bC, bE, bB);
         Mockito.when(bundle.getBlockingState()).thenReturn(bundleState);
         blockingStateDao.setBlockingState(bundleState, clock, internalCallContext);
     }
 
     private void setStateAccount(final boolean bC, final boolean bE, final boolean bB) {
-        final BlockingState accountState = new DefaultBlockingState(account.getId(), "state", "test-service", bC, bE, bB);
+        final BlockingState accountState = new DefaultBlockingState(account.getId(), BlockingStateType.ACCOUNT, "state", "test-service", bC, bE, bB);
         blockingStateDao.setBlockingState(accountState, clock, internalCallContext);
     }
 
     private void setStateSubscription(final boolean bC, final boolean bE, final boolean bB) {
-        final BlockingState subscriptionState = new DefaultBlockingState(subscription.getId(), "state", "test-service", bC, bE, bB);
+        final BlockingState subscriptionState = new DefaultBlockingState(subscription.getId(), BlockingStateType.SUBSCRIPTION, "state", "test-service", bC, bE, bB);
         Mockito.when(subscription.getBlockingState()).thenReturn(subscriptionState);
         blockingStateDao.setBlockingState(subscriptionState, clock, internalCallContext);
     }
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/block/TestDefaultBlockingApi.java b/entitlement/src/test/java/com/ning/billing/entitlement/block/TestDefaultBlockingApi.java
index 9a64fb4..80607f7 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/block/TestDefaultBlockingApi.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/block/TestDefaultBlockingApi.java
@@ -18,6 +18,7 @@ package com.ning.billing.entitlement.block;
 
 import com.ning.billing.entitlement.EntitlementTestSuiteWithEmbeddedDB;
 import com.ning.billing.entitlement.api.BlockingState;
+import com.ning.billing.entitlement.api.BlockingStateType;
 import com.ning.billing.util.svcapi.junction.DefaultBlockingState;
 import org.skife.jdbi.v2.Handle;
 import org.skife.jdbi.v2.tweak.HandleCallback;
@@ -53,11 +54,11 @@ public class TestDefaultBlockingApi extends EntitlementTestSuiteWithEmbeddedDB {
             }
         });
 
-        final BlockingState blockingState = new DefaultBlockingState(UUID.randomUUID(), bundleId, "BLOCKED", "myService", true, true, true, internalCallContext.getCreatedDate(), null);
+        final BlockingState blockingState = new DefaultBlockingState(UUID.randomUUID(), bundleId, BlockingStateType.ACCOUNT, "BLOCKED", "myService", true, true, true, internalCallContext.getCreatedDate(), null);
         blockingInternalApi.setBlockingState(blockingState, internalCallContext);
 
         // Verify the blocking state was applied
-        final BlockingState resultState = blockingInternalApi.getBlockingStateFor(bundleId, internalCallContext);
+        final BlockingState resultState = blockingInternalApi.getBlockingStateForService(bundleId, "myService", internalCallContext);
 
         Assert.assertEquals(resultState.getStateName(), blockingState.getStateName());
         // Verify the account_record_id was populated
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/dao/MockBlockingStateDao.java b/entitlement/src/test/java/com/ning/billing/entitlement/dao/MockBlockingStateDao.java
index 194db1b..317c1e1 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/dao/MockBlockingStateDao.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/dao/MockBlockingStateDao.java
@@ -22,31 +22,68 @@ import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
+import javax.annotation.Nullable;
+
+import com.ning.billing.clock.Clock;
 import com.ning.billing.entitlement.api.Blockable;
 import com.ning.billing.entitlement.api.BlockingState;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalTenantContext;
-import com.ning.billing.clock.Clock;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
 
 public class MockBlockingStateDao implements BlockingStateDao {
 
     private final Map<UUID, List<BlockingState>> blockingStates = new HashMap<UUID, List<BlockingState>>();
 
     @Override
-    public BlockingState getBlockingStateFor(final UUID blockableId, final InternalTenantContext context) {
-        final List<BlockingState> blockingStates = getBlockingHistoryFor(blockableId, context);
-        return blockingStates == null ? null : blockingStates.get(blockingStates.size() - 1);
+    public BlockingState getBlockingStateForService(final UUID blockableId, final String serviceName, final InternalTenantContext context) {
+        final List<BlockingState> states = getBlockingHistory(blockableId, context);
+        if (states == null) {
+            return null;
+        }
+        final ImmutableList<BlockingState> filtered = ImmutableList.<BlockingState>copyOf(Collections2.filter(states, new Predicate<BlockingState>() {
+            @Override
+            public boolean apply(@Nullable final BlockingState input) {
+                return input.getService().equals(serviceName);
+            }
+        }));
+        return filtered.size() == 0 ? null : filtered.get(filtered.size() - 1);
+    }
+
+    @Override
+    public List<BlockingState> getBlockingState(final UUID blockableId, final InternalTenantContext context) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public List<BlockingState> getBlockingHistoryForService(final UUID overdueableId, final String serviceName, final InternalTenantContext context) {
+        final List<BlockingState> states = blockingStates.get(overdueableId);
+        if (states == null) {
+            return null;
+        }
+        final ImmutableList<BlockingState> filtered = ImmutableList.<BlockingState>copyOf(Collections2.filter(states, new Predicate<BlockingState>() {
+            @Override
+            public boolean apply(@Nullable final BlockingState input) {
+                return input.getService().equals(serviceName);
+            }
+        }));
+
+        // Note! The returned list cannot be immutable!
+        return states == null ? new ArrayList<BlockingState>() : new ArrayList<BlockingState>(filtered);
     }
 
     @Override
-    public List<BlockingState> getBlockingHistoryFor(final UUID overdueableId, final InternalTenantContext context) {
+    public List<BlockingState> getBlockingHistory(final UUID overdueableId, final InternalTenantContext context) {
         final List<BlockingState> states = blockingStates.get(overdueableId);
         // Note! The returned list cannot be immutable!
         return states == null ? new ArrayList<BlockingState>() : states;
     }
 
     @Override
-    public synchronized <T extends Blockable> void setBlockingState(final BlockingState state, final Clock clock, final InternalCallContext context) {
+    public synchronized void setBlockingState(final BlockingState state, final Clock clock, final InternalCallContext context) {
         if (blockingStates.get(state.getBlockedId()) == null) {
             blockingStates.put(state.getBlockedId(), new ArrayList<BlockingState>());
         }
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/dao/TestBlockingDao.java b/entitlement/src/test/java/com/ning/billing/entitlement/dao/TestBlockingDao.java
index 1c02e8a..a170ac4 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/dao/TestBlockingDao.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/dao/TestBlockingDao.java
@@ -19,12 +19,16 @@ package com.ning.billing.entitlement.dao;
 import java.util.List;
 import java.util.UUID;
 
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
 import org.mockito.Mockito;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import com.ning.billing.entitlement.EntitlementTestSuiteWithEmbeddedDB;
 import com.ning.billing.entitlement.api.BlockingState;
+import com.ning.billing.entitlement.api.BlockingStateType;
+import com.ning.billing.overdue.OverdueState;
 import com.ning.billing.subscription.api.user.SubscriptionBaseBundle;
 import com.ning.billing.util.svcapi.junction.DefaultBlockingState;
 
@@ -32,6 +36,8 @@ public class TestBlockingDao extends EntitlementTestSuiteWithEmbeddedDB {
 
     @Test(groups = "slow")
     public void testDao() {
+
+
         final UUID uuid = UUID.randomUUID();
         final String overdueStateName = "WayPassedItMan";
         final String service = "TEST";
@@ -40,42 +46,54 @@ public class TestBlockingDao extends EntitlementTestSuiteWithEmbeddedDB {
         final boolean blockEntitlement = false;
         final boolean blockBilling = false;
 
-        final BlockingState state1 = new DefaultBlockingState(uuid, overdueStateName, service, blockChange, blockEntitlement, blockBilling);
+        clock.setDay(new LocalDate(2012, 4, 1));
+
+        final BlockingState state1 = new DefaultBlockingState(uuid, BlockingStateType.ACCOUNT, overdueStateName, service, blockChange, blockEntitlement, blockBilling);
         blockingStateDao.setBlockingState(state1, clock, internalCallContext);
-        clock.setDeltaFromReality(1000 * 3600 * 24);
+
+        clock.addDays(1);
 
         final String overdueStateName2 = "NoReallyThisCantGoOn";
-        final BlockingState state2 = new DefaultBlockingState(uuid, overdueStateName2, service, blockChange, blockEntitlement, blockBilling);
+        final BlockingState state2 = new DefaultBlockingState(uuid, BlockingStateType.ACCOUNT, overdueStateName2, service, blockChange, blockEntitlement, blockBilling);
         blockingStateDao.setBlockingState(state2, clock, internalCallContext);
 
         final SubscriptionBaseBundle bundle = Mockito.mock(SubscriptionBaseBundle.class);
         Mockito.when(bundle.getId()).thenReturn(uuid);
 
-        Assert.assertEquals(blockingStateDao.getBlockingStateFor(uuid, internalCallContext).getStateName(), state2.getStateName());
+        Assert.assertEquals(blockingStateDao.getBlockingStateForService(uuid, service, internalCallContext).getStateName(), state2.getStateName());
+
+        final List<BlockingState> states = blockingStateDao.getBlockingHistoryForService(uuid, service, internalCallContext);
+        Assert.assertEquals(states.size(), 2);
+
+        Assert.assertEquals(states.get(0).getStateName(), overdueStateName);
+        Assert.assertEquals(states.get(1).getStateName(), overdueStateName2);
     }
 
+
     @Test(groups = "slow")
     public void testDaoHistory() throws Exception {
         final UUID uuid = UUID.randomUUID();
         final String overdueStateName = "WayPassedItMan";
-        final String service = "TEST";
+        final String service1 = "TEST";
 
         final boolean blockChange = true;
         final boolean blockEntitlement = false;
         final boolean blockBilling = false;
 
-        final BlockingState state1 = new DefaultBlockingState(uuid, overdueStateName, service, blockChange, blockEntitlement, blockBilling);
+        final BlockingState state1 = new DefaultBlockingState(uuid, BlockingStateType.ACCOUNT, overdueStateName, service1, blockChange, blockEntitlement, blockBilling);
         blockingStateDao.setBlockingState(state1, clock, internalCallContext);
         clock.setDeltaFromReality(1000 * 3600 * 24);
 
+        final String service2 = "TEST2";
+
         final String overdueStateName2 = "NoReallyThisCantGoOn";
-        final BlockingState state2 = new DefaultBlockingState(uuid, overdueStateName2, service, blockChange, blockEntitlement, blockBilling);
+        final BlockingState state2 = new DefaultBlockingState(uuid, BlockingStateType.ACCOUNT, overdueStateName2, service2, blockChange, blockEntitlement, blockBilling);
         blockingStateDao.setBlockingState(state2, clock, internalCallContext);
 
         final SubscriptionBaseBundle bundle = Mockito.mock(SubscriptionBaseBundle.class);
         Mockito.when(bundle.getId()).thenReturn(uuid);
 
-        final List<BlockingState> history2 = blockingStateDao.getBlockingHistoryFor(bundle.getId(), internalCallContext);
+        final List<BlockingState> history2 = blockingStateDao.getBlockingHistory(bundle.getId(), internalCallContext);
         Assert.assertEquals(history2.size(), 2);
         Assert.assertEquals(history2.get(0).getStateName(), overdueStateName);
         Assert.assertEquals(history2.get(1).getStateName(), overdueStateName2);
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BlockingCalculator.java b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BlockingCalculator.java
index 2be9265..a18c0d3 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BlockingCalculator.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BlockingCalculator.java
@@ -33,6 +33,7 @@ import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.overdue.OverdueService;
 import com.ning.billing.subscription.api.SubscriptionBaseTransitionType;
 import com.ning.billing.subscription.api.SubscriptionBase;
 import com.ning.billing.entitlement.api.BlockingState;
@@ -92,8 +93,8 @@ public class BlockingCalculator {
         final SortedSet<BillingEvent> billingEventsToRemove = new TreeSet<BillingEvent>();
 
         for (final UUID bundleId : bundleMap.keySet()) {
-            final List<BlockingState> blockingEvents = blockingApi.getBlockingHistory(bundleId, context);
-            blockingEvents.addAll(blockingApi.getBlockingHistory(account.getId(), context));
+            final List<BlockingState> blockingEvents = blockingApi.getBlockingHistoryForService(bundleId, OverdueService.OVERDUE_SERVICE_NAME, context);
+            blockingEvents.addAll(blockingApi.getBlockingHistoryForService(account.getId(), OverdueService.OVERDUE_SERVICE_NAME, context));
             final List<DisabledDuration> blockingDurations = createBlockingDurations(blockingEvents);
 
             for (final SubscriptionBase subscription : bundleMap.get(bundleId)) {
diff --git a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApi.java b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApi.java
index ca3f206..c6d01b7 100644
--- a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApi.java
+++ b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApi.java
@@ -29,6 +29,7 @@ import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.catalog.api.PriceList;
 import com.ning.billing.catalog.api.PriceListSet;
+import com.ning.billing.entitlement.api.BlockingStateType;
 import com.ning.billing.entitlement.dao.MockBlockingStateDao;
 import com.ning.billing.junction.JunctionTestSuiteNoDB;
 import com.ning.billing.entitlement.api.BlockingState;
@@ -181,8 +182,8 @@ public class TestBillingApi extends JunctionTestSuiteNoDB {
         final Account account = createAccount(32);
 
         final List<BlockingState> blockingStates = new ArrayList<BlockingState>();
-        blockingStates.add(new DefaultBlockingState(UUID.randomUUID(), bunId, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
-        blockingStates.add(new DefaultBlockingState(UUID.randomUUID(), bunId, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2), null));
+        blockingStates.add(new DefaultBlockingState(UUID.randomUUID(), bunId, BlockingStateType.BUNDLE,  DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
+        blockingStates.add(new DefaultBlockingState(UUID.randomUUID(), bunId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2), null));
 
         ((MockBlockingStateDao) blockingStateDao).setBlockingStates(bunId, blockingStates);
         final SortedSet<BillingEvent> events = billingInternalApi.getBillingEventsForAccountAndUpdateAccountBCD(account.getId(), internalCallContext);
diff --git a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBlockingCalculator.java b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBlockingCalculator.java
index 974f9b9..837e66f 100644
--- a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBlockingCalculator.java
+++ b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBlockingCalculator.java
@@ -23,6 +23,7 @@ import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.entitlement.api.BlockingStateType;
 import com.ning.billing.entitlement.dao.MockBlockingStateDao;
 import com.ning.billing.junction.JunctionTestSuiteNoDB;
 import com.ning.billing.entitlement.api.BlockingState;
@@ -112,8 +113,8 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         billingEvents.add(D);
 
         final List<BlockingState> blockingStates = new ArrayList<BlockingState>();
-        blockingStates.add(new DefaultBlockingState(UUID.randomUUID(), bundleId1, DISABLED_BUNDLE, "test", true, true, true, now, null));
-        blockingStates.add(new DefaultBlockingState(UUID.randomUUID(), bundleId1, CLEAR_BUNDLE,  "test", false, false, false, now.plusDays(2), null));
+        blockingStates.add(new DefaultBlockingState(UUID.randomUUID(), bundleId1, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now, null));
+        blockingStates.add(new DefaultBlockingState(UUID.randomUUID(), bundleId1, BlockingStateType.BUNDLE, CLEAR_BUNDLE,  "test", false, false, false, now.plusDays(2), null));
 
         setBlockingStates(bundleId1, blockingStates);
 
@@ -645,8 +646,8 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
 
         //simple events open clear -> disabled
         blockingEvents = new ArrayList<BlockingState>();
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, CLEAR_BUNDLE, "test", false, false, false, now, null));
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now, null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
 
         List<DisabledDuration> pairs = blockingCalculator.createBlockingDurations(blockingEvents);
         assertEquals(pairs.size(), 1);
@@ -656,9 +657,9 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
 
         //simple events closed clear -> disabled
         blockingEvents = new ArrayList<BlockingState>();
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, CLEAR_BUNDLE, "test", false, false, false, now, null));
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now, null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2), null));
 
         pairs = blockingCalculator.createBlockingDurations(blockingEvents);
         assertEquals(pairs.size(), 1);
@@ -669,9 +670,9 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
 
         //simple BUNDLE events closed clear -> disabled
         blockingEvents = new ArrayList<BlockingState>();
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, CLEAR_BUNDLE, "test", false, false, false, now, null));
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now, null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(2), null));
 
         pairs = blockingCalculator.createBlockingDurations(blockingEvents);
         assertEquals(pairs.size(), 1);
@@ -682,10 +683,10 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
 
         //two or more disableds in a row
         blockingEvents = new ArrayList<BlockingState>();
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, CLEAR_BUNDLE, "test", false, false, false, now, null));
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(2), null));
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(3), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now, null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(2), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(3), null));
 
         pairs = blockingCalculator.createBlockingDurations(blockingEvents);
         assertEquals(pairs.size(), 1);
@@ -695,11 +696,11 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         assertEquals(pairs.get(0).getEnd(), now.plusDays(3));
 
         blockingEvents = new ArrayList<BlockingState>();
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, CLEAR_BUNDLE, "test", false, false, false, now, null));
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(2), null));
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(3), null));
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(4), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now, null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(1), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(2), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, now.plusDays(3), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, now.plusDays(4), null));
 
         pairs = blockingCalculator.createBlockingDurations(blockingEvents);
         assertEquals(pairs.size(), 1);
@@ -722,10 +723,10 @@ public class TestBlockingCalculator extends JunctionTestSuiteNoDB {
         billingEvents.add(upgrade);
 
         final List<BlockingState> blockingEvents = new ArrayList<BlockingState>();
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, DISABLED_BUNDLE, "test", true, false, false, new LocalDate(2012, 7, 5).toDateTimeAtStartOfDay(DateTimeZone.UTC), null));
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, DISABLED_BUNDLE, "test", true, true, true, new LocalDate(2012, 7, 15).toDateTimeAtStartOfDay(DateTimeZone.UTC), null));
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, DISABLED_BUNDLE, "test", true, true, true, new LocalDate(2012, 7, 25).toDateTimeAtStartOfDay(DateTimeZone.UTC), null));
-        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, CLEAR_BUNDLE, "test", false, false, false, new LocalDate(2012, 7, 25).toDateTimeAtStartOfDay(DateTimeZone.UTC), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, false, false, new LocalDate(2012, 7, 5).toDateTimeAtStartOfDay(DateTimeZone.UTC), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, new LocalDate(2012, 7, 15).toDateTimeAtStartOfDay(DateTimeZone.UTC), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, DISABLED_BUNDLE, "test", true, true, true, new LocalDate(2012, 7, 25).toDateTimeAtStartOfDay(DateTimeZone.UTC), null));
+        blockingEvents.add(new DefaultBlockingState(UUID.randomUUID(), ovdId, BlockingStateType.BUNDLE, CLEAR_BUNDLE, "test", false, false, false, new LocalDate(2012, 7, 25).toDateTimeAtStartOfDay(DateTimeZone.UTC), null));
 
         setBlockingStates(bundleId1, blockingEvents);
 
diff --git a/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java b/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
index 47caf84..e31d87c 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
@@ -24,6 +24,7 @@ import com.ning.billing.ObjectType;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.entitlement.api.Blockable;
 import com.ning.billing.overdue.OverdueApiException;
+import com.ning.billing.overdue.OverdueService;
 import com.ning.billing.overdue.OverdueState;
 import com.ning.billing.overdue.OverdueUserApi;
 import com.ning.billing.overdue.config.OverdueConfig;
@@ -61,7 +62,7 @@ public class DefaultOverdueUserApi implements OverdueUserApi {
     @Override
     public OverdueState getOverdueStateFor(final Account overdueable, final TenantContext context) throws OverdueException {
         try {
-            final String stateName = accessApi.getBlockingStateFor(overdueable, internalCallContextFactory.createInternalTenantContext(context)).getStateName();
+            final String stateName = accessApi.getBlockingStateForService(overdueable, OverdueService.OVERDUE_SERVICE_NAME, internalCallContextFactory.createInternalTenantContext(context)).getStateName();
             final OverdueStateSet states = overdueConfig.getBundleStateSet();
             return states.findState(stateName);
         } catch (OverdueApiException e) {
diff --git a/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java b/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
index 9374751..885ec8f 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
@@ -34,6 +34,7 @@ import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.bus.api.PersistentBus;
 import com.ning.billing.catalog.api.BillingActionPolicy;
 import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.entitlement.api.BlockingStateType;
 import com.ning.billing.entitlement.api.Entitlement;
 import com.ning.billing.entitlement.api.EntitlementApi;
 import com.ning.billing.entitlement.api.EntitlementApiException;
@@ -172,6 +173,7 @@ public class OverdueStateApplicator<T extends Blockable> {
     protected void storeNewState(final Account blockable, final OverdueState nextOverdueState, final InternalCallContext context) throws OverdueException {
         try {
             blockingApi.setBlockingState(new DefaultBlockingState(blockable.getId(),
+                                                                  BlockingStateType.ACCOUNT,
                                                                   nextOverdueState.getName(),
                                                                   OverdueService.OVERDUE_SERVICE_NAME,
                                                                   blockChanges(nextOverdueState),
diff --git a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
index 7dceec9..2a03dd6 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapper.java
@@ -17,8 +17,8 @@
 package com.ning.billing.overdue.wrapper;
 
 import com.ning.billing.account.api.Account;
-import com.ning.billing.entitlement.api.Blockable;
 import com.ning.billing.overdue.OverdueApiException;
+import com.ning.billing.overdue.OverdueService;
 import com.ning.billing.overdue.OverdueState;
 import com.ning.billing.overdue.applicator.OverdueStateApplicator;
 import com.ning.billing.overdue.calculator.BillingStateCalculator;
@@ -57,7 +57,7 @@ public class OverdueWrapper {
         }
 
         final BillingState billingState = billingState(context);
-        final String previousOverdueStateName = api.getBlockingStateFor(overdueable, context).getStateName();
+        final String previousOverdueStateName = api.getBlockingStateForService(overdueable, OverdueService.OVERDUE_SERVICE_NAME, context).getStateName();
         final OverdueState nextOverdueState = overdueStateSet.calculateOverdueState(billingState, clock.getToday(billingState.getAccountTimeZone()));
 
         overdueStateApplicator.apply(overdueStateSet.getFirstState(), billingState, overdueable, previousOverdueStateName, nextOverdueState, context);
@@ -66,7 +66,7 @@ public class OverdueWrapper {
     }
 
     public void clear(final InternalCallContext context) throws OverdueException, OverdueApiException {
-        final String previousOverdueStateName = api.getBlockingStateFor(overdueable, context).getStateName();
+        final String previousOverdueStateName = api.getBlockingStateForService(overdueable, OverdueService.OVERDUE_SERVICE_NAME, context).getStateName();
         overdueStateApplicator.clear(overdueable, previousOverdueStateName, overdueStateSet.getClearState(), context);
     }
 
diff --git a/overdue/src/test/java/com/ning/billing/overdue/glue/ApplicatorMockJunctionModule.java b/overdue/src/test/java/com/ning/billing/overdue/glue/ApplicatorMockJunctionModule.java
index da8b7c1..99911f9 100644
--- a/overdue/src/test/java/com/ning/billing/overdue/glue/ApplicatorMockJunctionModule.java
+++ b/overdue/src/test/java/com/ning/billing/overdue/glue/ApplicatorMockJunctionModule.java
@@ -23,6 +23,7 @@ import org.joda.time.DateTime;
 
 import com.ning.billing.entitlement.api.Blockable;
 import com.ning.billing.entitlement.api.BlockingState;
+import com.ning.billing.entitlement.api.BlockingStateType;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalTenantContext;
 import com.ning.billing.util.svcapi.junction.BlockingInternalApi;
@@ -46,7 +47,7 @@ public class ApplicatorMockJunctionModule extends AbstractModule {
         }
 
         @Override
-        public BlockingState getBlockingStateFor(final Blockable overdueable, final InternalTenantContext context) {
+        public BlockingState getBlockingStateForService(final Blockable overdueable, final String serviceName, final InternalTenantContext context) {
             return new BlockingState() {
 
                 @Override
@@ -60,6 +61,11 @@ public class ApplicatorMockJunctionModule extends AbstractModule {
                 }
 
                 @Override
+                public BlockingStateType getType() {
+                    return BlockingStateType.ACCOUNT;
+                }
+
+                @Override
                 public DateTime getTimestamp() {
                     return null;
                 }
@@ -112,22 +118,23 @@ public class ApplicatorMockJunctionModule extends AbstractModule {
         }
 
         @Override
-        public BlockingState getBlockingStateFor(final UUID overdueableId, final InternalTenantContext context) {
+        public BlockingState getBlockingStateForService(final UUID overdueableId, final String serviceName, final InternalTenantContext context) {
             throw new UnsupportedOperationException();
         }
 
         @Override
-        public List<BlockingState> getBlockingHistory(final Blockable overdueable, final InternalTenantContext context) {
+        public List<BlockingState> getBlockingHistoryForService(final Blockable overdueable, final String serviceName, final InternalTenantContext context) {
             throw new UnsupportedOperationException();
         }
 
         @Override
-        public List<BlockingState> getBlockingHistory(final UUID overdueableId, final InternalTenantContext context) {
+        public List<BlockingState> getBlockingHistoryForService(final UUID overdueableId, final String serviceName, final InternalTenantContext context) {
             throw new UnsupportedOperationException();
         }
 
+
         @Override
-        public <T extends Blockable> void setBlockingState(final BlockingState state, final InternalCallContext context) {
+        public void setBlockingState(final BlockingState state, final InternalCallContext context) {
             blockingState = state;
         }
 
diff --git a/util/src/main/java/com/ning/billing/util/svcapi/junction/BlockingInternalApi.java b/util/src/main/java/com/ning/billing/util/svcapi/junction/BlockingInternalApi.java
index 4baae14..d4a7f84 100644
--- a/util/src/main/java/com/ning/billing/util/svcapi/junction/BlockingInternalApi.java
+++ b/util/src/main/java/com/ning/billing/util/svcapi/junction/BlockingInternalApi.java
@@ -26,14 +26,14 @@ import com.ning.billing.util.callcontext.InternalTenantContext;
 
 public interface BlockingInternalApi {
 
-    public BlockingState getBlockingStateFor(Blockable overdueable, InternalTenantContext context);
+    public BlockingState getBlockingStateForService(Blockable overdueable, String serviceName, InternalTenantContext context);
 
-    public BlockingState getBlockingStateFor(UUID overdueableId, InternalTenantContext context);
+    public BlockingState getBlockingStateForService(UUID overdueableId, String serviceName, InternalTenantContext context);
 
-    public List<BlockingState> getBlockingHistory(Blockable overdueable, InternalTenantContext context);
+    public List<BlockingState> getBlockingHistoryForService(Blockable overdueable, String serviceName, InternalTenantContext context);
 
-    public List<BlockingState> getBlockingHistory(UUID overdueableId, InternalTenantContext context);
+    public List<BlockingState> getBlockingHistoryForService(UUID overdueableId, String serviceName, InternalTenantContext context);
 
-    public <T extends Blockable> void setBlockingState(BlockingState state, InternalCallContext context);
+    public void setBlockingState(BlockingState state, InternalCallContext context);
 
 }
diff --git a/util/src/main/java/com/ning/billing/util/svcapi/junction/DefaultBlockingState.java b/util/src/main/java/com/ning/billing/util/svcapi/junction/DefaultBlockingState.java
index f1f8e04..e345e44 100644
--- a/util/src/main/java/com/ning/billing/util/svcapi/junction/DefaultBlockingState.java
+++ b/util/src/main/java/com/ning/billing/util/svcapi/junction/DefaultBlockingState.java
@@ -21,6 +21,7 @@ import java.util.UUID;
 import org.joda.time.DateTime;
 
 import com.ning.billing.entitlement.api.BlockingState;
+import com.ning.billing.entitlement.api.BlockingStateType;
 import com.ning.billing.util.entity.EntityBase;
 
 
@@ -37,11 +38,12 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
     private final boolean blockEntitlement;
     private final boolean blockBilling;
     private final DateTime timestamp;
+    private final BlockingStateType type;
 
-    public static BlockingState getClearState() {
+    public static BlockingState getClearState(final BlockingStateType type) {
         if (clearState == null) {
             // STEPH_ENT should we not always have a service name?
-            clearState = new DefaultBlockingState(null, CLEAR_STATE_NAME, null, false, false, false);
+            clearState = new DefaultBlockingState(null, type, CLEAR_STATE_NAME, null, false, false, false);
         }
         return clearState;
     }
@@ -49,6 +51,7 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
 
     public DefaultBlockingState(final UUID id,
                                 final UUID blockingId,
+                                final BlockingStateType type,
                                 final String stateName,
                                 final String service,
                                 final boolean blockChange,
@@ -58,6 +61,7 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
                                 final DateTime createDate) {
         super(id, createDate, null);
         this.blockingId = blockingId;
+        this.type = type;
         this.stateName = stateName;
         this.service = service;
         this.blockChange = blockChange;
@@ -67,6 +71,7 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
     }
 
     public DefaultBlockingState(final UUID blockingId,
+                                final BlockingStateType type,
                                  final String stateName,
                                  final String service,
                                  final boolean blockChange,
@@ -74,6 +79,7 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
                                  final boolean blockBilling) {
         this(UUID.randomUUID(),
              blockingId,
+             type,
              stateName,
              service,
              blockChange,
@@ -96,6 +102,11 @@ public class DefaultBlockingState extends EntityBase implements BlockingState {
         return stateName;
     }
 
+    @Override
+    public BlockingStateType getType() {
+        return type;
+    }
+
     /* (non-Javadoc)
     * @see com.ning.billing.junction.api.blocking.BlockingState#getTimestamp()
     */
diff --git a/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java b/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java
index 1b01933..760137b 100644
--- a/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java
+++ b/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java
@@ -26,6 +26,7 @@ import com.ning.billing.account.api.AccountData;
 import com.ning.billing.account.api.MutableAccountData;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.entitlement.api.BlockingState;
+import com.ning.billing.entitlement.api.BlockingStateType;
 import com.ning.billing.util.svcapi.junction.DefaultBlockingState;
 
 public class MockAccountBuilder {
@@ -321,7 +322,7 @@ public class MockAccountBuilder {
 
             @Override
             public BlockingState getBlockingState() {
-                return  DefaultBlockingState.getClearState();
+                return  DefaultBlockingState.getClearState(BlockingStateType.ACCOUNT);
             }
 
             @Override