killbill-aplcache

Added several new tests and worked through a lot of test guice

4/20/2012 5:19:58 PM

Changes

beatrix/pom.xml 10(+10 -0)

invoice/pom.xml 12(+12 -0)

junction/pom.xml 11(+11 -0)

junction/src/test/java/com/ning/billing/junction/blocking/TestOverdueChecker.java 170(+0 -170)

overdue/pom.xml 5(+5 -0)

Details

diff --git a/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java b/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java
index 564f892..ca58034 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/AnalyticsTestModule.java
@@ -24,6 +24,7 @@ import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.entitlement.glue.EntitlementModule;
 import com.ning.billing.invoice.glue.InvoiceModule;
 import com.ning.billing.junction.MockBlockingModule;
+import com.ning.billing.junction.glue.JunctionModule;
 import com.ning.billing.payment.setup.PaymentModule;
 import com.ning.billing.util.glue.BusModule;
 import com.ning.billing.util.glue.CallContextModule;
@@ -48,11 +49,11 @@ public class AnalyticsTestModule extends AnalyticsModule
         install(new AccountModule());
         install(new BusModule());
         install(new EntitlementModule());
-        install(new MockBlockingModule());
         install(new InvoiceModule());
         install(new PaymentModule());
         install(new TagStoreModule());
         install(new NotificationQueueModule());
+        install(new JunctionModule());
 
         // Install the Dao layer
         final MysqlTestingHelper helper = new MysqlTestingHelper();
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
index 306bf90..7144edb 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
@@ -245,4 +245,9 @@ public class MockSubscription implements Subscription
     public boolean processPayment() {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public List<SubscriptionEventTransition> getBillingTransitions() {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/billing/ChargeThruApi.java b/api/src/main/java/com/ning/billing/entitlement/api/billing/ChargeThruApi.java
new file mode 100644
index 0000000..0dec9b9
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/entitlement/api/billing/ChargeThruApi.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.entitlement.api.billing;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+
+import com.ning.billing.util.callcontext.CallContext;
+
+public interface ChargeThruApi {
+
+    /**
+     * @param subscriptionId
+     * @return UUID of
+     */
+    public UUID getAccountIdFromSubscriptionId(UUID subscriptionId);
+    
+    /**
+     * Sets the charged through date for the subscription with that Id.
+     * 
+     * @param subscriptionId
+     * @param ctd
+     * @param context
+     */
+    public void setChargedThroughDate(UUID subscriptionId, DateTime ctd, CallContext context);
+
+    /**
+     * Sets the charged through date for the subscription with that Id. Within the context of a SQL Transaction
+     * 
+     * @param transactionalDao
+     * @param subscriptionId
+     * @param ctd
+     * @param context
+     */
+    public void setChargedThroughDateFromTransaction(Transmogrifier transactionalDao, UUID subscriptionId,
+                                                     DateTime ctd, CallContext context);
+
+}
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/EntitlementService.java b/api/src/main/java/com/ning/billing/entitlement/api/EntitlementService.java
index 28084b2..9c9e26e 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/EntitlementService.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/EntitlementService.java
@@ -16,7 +16,7 @@
 
 package com.ning.billing.entitlement.api;
 
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
+import com.ning.billing.entitlement.api.billing.ChargeThruApi;
 import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.lifecycle.KillbillService;
@@ -28,7 +28,7 @@ public interface EntitlementService extends KillbillService {
 
     public EntitlementUserApi getUserApi();
 
-    public EntitlementBillingApi getBillingApi();
+    public ChargeThruApi getBillingApi();
 
     public EntitlementMigrationApi getMigrationApi();
 }
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
index da8ad47..b47414b 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
@@ -16,6 +16,7 @@
 
 package com.ning.billing.entitlement.api.user;
 
+import java.util.List;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
@@ -26,11 +27,12 @@ import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.PriceList;
 import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.junction.api.Blockable;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.entity.ExtendedEntity;
 
 
-public interface Subscription extends ExtendedEntity {
+public interface Subscription extends ExtendedEntity, Blockable {
 
     public boolean cancel(DateTime requestedDate, boolean eot, CallContext context)
     throws EntitlementUserApiException;
@@ -72,4 +74,6 @@ public interface Subscription extends ExtendedEntity {
     public SubscriptionEventTransition getPendingTransition();
 
     public SubscriptionEventTransition getPreviousTransition();
+    
+    public List<SubscriptionEventTransition> getBillingTransitions();
 }
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEventTransition.java b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEventTransition.java
index e0de69d..bd93598 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEventTransition.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionEventTransition.java
@@ -68,4 +68,6 @@ public interface SubscriptionEventTransition extends BusEvent {
     PriceList getNextPriceList();
     
     Integer getRemainingEventsForUserOperation();
+    
+    long getTotalOrdering();
 }
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index db73376..234cb45 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -165,8 +165,15 @@ public enum ErrorCode {
      * Range 5000: Overdue system
      * 
      */
-    OVERDUE_OVERDUEABLE_NOT_SUPPORTED(5001, "The Overdueable type '%s' is not supported"), 
-    OVERDUE_CAT_ERROR_ENCOUNTERED(5002,"Catalog error encountered on Overdueable: id='%s', type='%s'"),  
+    OVERDUE_CAT_ERROR_ENCOUNTERED(5001,"Catalog error encountered on Overdueable: id='%s', type='%s'"),  
+    OVERDUE_TYPE_NOT_SUPPORTED(5002,"Overdue of this type is not supported: id='%s', type='%s'"),  
+    /*
+     * 
+     * Range 6000: Blocking system
+     * 
+     */
+    BLOCK_BLOCKED_ACTION(6000, "The action %s is block on this %s with id=%s"),
+    BLOCK_TYPE_NOT_SUPPORTED(6001, "The Blockable type '%s' is not supported") 
     
     
     ;
diff --git a/api/src/main/java/com/ning/billing/junction/api/Blockable.java b/api/src/main/java/com/ning/billing/junction/api/Blockable.java
index a3098c7..6c0976e 100644
--- a/api/src/main/java/com/ning/billing/junction/api/Blockable.java
+++ b/api/src/main/java/com/ning/billing/junction/api/Blockable.java
@@ -19,28 +19,37 @@ package com.ning.billing.junction.api;
 import java.util.UUID;
 
 import com.ning.billing.ErrorCode;
-import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 
 public interface Blockable {
 
     public enum Type {
-        //Not currently supported
-        // ACCOUNT,
-        SUBSCRIPTION_BUNDLE;
+        ACCOUNT,
+        SUBSCRIPTION_BUNDLE,
+        SUBSCRIPTION;
         
-        public static Type get(Blockable o) throws CatalogApiException{
-            if (o instanceof SubscriptionBundle){
+        public static Type get(Blockable o) throws BlockingApiException{
+            if (o instanceof Account){
+                return ACCOUNT;
+            } else if (o instanceof SubscriptionBundle){
                 return SUBSCRIPTION_BUNDLE;
+            } else if (o instanceof Subscription){
+                return SUBSCRIPTION;
             }
-            throw new CatalogApiException(ErrorCode.CAT_NO_OVERDUEABLE_TYPE , o.getClass().getName());
+            throw new BlockingApiException(ErrorCode.BLOCK_TYPE_NOT_SUPPORTED , o.getClass().getName());
         }
         
-        public static Type get(String type) throws CatalogApiException {
-            if (type.equalsIgnoreCase(SUBSCRIPTION_BUNDLE.name())) {
+        public static Type get(String type) throws BlockingApiException {
+            if (type.equalsIgnoreCase(ACCOUNT.name())) {
+                return ACCOUNT;
+            } else if (type.equalsIgnoreCase(SUBSCRIPTION_BUNDLE.name())) {
                 return SUBSCRIPTION_BUNDLE;
+            } else if (type.equalsIgnoreCase(SUBSCRIPTION.name())) {
+                return SUBSCRIPTION;
             }
-            throw new CatalogApiException(ErrorCode.CAT_NO_OVERDUEABLE_TYPE , type);
+            throw new BlockingApiException(ErrorCode.BLOCK_TYPE_NOT_SUPPORTED , type);
         }
 
     }
diff --git a/api/src/main/java/com/ning/billing/junction/api/BlockingApi.java b/api/src/main/java/com/ning/billing/junction/api/BlockingApi.java
index 584cfda..e901d19 100644
--- a/api/src/main/java/com/ning/billing/junction/api/BlockingApi.java
+++ b/api/src/main/java/com/ning/billing/junction/api/BlockingApi.java
@@ -19,15 +19,13 @@ package com.ning.billing.junction.api;
 import java.util.SortedSet;
 import java.util.UUID;
 
-import com.ning.billing.overdue.OverdueState;
-
 
 public interface BlockingApi {
     public static final String CLEAR_STATE_NAME = "__KILLBILL__CLEAR__OVERDUE_STATE__";
 
-    public String getBlockingStateNameFor(Blockable overdueable);
+    public BlockingState getBlockingStateFor(Blockable overdueable);
 
-    public String getBlockingStateNameFor(UUID overdueableId, Blockable.Type type);
+    public BlockingState getBlockingStateFor(UUID overdueableId, Blockable.Type type);
     
     public SortedSet<BlockingState> getBlockingHistory(Blockable overdueable);
 
diff --git a/api/src/main/java/com/ning/billing/junction/api/BlockingState.java b/api/src/main/java/com/ning/billing/junction/api/BlockingState.java
index dcc066b..8c771d2 100644
--- a/api/src/main/java/com/ning/billing/junction/api/BlockingState.java
+++ b/api/src/main/java/com/ning/billing/junction/api/BlockingState.java
@@ -176,5 +176,14 @@ public class BlockingState implements Comparable<BlockingState>{
             return "On";
         }
     }
+
+    @Override
+    public String toString() {
+        return "BlockingState [blockingId=" + blockingId + ", type=" + type + ", stateName=" + stateName + ", service="
+                + service + ", blockChange=" + blockChange + ", blockEntitlement=" + blockEntitlement
+                + ", blockBilling=" + blockBilling + ", timestamp=" + timestamp + "]";
+    }
+    
+    
     
 }

beatrix/pom.xml 10(+10 -0)

diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index 64726c8..bed20c1 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -41,6 +41,10 @@
             <artifactId>killbill-catalog</artifactId>
         </dependency>
         <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-junction</artifactId>
+        </dependency>
+        <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
         </dependency>
@@ -61,6 +65,12 @@
             <groupId>joda-time</groupId>
             <artifactId>joda-time</artifactId>
         </dependency>
+         <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-junction</artifactId>
+             <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>com.ning.billing</groupId>
             <artifactId>killbill-payment</artifactId>
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java
index 1ad8ccb..0a4a18a 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/MockModule.java
@@ -42,6 +42,7 @@ import com.ning.billing.entitlement.api.EntitlementService;
 import com.ning.billing.entitlement.glue.EntitlementModule;
 import com.ning.billing.invoice.api.InvoiceService;
 import com.ning.billing.invoice.glue.InvoiceModule;
+import com.ning.billing.junction.glue.JunctionModule;
 import com.ning.billing.lifecycle.KillbillService;
 import com.ning.billing.payment.api.PaymentService;
 import com.ning.billing.payment.provider.MockPaymentProviderPluginModule;
@@ -93,6 +94,7 @@ public class MockModule extends AbstractModule {
         install(new EntitlementModule());
         install(new InvoiceModule());
         install(new PaymentMockModule());
+        install(new JunctionModule());
     }
 
     private static final class PaymentMockModule extends PaymentModule {
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java
index 5c7b1e6..2ed1cfa 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java
@@ -43,7 +43,6 @@ public class DefaultCatalogService implements KillbillService, Provider<Catalog>
     @Inject
     public DefaultCatalogService(CatalogConfig config, VersionedCatalogLoader loader) {
         this.config = config;
-        System.out.println(config.getCatalogURI());
         this.isInitialized = false;
         this.loader = loader;
     }
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java b/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
index fa51ed1..40dc146 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
@@ -18,14 +18,35 @@ package com.ning.billing.catalog;
 
 import java.util.Date;
 
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.ActionPolicy;
+import com.ning.billing.catalog.api.BillingAlignment;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.Catalog;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanAlignmentChange;
+import com.ning.billing.catalog.api.PlanAlignmentCreate;
+import com.ning.billing.catalog.api.PlanChangeResult;
+import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.api.PriceList;
+import com.ning.billing.catalog.api.Product;
 import com.ning.billing.catalog.rules.CaseCancelPolicy;
 import com.ning.billing.catalog.rules.CaseChangePlanAlignment;
 import com.ning.billing.catalog.rules.CaseChangePlanPolicy;
 import com.ning.billing.catalog.rules.CaseCreateAlignment;
 import com.ning.billing.catalog.rules.PlanRules;
 
-public class MockCatalog extends StandaloneCatalog {
+public class MockCatalog extends StandaloneCatalog implements Catalog {
 	private static final String[] PRODUCT_NAMES = new String[]{ "TestProduct1", "TestProduct2", "TestProduct3"};
+    private boolean canCreatePlan;
+    private PlanChangeResult planChange;
+    private BillingAlignment billingAlignment;
+    private PlanAlignmentCreate planCreateAlignment;
 	
 	public MockCatalog() {
 		setEffectiveDate(new Date());
@@ -66,6 +87,156 @@ public class MockCatalog extends StandaloneCatalog {
 		return PRODUCT_NAMES;
 	}
 
+    @Override
+    public Currency[] getSupportedCurrencies(DateTime requestedDate) throws CatalogApiException {
+        return getCurrentSupportedCurrencies();
+    }
+
+    @Override
+    public Product[] getProducts(DateTime requestedDate) throws CatalogApiException {
+       return getCurrentProducts();
+    }
+
+    @Override
+    public Plan[] getPlans(DateTime requestedDate) throws CatalogApiException {
+        return getCurrentPlans();
+    }
+
+    @Override
+    public Plan findPlan(String name, DateTime requestedDate) throws CatalogApiException {
+        return findCurrentPlan(name);
+    }
+
+    @Override
+    public Plan findPlan(String productName, BillingPeriod term, String priceListName, DateTime requestedDate)
+            throws CatalogApiException {
+        return findCurrentPlan(productName, term, priceListName);
+    }
+
+    @Override
+    public Plan findPlan(String name, DateTime effectiveDate, DateTime subscriptionStartDate)
+            throws CatalogApiException {
+        return findCurrentPlan(name);
+    }
+
+    @Override
+    public Plan findPlan(String productName, BillingPeriod term, String priceListName, DateTime requestedDate,
+            DateTime subscriptionStartDate) throws CatalogApiException {
+       return findCurrentPlan(productName, term, priceListName);
+    }
+    
+    @Override
+    public Product findProduct(String name, DateTime requestedDate) throws CatalogApiException {
+        return findCurrentProduct(name);
+    }
+
+    @Override
+    public PlanPhase findPhase(String name, DateTime requestedDate, DateTime subscriptionStartDate)
+            throws CatalogApiException {
+        return findCurrentPhase(name);
+    }
+
+    @Override
+    public PriceList findPriceList(String name, DateTime requestedDate) throws CatalogApiException {
+        return findCurrentPricelist(name);
+    }
+
+    @Override
+    public ActionPolicy planChangePolicy(PlanPhaseSpecifier from, PlanSpecifier to, DateTime requestedDate)
+            throws CatalogApiException {
+        return planChangePolicy(from, to);
+    }
+
+    @Override
+    public PlanChangeResult planChange(PlanPhaseSpecifier from, PlanSpecifier to, DateTime requestedDate)
+            throws CatalogApiException {
+        return planChange(from, to);
+    }
+
+    @Override
+    public ActionPolicy planCancelPolicy(PlanPhaseSpecifier planPhase, DateTime requestedDate)
+            throws CatalogApiException {
+        return planCancelPolicy(planPhase);
+    }
+
+    @Override
+    public PlanAlignmentCreate planCreateAlignment(PlanSpecifier specifier, DateTime requestedDate)
+            throws CatalogApiException {
+        return planCreateAlignment(specifier);  
+    }
+
+    @Override
+    public BillingAlignment billingAlignment(PlanPhaseSpecifier planPhase, DateTime requestedDate)
+            throws CatalogApiException {
+        return billingAlignment(planPhase);
+    }
+
+    @Override
+    public PlanAlignmentChange planChangeAlignment(PlanPhaseSpecifier from, PlanSpecifier to, DateTime requestedDate)
+            throws CatalogApiException {
+        return planChangeAlignment(from, to);
+    }
+
+    @Override
+    public boolean canCreatePlan(PlanSpecifier specifier, DateTime requestedDate) throws CatalogApiException {
+        return canCreatePlan(specifier);
+    }
+
+    @Override
+    public ActionPolicy planChangePolicy(PlanPhaseSpecifier from, PlanSpecifier to) throws CatalogApiException {
+        // TODO Auto-generated method stub
+        return super.planChangePolicy(from, to);
+    }
+
+    @Override
+    public PlanAlignmentChange planChangeAlignment(PlanPhaseSpecifier from, PlanSpecifier to)
+            throws CatalogApiException {
+        // TODO Auto-generated method stub
+        return super.planChangeAlignment(from, to);
+    }
+
+    @Override
+    public ActionPolicy planCancelPolicy(PlanPhaseSpecifier planPhase) throws CatalogApiException {
+        // TODO Auto-generated method stub
+        return super.planCancelPolicy(planPhase);
+    }
+
+    @Override
+    public PlanAlignmentCreate planCreateAlignment(PlanSpecifier specifier) throws CatalogApiException {
+        return planCreateAlignment;
+    }
+
+    @Override
+    public BillingAlignment billingAlignment(PlanPhaseSpecifier planPhase) throws CatalogApiException {
+        // TODO Auto-generated method stub
+        return billingAlignment;
+    }
+
+    @Override
+    public PlanChangeResult planChange(PlanPhaseSpecifier from, PlanSpecifier to) throws CatalogApiException {
+        // TODO Auto-generated method stub
+        return planChange;
+    }
+
+    @Override
+    public boolean canCreatePlan(PlanSpecifier specifier) throws CatalogApiException {
+        return canCreatePlan;
+    }
+
+    public void setCanCreatePlan(boolean canCreatePlan) {
+        this.canCreatePlan = canCreatePlan;
+    }
+
+    public void setPlanChange(PlanChangeResult planChange) {
+        this.planChange = planChange;
+    }
+
+    public void setBillingAlignment(BillingAlignment billingAlignment) {
+        this.billingAlignment = billingAlignment;
+    }
+
+    public void setPlanCreateAlignment(PlanAlignmentCreate planCreateAlignment) {
+        this.planCreateAlignment = planCreateAlignment;
+    }
 
-	
 }
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockCatalogService.java b/catalog/src/test/java/com/ning/billing/catalog/MockCatalogService.java
new file mode 100644
index 0000000..f7277c7
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockCatalogService.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.catalog;
+
+import com.ning.billing.catalog.api.Catalog;
+import com.ning.billing.catalog.api.StaticCatalog;
+
+
+public class MockCatalogService extends DefaultCatalogService {
+
+    private MockCatalog catalog;
+
+    public MockCatalogService(MockCatalog catalog) {
+        super(null, null);
+        this.catalog = catalog;
+    }
+
+    @Override
+    public synchronized void loadCatalog() throws ServiceException {
+    }
+
+    @Override
+    public String getName() {
+        return "Mock Catalog";
+    }
+
+    @Override
+    public Catalog getFullCatalog() {
+        return catalog;
+    }
+
+    @Override
+    public Catalog get() {
+         return catalog;
+    }
+
+    @Override
+    public StaticCatalog getCurrentCatalog() {
+        return catalog;
+    }
+
+    
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockPlan.java b/catalog/src/test/java/com/ning/billing/catalog/MockPlan.java
index 45ea7d3..f4dfab1 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/MockPlan.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockPlan.java
@@ -131,7 +131,8 @@ public class MockPlan extends DefaultPlan {
 				createPickupTrialEvergreen10USD(),
 				createSportsCarTrialEvergreen100USD(),
 				createJetTrialEvergreen1000USD(),
-				createJetTrialFixedTermEvergreen1000USD()
+				createJetTrialFixedTermEvergreen1000USD(),
+				createHornMonthlyNoTrial1USD()
 		};
 	}
 	
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
index 2984ac3..bcfb4e3 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
@@ -23,20 +23,12 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
-
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.CallContextFactory;
-import com.ning.billing.util.callcontext.CallOrigin;
-import com.ning.billing.util.callcontext.UserType;
 import org.joda.time.DateTime;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.inject.Inject;
-
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.Product;
 import com.ning.billing.catalog.api.ProductCategory;
@@ -45,16 +37,16 @@ import com.ning.billing.config.NotificationConfig;
 import com.ning.billing.entitlement.alignment.PlanAligner;
 import com.ning.billing.entitlement.alignment.TimedPhase;
 import com.ning.billing.entitlement.api.EntitlementService;
-import com.ning.billing.entitlement.api.billing.DefaultEntitlementBillingApi;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
+import com.ning.billing.entitlement.api.billing.ChargeThruApi;
+import com.ning.billing.entitlement.api.billing.DefaultChargeThruApi;
 import com.ning.billing.entitlement.api.migration.DefaultEntitlementMigrationApi;
 import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
 import com.ning.billing.entitlement.api.user.DefaultEntitlementUserApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.SubscriptionFactory;
 import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
+import com.ning.billing.entitlement.api.user.SubscriptionFactory;
 import com.ning.billing.entitlement.engine.addon.AddonUtils;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
 import com.ning.billing.entitlement.events.EntitlementEvent;
@@ -65,11 +57,16 @@ import com.ning.billing.entitlement.events.user.ApiEvent;
 import com.ning.billing.entitlement.events.user.ApiEventBuilder;
 import com.ning.billing.entitlement.events.user.ApiEventCancel;
 import com.ning.billing.entitlement.exceptions.EntitlementError;
+import com.ning.billing.junction.api.BillingApi;
 import com.ning.billing.lifecycle.LifecycleHandlerType;
 import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
-import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.bus.Bus;
 import com.ning.billing.util.bus.Bus.EventBusException;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallContextFactory;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.notificationq.NotificationQueue;
 import com.ning.billing.util.notificationq.NotificationQueueService;
 import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueAlreadyExists;
@@ -87,7 +84,7 @@ public class Engine implements EventListener, EntitlementService {
     private final EntitlementDao dao;
     private final PlanAligner planAligner;
     private final EntitlementUserApi userApi;
-    private final EntitlementBillingApi billingApi;
+    private final ChargeThruApi billingApi;
     private final EntitlementMigrationApi migrationApi;
     private final AddonUtils addonUtils;
     private final Bus eventBus;
@@ -101,7 +98,7 @@ public class Engine implements EventListener, EntitlementService {
     @Inject
     public Engine(Clock clock, EntitlementDao dao, PlanAligner planAligner,
             EntitlementConfig config, DefaultEntitlementUserApi userApi,
-            DefaultEntitlementBillingApi billingApi,
+            DefaultChargeThruApi billingApi,
             DefaultEntitlementMigrationApi migrationApi, AddonUtils addonUtils, Bus eventBus,
             NotificationQueueService notificationQueueService,
             SubscriptionFactory subscriptionFactory,
@@ -191,7 +188,7 @@ public class Engine implements EventListener, EntitlementService {
     }
 
     @Override
-    public EntitlementBillingApi getBillingApi() {
+    public ChargeThruApi getBillingApi() {
         return billingApi;
     }
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
index dea0aea..6f32fe3 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
@@ -23,8 +23,8 @@ import com.ning.billing.config.EntitlementConfig;
 import com.ning.billing.entitlement.alignment.MigrationPlanAligner;
 import com.ning.billing.entitlement.alignment.PlanAligner;
 import com.ning.billing.entitlement.api.EntitlementService;
-import com.ning.billing.entitlement.api.billing.DefaultEntitlementBillingApi;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
+import com.ning.billing.entitlement.api.billing.ChargeThruApi;
+import com.ning.billing.entitlement.api.billing.DefaultChargeThruApi;
 import com.ning.billing.entitlement.api.migration.DefaultEntitlementMigrationApi;
 import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
 import com.ning.billing.entitlement.api.user.DefaultEntitlementUserApi;
@@ -55,8 +55,8 @@ public class EntitlementModule extends AbstractModule {
         bind(AddonUtils.class).asEagerSingleton();
         bind(MigrationPlanAligner.class).asEagerSingleton();
         bind(EntitlementUserApi.class).to(DefaultEntitlementUserApi.class).asEagerSingleton();
-        bind(EntitlementBillingApi.class).to(DefaultEntitlementBillingApi.class).asEagerSingleton();
         bind(EntitlementMigrationApi.class).to(DefaultEntitlementMigrationApi.class).asEagerSingleton();
+        bind(ChargeThruApi.class).to(DefaultChargeThruApi.class).asEagerSingleton();
     }
 
     @Override
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
index 20409ee..c422587 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
@@ -26,21 +26,18 @@ import java.net.URL;
 import java.util.List;
 import java.util.UUID;
 
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.TestCallContext;
+import javax.annotation.Nullable;
+
 import org.apache.commons.io.IOUtils;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
-import org.testng.ITestResult;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.AfterMethod;
-import org.testng.annotations.AfterSuite;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.BeforeSuite;
 
 import com.google.inject.Injector;
 import com.ning.billing.account.api.AccountData;
@@ -57,7 +54,7 @@ import com.ning.billing.catalog.api.TimeUnit;
 import com.ning.billing.config.EntitlementConfig;
 import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
+import com.ning.billing.entitlement.api.billing.ChargeThruApi;
 import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
@@ -72,13 +69,12 @@ import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.entitlement.events.phase.PhaseEvent;
 import com.ning.billing.entitlement.events.user.ApiEvent;
 import com.ning.billing.entitlement.events.user.ApiEventType;
+import com.ning.billing.util.bus.BusService;
+import com.ning.billing.util.bus.DefaultBusService;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.TestCallContext;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.clock.ClockMock;
-import com.ning.billing.util.bus.Bus.EventBusException;
-import com.ning.billing.util.bus.DefaultBusService;
-import com.ning.billing.util.bus.BusService;
-
-import javax.annotation.Nullable;
 
 
 public abstract class TestApiBase {
@@ -88,7 +84,7 @@ public abstract class TestApiBase {
 
     protected EntitlementService entitlementService;
     protected EntitlementUserApi entitlementApi;
-    protected EntitlementBillingApi billingApi;
+    protected ChargeThruApi billingApi;
 
     protected EntitlementMigrationApi migrationApi;
 

invoice/pom.xml 12(+12 -0)

diff --git a/invoice/pom.xml b/invoice/pom.xml
index 8db3258..552b41d 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -52,6 +52,18 @@
         </dependency>
         <dependency>
             <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-junction</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-junction</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        
+        <dependency>
+            <groupId>com.ning.billing</groupId>
             <artifactId>killbill-catalog</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
index f6ba4a5..9572e57 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
@@ -24,14 +24,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
-import com.ning.billing.util.ChangeType;
-import com.ning.billing.util.audit.dao.AuditSqlDao;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.customfield.CustomField;
-import com.ning.billing.util.customfield.dao.CustomFieldSqlDao;
-import com.ning.billing.util.tag.ControlTagType;
-import com.ning.billing.util.tag.Tag;
-import com.ning.billing.util.tag.dao.TagDao;
 import org.joda.time.DateTime;
 import org.skife.jdbi.v2.IDBI;
 import org.skife.jdbi.v2.Transaction;
@@ -41,7 +33,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.inject.Inject;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceCreationEvent;
 import com.ning.billing.invoice.api.InvoiceItem;
@@ -50,14 +41,23 @@ import com.ning.billing.invoice.api.user.DefaultInvoiceCreationNotification;
 import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
 import com.ning.billing.invoice.model.RecurringInvoiceItem;
 import com.ning.billing.invoice.notification.NextBillingDatePoster;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.util.ChangeType;
+import com.ning.billing.util.audit.dao.AuditSqlDao;
 import com.ning.billing.util.bus.Bus;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.customfield.CustomField;
+import com.ning.billing.util.customfield.dao.CustomFieldSqlDao;
+import com.ning.billing.util.tag.ControlTagType;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.dao.TagDao;
 
 public class DefaultInvoiceDao implements InvoiceDao {
     private final static Logger log = LoggerFactory.getLogger(DefaultInvoiceDao.class);
 
     private final InvoiceSqlDao invoiceSqlDao;
     private final InvoicePaymentSqlDao invoicePaymentSqlDao;
-    private final EntitlementBillingApi entitlementBillingApi;
+    private final BillingApi billingApi;
     private final TagDao tagDao;
 
     private final Bus eventBus;
@@ -66,13 +66,13 @@ public class DefaultInvoiceDao implements InvoiceDao {
 
     @Inject
     public DefaultInvoiceDao(final IDBI dbi, final Bus eventBus,
-                             final EntitlementBillingApi entitlementBillingApi,
+                             final BillingApi entitlementBillingApi,
                              final NextBillingDatePoster nextBillingDatePoster,
                              final TagDao tagDao) {
         this.invoiceSqlDao = dbi.onDemand(InvoiceSqlDao.class);
         this.invoicePaymentSqlDao = dbi.onDemand(InvoicePaymentSqlDao.class);
         this.eventBus = eventBus;
-        this.entitlementBillingApi = entitlementBillingApi;
+        this.billingApi = entitlementBillingApi;
         this.nextBillingDatePoster = nextBillingDatePoster;
         this.tagDao = tagDao;
     }
@@ -387,7 +387,7 @@ public class DefaultInvoiceDao implements InvoiceDao {
             if(subscriptionId != null) {
                 DateTime chargeThroughDate = chargeThroughDates.get(subscriptionId);
                 log.info("Setting CTD for subscription {} to {}", subscriptionId.toString(), chargeThroughDate.toString());
-                entitlementBillingApi.setChargedThroughDateFromTransaction(dao, subscriptionId, chargeThroughDate, context);
+                billingApi.setChargedThroughDateFromTransaction(dao, subscriptionId, chargeThroughDate, context);
             }
         }
     }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java b/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
index 043c670..870e7c5 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
@@ -21,12 +21,6 @@ import java.util.List;
 import java.util.SortedSet;
 import java.util.UUID;
 
-import com.ning.billing.util.bus.Bus;
-import com.ning.billing.util.bus.Bus.EventBusException;
-import com.ning.billing.util.bus.BusEvent;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.clock.Clock;
-
 import org.joda.time.DateTime;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -37,7 +31,6 @@ import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
 import com.ning.billing.entitlement.api.user.SubscriptionEventTransition;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
@@ -46,17 +39,23 @@ import com.ning.billing.invoice.api.user.DefaultEmptyInvoiceNotification;
 import com.ning.billing.invoice.dao.InvoiceDao;
 import com.ning.billing.invoice.model.BillingEventSet;
 import com.ning.billing.invoice.model.InvoiceGenerator;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.util.bus.Bus;
+import com.ning.billing.util.bus.Bus.EventBusException;
+import com.ning.billing.util.bus.BusEvent;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.globallocker.GlobalLock;
 import com.ning.billing.util.globallocker.GlobalLocker;
-import com.ning.billing.util.globallocker.LockFailedException;
 import com.ning.billing.util.globallocker.GlobalLocker.LockerService;
+import com.ning.billing.util.globallocker.LockFailedException;
 
 public class InvoiceDispatcher {
 	private final static Logger log = LoggerFactory.getLogger(InvoiceDispatcher.class);
     private final static int NB_LOCK_TRY = 5;
 
     private final InvoiceGenerator generator;
-    private final EntitlementBillingApi entitlementBillingApi;
+    private final BillingApi billingApi;
     private final AccountUserApi accountUserApi;
     private final InvoiceDao invoiceDao;
     private final GlobalLocker locker;
@@ -67,13 +66,13 @@ public class InvoiceDispatcher {
 
     @Inject
     public InvoiceDispatcher(final InvoiceGenerator generator, final AccountUserApi accountUserApi,
-                             final EntitlementBillingApi entitlementBillingApi,
+                             final BillingApi billingApi,
                              final InvoiceDao invoiceDao,
                              final GlobalLocker locker,
                              final Bus eventBus,
                              final Clock clock) {
         this.generator = generator;
-        this.entitlementBillingApi = entitlementBillingApi;
+        this.billingApi = billingApi;
         this.accountUserApi = accountUserApi;
         this.invoiceDao = invoiceDao;
         this.locker = locker;
@@ -100,7 +99,7 @@ public class InvoiceDispatcher {
             return;
         }
 
-        UUID accountId = entitlementBillingApi.getAccountIdFromSubscriptionId(subscriptionId);
+        UUID accountId = billingApi.getAccountIdFromSubscriptionId(subscriptionId);
         if (accountId == null) {
             log.error("Failed handling entitlement change.",
                     new InvoiceApiException(ErrorCode.INVOICE_NO_ACCOUNT_ID_FOR_SUBSCRIPTION_ID, subscriptionId.toString()));
@@ -148,7 +147,7 @@ public class InvoiceDispatcher {
             return null;    
         }
 
-        SortedSet<BillingEvent> events = entitlementBillingApi.getBillingEventsForAccountAndUpdateAccountBCD(accountId);
+        SortedSet<BillingEvent> events = billingApi.getBillingEventsForAccountAndUpdateAccountBCD(accountId);
         BillingEventSet billingEvents = new BillingEventSet(events);
 
         Currency targetCurrency = account.getCurrency();
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/migration/MockModuleNoEntitlement.java b/invoice/src/test/java/com/ning/billing/invoice/api/migration/MockModuleNoEntitlement.java
index 300313c..28077d2 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/migration/MockModuleNoEntitlement.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/migration/MockModuleNoEntitlement.java
@@ -16,14 +16,13 @@
 
 package com.ning.billing.invoice.api.migration;
 
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
-import com.ning.billing.entitlement.engine.dao.EntitlementDao;
+import com.ning.billing.entitlement.api.billing.ChargeThruApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.invoice.MockModule;
 import com.ning.billing.invoice.glue.InvoiceModule;
-import com.ning.billing.invoice.notification.DefaultNextBillingDateNotifier;
-import com.ning.billing.invoice.notification.DefaultNextBillingDatePoster;
 import com.ning.billing.invoice.notification.NextBillingDateNotifier;
 import com.ning.billing.invoice.notification.NextBillingDatePoster;
+import com.ning.billing.junction.api.BillingApi;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
 
@@ -31,12 +30,14 @@ public class MockModuleNoEntitlement extends MockModule {
 
 	@Override
 	protected void installEntitlementModule() {
-		EntitlementBillingApi entitlementApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementBillingApi.class);
+		BillingApi entitlementApi = BrainDeadProxyFactory.createBrainDeadProxyFor(BillingApi.class);
         ((ZombieControl)entitlementApi).addResult("setChargedThroughDateFromTransaction", BrainDeadProxyFactory.ZOMBIE_VOID);
         ((ZombieControl)entitlementApi).addResult("getBillingEventsForAccountAndUpdateAccountBCD", BrainDeadProxyFactory.ZOMBIE_VOID);
-		bind(EntitlementBillingApi.class).toInstance(entitlementApi);
-		bind(EntitlementDao.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementDao.class));
-
+		//bind(BillingApi.class).toInstance(entitlementApi);
+        bind(EntitlementUserApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementUserApi.class));
+        ChargeThruApi cta = BrainDeadProxyFactory.createBrainDeadProxyFor(ChargeThruApi.class);
+        bind(ChargeThruApi.class).toInstance(cta);
+        ((ZombieControl)cta).addResult("setChargedThroughDateFromTransaction", BrainDeadProxyFactory.ZOMBIE_VOID);
 	}
 
 	@Override
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java b/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
index 3aee83d..5dce59b 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/migration/TestDefaultInvoiceMigrationApi.java
@@ -23,11 +23,6 @@ import java.util.SortedSet;
 import java.util.TreeSet;
 import java.util.UUID;
 
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.CallOrigin;
-import com.ning.billing.util.callcontext.UserType;
-import com.ning.billing.util.callcontext.DefaultCallContextFactory;
-import com.ning.billing.util.clock.Clock;
 import org.apache.commons.io.IOUtils;
 import org.joda.time.DateTime;
 import org.slf4j.Logger;
@@ -50,8 +45,6 @@ import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
 import com.ning.billing.entitlement.api.billing.BillingModeType;
-import com.ning.billing.entitlement.api.billing.DefaultBillingEvent;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionEventTransition.SubscriptionTransitionType;
 import com.ning.billing.invoice.InvoiceDispatcher;
@@ -62,10 +55,17 @@ import com.ning.billing.invoice.api.InvoicePaymentApi;
 import com.ning.billing.invoice.api.InvoiceUserApi;
 import com.ning.billing.invoice.dao.InvoiceDao;
 import com.ning.billing.invoice.model.InvoiceGenerator;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingEvent;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
 import com.ning.billing.util.bus.BusService;
 import com.ning.billing.util.bus.DefaultBusService;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.clock.ClockMock;
 import com.ning.billing.util.globallocker.GlobalLocker;
 
@@ -183,7 +183,7 @@ public class TestDefaultInvoiceMigrationApi {
 				fixedPrice, BigDecimal.ONE, currency, BillingPeriod.MONTHLY, 1,
 				BillingModeType.IN_ADVANCE, "", 1L, SubscriptionTransitionType.CREATE));
 
-		EntitlementBillingApi entitlementBillingApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementBillingApi.class);
+		BillingApi entitlementBillingApi = BrainDeadProxyFactory.createBrainDeadProxyFor(BillingApi.class);
         ((ZombieControl)entitlementBillingApi).addResult("getBillingEventsForAccountAndUpdateAccountBCD", events);
 		InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountUserApi, entitlementBillingApi, invoiceDao, locker, busService.getBus(), clock);
 
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/MockInvoicePaymentApi.java b/invoice/src/test/java/com/ning/billing/invoice/api/MockInvoicePaymentApi.java
index 3a00c1b..09b809c 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/MockInvoicePaymentApi.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/MockInvoicePaymentApi.java
@@ -22,11 +22,11 @@ import java.util.List;
 import java.util.UUID;
 import java.util.concurrent.CopyOnWriteArrayList;
 
-import com.ning.billing.util.callcontext.CallContext;
 import org.joda.time.DateTime;
 
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.model.DefaultInvoicePayment;
+import com.ning.billing.util.callcontext.CallContext;
 
 public class MockInvoicePaymentApi implements InvoicePaymentApi
 {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java
index fbb77dd..a6980bc 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java
@@ -71,10 +71,12 @@ public abstract class InvoiceDaoTestBase extends InvoicingTestBase {
             module = new InvoiceModuleWithEmbeddedDb();
             final String invoiceDdl = IOUtils.toString(DefaultInvoiceDao.class.getResourceAsStream("/com/ning/billing/invoice/ddl.sql"));
             final String entitlementDdl = IOUtils.toString(DefaultInvoiceDao.class.getResourceAsStream("/com/ning/billing/entitlement/ddl.sql"));
+            final String utilDdl = IOUtils.toString(DefaultInvoiceDao.class.getResourceAsStream("/com/ning/billing/util/ddl.sql"));
 
             module.startDb();
             module.initDb(invoiceDdl);
             module.initDb(entitlementDdl);
+            module.initDb(utilDdl);
 
             final Injector injector = Guice.createInjector(Stage.DEVELOPMENT, module);
 
@@ -101,7 +103,7 @@ public abstract class InvoiceDaoTestBase extends InvoicingTestBase {
             @Override
             public Void inTransaction(Handle h, TransactionStatus status)
                     throws Exception {
-                h.execute("truncate table accounts");
+                //h.execute("truncate table accounts");
                 //h.execute("truncate table entitlement_events");
                 //h.execute("truncate table subscriptions");
                 //h.execute("truncate table bundles");
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
index a3b8888..7506f20 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
@@ -16,6 +16,21 @@
 
 package com.ning.billing.invoice.dao;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.testng.annotations.Test;
+
 import com.ning.billing.catalog.DefaultPrice;
 import com.ning.billing.catalog.MockInternationalPrice;
 import com.ning.billing.catalog.MockPlan;
@@ -28,7 +43,6 @@ import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
 import com.ning.billing.entitlement.api.billing.BillingModeType;
-import com.ning.billing.entitlement.api.billing.DefaultBillingEvent;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionEventTransition.SubscriptionTransitionType;
 import com.ning.billing.invoice.api.Invoice;
@@ -39,23 +53,10 @@ import com.ning.billing.invoice.model.BillingEventSet;
 import com.ning.billing.invoice.model.DefaultInvoice;
 import com.ning.billing.invoice.model.DefaultInvoicePayment;
 import com.ning.billing.invoice.model.RecurringInvoiceItem;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingEvent;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
 import com.ning.billing.util.tag.ControlTagType;
-import org.joda.time.DateTime;
-import org.testng.annotations.Test;
-
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.UUID;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
 
 @Test(groups = {"invoicing", "invoicing-invoiceDao"})
 public class InvoiceDaoTests extends InvoiceDaoTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java
index 7ada46c..9acde8e 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java
@@ -16,19 +16,20 @@
 
 package com.ning.billing.invoice.dao;
 
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.invoice.api.InvoiceItem;
-import com.ning.billing.invoice.model.DefaultInvoice;
-import com.ning.billing.invoice.model.RecurringInvoiceItem;
-import org.joda.time.DateTime;
-import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
 
 import java.math.BigDecimal;
 import java.util.List;
 import java.util.UUID;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
+import org.joda.time.DateTime;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.model.DefaultInvoice;
+import com.ning.billing.invoice.model.RecurringInvoiceItem;
 
 @Test(groups = {"invoicing", "invoicing-invoiceDao"})
 public class InvoiceItemDaoTests extends InvoiceDaoTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
index c7818d8..c733442 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
@@ -23,16 +23,16 @@ import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
-import com.ning.billing.invoice.api.InvoicePayment;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.bus.Bus;
-import com.ning.billing.util.tag.ControlTagType;
 import org.joda.time.DateTime;
 
 import com.google.inject.Inject;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.InvoicePayment;
 import com.ning.billing.invoice.api.user.DefaultInvoiceCreationNotification;
+import com.ning.billing.util.bus.Bus;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.tag.ControlTagType;
 
 public class MockInvoiceDao implements InvoiceDao {
     private final Bus eventBus;
diff --git a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java
index 368b74f..1bf9586 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithEmbeddedDb.java
@@ -35,6 +35,7 @@ import com.ning.billing.invoice.notification.MockNextBillingDateNotifier;
 import com.ning.billing.invoice.notification.MockNextBillingDatePoster;
 import com.ning.billing.invoice.notification.NextBillingDateNotifier;
 import com.ning.billing.invoice.notification.NextBillingDatePoster;
+import com.ning.billing.junction.api.BillingApi;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.util.callcontext.CallContextFactory;
 import com.ning.billing.util.callcontext.DefaultCallContextFactory;
@@ -100,6 +101,7 @@ public class InvoiceModuleWithEmbeddedDb extends InvoiceModule {
         installNotificationQueue();
 //      install(new AccountModule());
         bind(AccountUserApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class));
+        bind(BillingApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(BillingApi.class));
         install(new CatalogModule());
         install(new EntitlementModule());
         install(new GlobalLockerModule());
diff --git a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithMocks.java b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithMocks.java
index fe4feb4..a6366b8 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithMocks.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleWithMocks.java
@@ -20,10 +20,7 @@ import com.ning.billing.invoice.dao.InvoiceDao;
 import com.ning.billing.invoice.dao.MockInvoiceDao;
 import com.ning.billing.util.globallocker.GlobalLocker;
 import com.ning.billing.util.globallocker.MockGlobalLocker;
-import com.ning.billing.util.glue.CallContextModule;
 import com.ning.billing.util.glue.FieldStoreModule;
-import com.ning.billing.util.glue.TagStoreModule;
-import org.skife.jdbi.v2.Call;
 
 
 public class InvoiceModuleWithMocks extends InvoiceModule {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/MockModule.java b/invoice/src/test/java/com/ning/billing/invoice/MockModule.java
index c062a06..5345ac9 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/MockModule.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/MockModule.java
@@ -25,9 +25,12 @@ import com.ning.billing.catalog.glue.CatalogModule;
 import com.ning.billing.dbi.DBIProvider;
 import com.ning.billing.dbi.DbiConfig;
 import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.entitlement.api.billing.ChargeThruApi;
 import com.ning.billing.entitlement.glue.EntitlementModule;
 import com.ning.billing.invoice.glue.InvoiceModule;
+import com.ning.billing.junction.glue.JunctionModule;
 import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
 import com.ning.billing.util.callcontext.CallContextFactory;
 import com.ning.billing.util.callcontext.DefaultCallContextFactory;
 import com.ning.billing.util.clock.Clock;
@@ -63,14 +66,12 @@ public class MockModule extends AbstractModule {
 
         install(new GlobalLockerModule());
         install(new NotificationQueueModule());
-//        install(new AccountModule());
         bind(AccountUserApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class));
-
         installEntitlementModule();
         install(new CatalogModule());
         install(new BusModule());
         installInvoiceModule();
-
+        install(new JunctionModule());
     }
     
     protected void installEntitlementModule() {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/notification/MockNextBillingDatePoster.java b/invoice/src/test/java/com/ning/billing/invoice/notification/MockNextBillingDatePoster.java
index 493ba5d..88ff62a 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/notification/MockNextBillingDatePoster.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/notification/MockNextBillingDatePoster.java
@@ -16,11 +16,11 @@
 
 package com.ning.billing.invoice.notification;
 
+import java.util.UUID;
+
 import org.joda.time.DateTime;
 import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
 
-import java.util.UUID;
-
 public class MockNextBillingDatePoster implements NextBillingDatePoster {
     @Override
     public void insertNextBillingNotification(Transmogrifier transactionalDao, UUID subscriptionId, DateTime futureNotificationTime) {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java b/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java
index e70626f..a804bff 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java
@@ -46,12 +46,10 @@ import com.ning.billing.catalog.api.CatalogService;
 import com.ning.billing.config.CatalogConfig;
 import com.ning.billing.config.InvoiceConfig;
 import com.ning.billing.dbi.MysqlTestingHelper;
-import com.ning.billing.entitlement.api.billing.DefaultEntitlementBillingApi;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
+import com.ning.billing.entitlement.api.billing.ChargeThruApi;
 import com.ning.billing.entitlement.api.user.DefaultEntitlementUserApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
 import com.ning.billing.entitlement.engine.dao.EntitlementSqlDao;
 import com.ning.billing.invoice.InvoiceDispatcher;
@@ -60,6 +58,8 @@ import com.ning.billing.invoice.dao.DefaultInvoiceDao;
 import com.ning.billing.invoice.dao.InvoiceDao;
 import com.ning.billing.invoice.model.DefaultInvoiceGenerator;
 import com.ning.billing.invoice.model.InvoiceGenerator;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingApi;
 import com.ning.billing.lifecycle.KillbillService.ServiceException;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
@@ -142,8 +142,9 @@ public class TestNextBillingDateNotifier {
                 bind(InvoiceDao.class).to(DefaultInvoiceDao.class);
                 bind(NextBillingDatePoster.class).to(DefaultNextBillingDatePoster.class).asEagerSingleton();
                 bind(AccountUserApi.class).to(MockAccountUserApi.class).asEagerSingleton();
-                bind(EntitlementBillingApi.class).to(DefaultEntitlementBillingApi.class).asEagerSingleton();
+                bind(BillingApi.class).to(DefaultBillingApi.class).asEagerSingleton();
                 bind(EntitlementUserApi.class).to(DefaultEntitlementUserApi.class).asEagerSingleton();
+                bind(ChargeThruApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(ChargeThruApi.class));
             }
         });
 
@@ -214,8 +215,9 @@ public class TestNextBillingDateNotifier {
 		Assert.assertEquals(listener.getLatestSubscriptionId(), subscriptionId);
 	}
 
-	@AfterClass(alwaysRun = true)
+	@AfterClass(groups="slow")
     public void tearDown() {
+	    notifier.stop();
     	helper.stopMysql();
     }
 
diff --git a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
index 45f1db4..175267d 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
@@ -45,8 +45,6 @@ import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
 import com.ning.billing.entitlement.api.billing.BillingModeType;
-import com.ning.billing.entitlement.api.billing.DefaultBillingEvent;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionEventTransition.SubscriptionTransitionType;
 import com.ning.billing.invoice.api.Invoice;
@@ -54,6 +52,9 @@ import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.dao.InvoiceDao;
 import com.ning.billing.invoice.model.InvoiceGenerator;
 import com.ning.billing.invoice.notification.NextBillingDateNotifier;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.junction.glue.JunctionModule;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingEvent;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
 import com.ning.billing.util.bus.BusService;
@@ -149,7 +150,7 @@ public class TestInvoiceDispatcher {
 				fixedPrice, BigDecimal.ONE, currency, BillingPeriod.MONTHLY, 1,
 				BillingModeType.IN_ADVANCE, "", 1L, SubscriptionTransitionType.CREATE));
 
-		EntitlementBillingApi entitlementBillingApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementBillingApi.class);
+		BillingApi entitlementBillingApi = BrainDeadProxyFactory.createBrainDeadProxyFor(BillingApi.class);
 		((ZombieControl)entitlementBillingApi).addResult("getBillingEventsForAccountAndUpdateAccountBCD", events);
 
 		DateTime target = new DateTime();
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
index 1be0585..3e9c99f 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
@@ -16,6 +16,20 @@
 
 package com.ning.billing.invoice.tests;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import org.joda.time.DateTime;
+import org.testng.annotations.Test;
+
 import com.ning.billing.catalog.DefaultPrice;
 import com.ning.billing.catalog.MockInternationalPrice;
 import com.ning.billing.catalog.MockPlan;
@@ -29,11 +43,10 @@ import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.config.InvoiceConfig;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
 import com.ning.billing.entitlement.api.billing.BillingModeType;
-import com.ning.billing.entitlement.api.billing.DefaultBillingEvent;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
-import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
 import com.ning.billing.entitlement.api.user.SubscriptionEventTransition.SubscriptionTransitionType;
+import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.model.BillingEventSet;
@@ -41,23 +54,11 @@ import com.ning.billing.invoice.model.DefaultInvoiceGenerator;
 import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
 import com.ning.billing.invoice.model.InvoiceGenerator;
 import com.ning.billing.invoice.model.RecurringInvoiceItem;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingEvent;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
-
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.clock.DefaultClock;
-import org.joda.time.DateTime;
-import org.testng.annotations.Test;
-
-import javax.annotation.Nullable;
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
 
 @Test(groups = {"fast", "invoicing", "invoiceGenerator"})
 public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
@@ -632,7 +633,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         assertNotNull(invoice2);
         assertEquals(invoice2.getNumberOfItems(), 1);
         assertEquals(invoice2.getInvoiceItems().get(0).getStartDate().compareTo(trialPhaseEndDate), 0);
-        assertEquals(invoice2.getTotalAmount().compareTo(new BigDecimal("3.2097")), 0);
+        assertEquals(invoice2.getTotalAmount().compareTo(new BigDecimal("3.21")), 0);
 
         invoiceList.add(invoice2);
         DateTime targetDate = trialPhaseEndDate.toMutableDateTime().dayOfMonth().set(BILL_CYCLE_DAY).toDateTime();
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/DoubleProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/DoubleProRationTests.java
index fd37599..c08c8b8 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/DoubleProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/DoubleProRationTests.java
@@ -16,13 +16,14 @@
 
 package com.ning.billing.invoice.tests.inAdvance.annual;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class DoubleProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/GenericProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/GenericProRationTests.java
index 8d0eb06..81d5347 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/GenericProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/GenericProRationTests.java
@@ -16,11 +16,12 @@
 
 package com.ning.billing.invoice.tests.inAdvance.annual;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.tests.inAdvance.GenericProRationTestBase;
+import java.math.BigDecimal;
+
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.tests.inAdvance.GenericProRationTestBase;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class GenericProRationTests extends GenericProRationTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/LeadingProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/LeadingProRationTests.java
index a009fba..68611f7 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/LeadingProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/LeadingProRationTests.java
@@ -16,13 +16,14 @@
 
 package com.ning.billing.invoice.tests.inAdvance.annual;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class LeadingProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/ProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/ProRationTests.java
index f882005..88922e2 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/ProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/ProRationTests.java
@@ -16,13 +16,14 @@
 
 package com.ning.billing.invoice.tests.inAdvance.annual;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class ProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/TrailingProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/TrailingProRationTests.java
index e0216b5..d1c2013 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/TrailingProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/annual/TrailingProRationTests.java
@@ -16,13 +16,14 @@
 
 package com.ning.billing.invoice.tests.inAdvance.annual;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class TrailingProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/GenericProRationTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/GenericProRationTestBase.java
index 60892e6..70f1f8f 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/GenericProRationTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/GenericProRationTestBase.java
@@ -16,11 +16,12 @@
 
 package com.ning.billing.invoice.tests.inAdvance;
 
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import java.math.BigDecimal;
+
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public abstract class GenericProRationTestBase extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/DoubleProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/DoubleProRationTests.java
index 240b8aa..8c9b61d 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/DoubleProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/DoubleProRationTests.java
@@ -16,13 +16,14 @@
 
 package com.ning.billing.invoice.tests.inAdvance.monthly;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class DoubleProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/GenericProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/GenericProRationTests.java
index 8b40db8..b749ab8 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/GenericProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/GenericProRationTests.java
@@ -16,11 +16,12 @@
 
 package com.ning.billing.invoice.tests.inAdvance.monthly;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.tests.inAdvance.GenericProRationTestBase;
+import java.math.BigDecimal;
+
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.tests.inAdvance.GenericProRationTestBase;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class GenericProRationTests extends GenericProRationTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/LeadingProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/LeadingProRationTests.java
index 998e566..f723738 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/LeadingProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/LeadingProRationTests.java
@@ -16,13 +16,14 @@
 
 package com.ning.billing.invoice.tests.inAdvance.monthly;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class LeadingProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/ProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/ProRationTests.java
index c3748d1..8d564c8 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/ProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/ProRationTests.java
@@ -16,13 +16,14 @@
 
 package com.ning.billing.invoice.tests.inAdvance.monthly;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class ProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/TrailingProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/TrailingProRationTests.java
index 6a5e5ef..581e8af 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/TrailingProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/monthly/TrailingProRationTests.java
@@ -16,13 +16,14 @@
 
 package com.ning.billing.invoice.tests.inAdvance.monthly;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class TrailingProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ProRationInAdvanceTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ProRationInAdvanceTestBase.java
index 18bd096..b8f3848 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ProRationInAdvanceTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ProRationInAdvanceTestBase.java
@@ -16,10 +16,11 @@
 
 package com.ning.billing.invoice.tests.inAdvance;
 
+import org.testng.annotations.Test;
+
 import com.ning.billing.invoice.model.BillingMode;
 import com.ning.billing.invoice.model.InAdvanceBillingMode;
 import com.ning.billing.invoice.tests.ProRationTestBase;
-import org.testng.annotations.Test;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public abstract class ProRationInAdvanceTestBase extends ProRationTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/DoubleProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/DoubleProRationTests.java
index 184f5d5..e6c3cf3 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/DoubleProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/DoubleProRationTests.java
@@ -16,13 +16,14 @@
 
 package com.ning.billing.invoice.tests.inAdvance.quarterly;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class DoubleProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/GenericProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/GenericProRationTests.java
index c4237a6..3351807 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/GenericProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/GenericProRationTests.java
@@ -16,11 +16,12 @@
 
 package com.ning.billing.invoice.tests.inAdvance.quarterly;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.tests.inAdvance.GenericProRationTestBase;
+import java.math.BigDecimal;
+
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.tests.inAdvance.GenericProRationTestBase;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class GenericProRationTests extends GenericProRationTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/LeadingProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/LeadingProRationTests.java
index 04ec683..18bb8af 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/LeadingProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/LeadingProRationTests.java
@@ -16,13 +16,14 @@
 
 package com.ning.billing.invoice.tests.inAdvance.quarterly;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class LeadingProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/ProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/ProRationTests.java
index e13db0d..2988dfe 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/ProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/ProRationTests.java
@@ -16,13 +16,14 @@
 
 package com.ning.billing.invoice.tests.inAdvance.quarterly;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class ProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/TrailingProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/TrailingProRationTests.java
index 8f63010..270518d 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/TrailingProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/quarterly/TrailingProRationTests.java
@@ -16,13 +16,14 @@
 
 package com.ning.billing.invoice.tests.inAdvance.quarterly;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
+import java.math.BigDecimal;
+
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
-import java.math.BigDecimal;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.tests.inAdvance.ProRationInAdvanceTestBase;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class TrailingProRationTests extends ProRationInAdvanceTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ValidationProRationTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ValidationProRationTests.java
index bd8a38d..21dd092 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ValidationProRationTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/inAdvance/ValidationProRationTests.java
@@ -16,17 +16,18 @@
 
 package com.ning.billing.invoice.tests.inAdvance;
 
+import static org.testng.Assert.assertEquals;
+
+import java.math.BigDecimal;
+
+import org.joda.time.DateTime;
+import org.testng.annotations.Test;
+
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.invoice.model.BillingMode;
 import com.ning.billing.invoice.model.InAdvanceBillingMode;
 import com.ning.billing.invoice.model.InvalidDateSequenceException;
 import com.ning.billing.invoice.tests.ProRationTestBase;
-import org.joda.time.DateTime;
-import org.testng.annotations.Test;
-
-import java.math.BigDecimal;
-
-import static org.testng.Assert.assertEquals;
 
 @Test(groups = {"fast", "invoicing", "proRation"})
 public class ValidationProRationTests extends ProRationTestBase {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/InvoicingTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/tests/InvoicingTestBase.java
index 4b47237..50f1b23 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/InvoicingTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/InvoicingTestBase.java
@@ -16,10 +16,11 @@
 
 package com.ning.billing.invoice.tests;
 
-import com.ning.billing.invoice.model.InvoicingConfiguration;
+import java.math.BigDecimal;
+
 import org.joda.time.DateTime;
 
-import java.math.BigDecimal;
+import com.ning.billing.invoice.model.InvoicingConfiguration;
 
 public abstract class InvoicingTestBase {
     protected static final int NUMBER_OF_DECIMALS = InvoicingConfiguration.getNumberOfDecimals();
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java
index 122b13b..1cd4e2f 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java
@@ -16,17 +16,18 @@
 
 package com.ning.billing.invoice.tests;
 
-import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.invoice.model.BillingMode;
-import com.ning.billing.invoice.model.InvalidDateSequenceException;
-import com.ning.billing.invoice.model.RecurringInvoiceItemData;
-import org.joda.time.DateTime;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
 
 import java.math.BigDecimal;
 import java.util.List;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.fail;
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.invoice.model.BillingMode;
+import com.ning.billing.invoice.model.InvalidDateSequenceException;
+import com.ning.billing.invoice.model.RecurringInvoiceItemData;
 
 public abstract class ProRationTestBase extends InvoicingTestBase {
     protected abstract BillingMode getBillingMode();

junction/pom.xml 11(+11 -0)

diff --git a/junction/pom.xml b/junction/pom.xml
index 1d89f86..b5dfd03 100644
--- a/junction/pom.xml
+++ b/junction/pom.xml
@@ -73,6 +73,17 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-entitlement</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-entitlement</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
             <scope>runtime</scope>
diff --git a/junction/src/main/java/com/ning/billing/junction/api/blocking/DefaultBlockingApi.java b/junction/src/main/java/com/ning/billing/junction/api/blocking/DefaultBlockingApi.java
index 4c93fbe..02b3b41 100644
--- a/junction/src/main/java/com/ning/billing/junction/api/blocking/DefaultBlockingApi.java
+++ b/junction/src/main/java/com/ning/billing/junction/api/blocking/DefaultBlockingApi.java
@@ -38,13 +38,13 @@ public class DefaultBlockingApi implements BlockingApi {
     }
     
     @Override
-    public String getBlockingStateNameFor(Blockable overdueable) {
+    public BlockingState getBlockingStateFor(Blockable overdueable) {
         return dao.getBlockingStateFor(overdueable);
     }
 
     @Override
-    public String getBlockingStateNameFor(UUID overdueableId, Type type) {
-        return dao.getBlockingStateForIdAndType(overdueableId, type);
+    public BlockingState getBlockingStateFor(UUID overdueableId, Type type) {
+        return dao.getBlockingStateFor(overdueableId, type);
     }
 
     @Override
diff --git a/junction/src/main/java/com/ning/billing/junction/block/BlockingChecker.java b/junction/src/main/java/com/ning/billing/junction/block/BlockingChecker.java
index f20b4e0..a6ab7da 100644
--- a/junction/src/main/java/com/ning/billing/junction/block/BlockingChecker.java
+++ b/junction/src/main/java/com/ning/billing/junction/block/BlockingChecker.java
@@ -16,13 +16,29 @@
 
 package com.ning.billing.junction.block;
 
-import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
+import com.ning.billing.account.api.Account;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.api.BlockingApiException;
 
 public interface BlockingChecker {
 
-    public void checkBlocked(Subscription subscription)  throws EntitlementUserApiException;
+    public void checkBlockedChange(Subscription subscription)  throws BlockingApiException;
+
+    public void checkBlockedChange(SubscriptionBundle bundle) throws BlockingApiException;
+
+    public void checkBlockedChange(Account account) throws BlockingApiException;
+
+    public void checkBlockedEntitlement(Subscription subscription)  throws BlockingApiException;
+
+    public void checkBlockedEntitlement(SubscriptionBundle bundle) throws BlockingApiException;
+
+    public void checkBlockedEntitlement(Account account) throws BlockingApiException;
+
+    public void checkBlockedBilling(Subscription subscription)  throws BlockingApiException;
+
+    public void checkBlockedBilling(SubscriptionBundle bundleId) throws BlockingApiException;
+
+    public void checkBlockedBilling(Account account) throws BlockingApiException;
 
-    public void checkBlocked(SubscriptionBundle bundle) throws EntitlementUserApiException;
 }
diff --git a/junction/src/main/java/com/ning/billing/junction/block/DefaultBlockingChecker.java b/junction/src/main/java/com/ning/billing/junction/block/DefaultBlockingChecker.java
index ff4b009..1f65391 100644
--- a/junction/src/main/java/com/ning/billing/junction/block/DefaultBlockingChecker.java
+++ b/junction/src/main/java/com/ning/billing/junction/block/DefaultBlockingChecker.java
@@ -16,40 +16,180 @@
 
 package com.ning.billing.junction.block;
 
+import java.util.UUID;
+
 import com.google.inject.Inject;
 import com.ning.billing.ErrorCode;
-import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.account.api.Account;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
-import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
-import com.ning.billing.junction.api.BlockingApi;
-import com.ning.billing.overdue.OverdueState;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.BlockingApiException;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.junction.dao.BlockingStateDao;
 
 public class DefaultBlockingChecker implements BlockingChecker {
+    
+    private static class BlockingAggregator {
+        private boolean blockChange = false;
+        private boolean blockEntitlement= false;
+        private boolean blockBilling = false;
+
+        public void or(BlockingState state) {
+            if (state == null) { return; }
+            blockChange = blockChange || state.isBlockChange();
+            blockEntitlement = blockEntitlement || state.isBlockEntitlement();
+            blockBilling = blockBilling || state.isBlockBilling();
+        }
+        
+        public void or(BlockingAggregator state) {
+            if (state == null) { return; }
+            blockChange = blockChange || state.isBlockChange();
+            blockEntitlement = blockEntitlement || state.isBlockEntitlement();
+            blockBilling = blockBilling || state.isBlockBilling();
+        }
+        
+        public boolean isBlockChange() {
+            return blockChange;
+        }
+        public boolean isBlockEntitlement() {
+            return blockEntitlement;
+        }
+        public boolean isBlockBilling() {
+            return blockBilling;
+        }
+       
+    }
+
+    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 ACTION_CHANGE = "Change";
+    private static final Object ACTION_ENTITLEMENT = "Entitlement";
+    private static final Object ACTION_BILLING = "Billing";
 
     private final EntitlementUserApi entitlementApi;
+    private final BlockingStateDao dao;
 
     @Inject
-    public DefaultBlockingChecker(EntitlementUserApi entitlementApi, BlockingApi overdueApi) {
+    public DefaultBlockingChecker(EntitlementUserApi entitlementApi, BlockingStateDao dao) {
         this.entitlementApi = entitlementApi;
+        this.dao = dao;
+    }
+
+    public BlockingAggregator getBlockedStateSubscriptionId(UUID subscriptionId)  {
+       Subscription subscription = entitlementApi.getSubscriptionFromId(subscriptionId);
+       return getBlockedStateSubscription(subscription);
+    }
+    
+    public BlockingAggregator getBlockedStateSubscription(Subscription subscription)  {
+        BlockingAggregator result = new BlockingAggregator();
+        if(subscription != null) {
+            BlockingState subscriptionState = dao.getBlockingStateFor(subscription);
+            if(subscriptionState != null) {
+                result.or(subscriptionState);
+            }
+            if(subscription.getBundleId() != null) {
+                SubscriptionBundle bundle = entitlementApi.getBundleFromId(subscription.getBundleId());
+                result.or(getBlockedStateBundleId(subscription.getBundleId()));
+            } 
+        }
+        return result;
+    }
+
+    public BlockingAggregator getBlockedStateBundleId(UUID bundleId)  {
+        SubscriptionBundle bundle = entitlementApi.getBundleFromId(bundleId);
+        return getBlockedStateBundle(bundle);
+     }
+     
+    public BlockingAggregator getBlockedStateBundle(SubscriptionBundle bundle)  {
+        BlockingAggregator result = getBlockedStateAccount(bundle.getAccountId());
+        BlockingState bundleState = dao.getBlockingStateFor(bundle);
+        if(bundleState != null) {
+            result.or(bundleState);
+        }
+        return result;
+    }
+
+    public BlockingAggregator getBlockedStateAccount(UUID accountId)  {
+        BlockingAggregator result = new BlockingAggregator();
+        if(accountId != null) {
+            BlockingState accountState = dao.getBlockingStateFor(accountId, Blockable.Type.ACCOUNT);
+            result.or(accountState);
+        }
+        return result;
+    }
+
+    public BlockingAggregator getBlockedStateAccount(Account account)  {
+        if(account != null) {
+            return getBlockedStateAccount(account.getId());
+        }
+        return new BlockingAggregator();
+    }
+    @Override
+    public void checkBlockedChange(Subscription subscription) throws BlockingApiException {
+        if(getBlockedStateSubscription(subscription).isBlockChange()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_CHANGE, TYPE_SUBSCRIPTION, subscription.getId().toString());
+        }
+    }
+
+    @Override
+    public void checkBlockedChange(SubscriptionBundle bundle) throws BlockingApiException {
+        if(getBlockedStateBundle(bundle).isBlockChange()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_CHANGE, TYPE_BUNDLE, bundle.getId().toString());
+        }
+    }
+
+    @Override
+    public void checkBlockedChange(Account account) throws BlockingApiException {
+        if(getBlockedStateAccount(account).isBlockChange()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_CHANGE, TYPE_ACCOUNT, account.getId().toString());
+        }
+    }
+
+    @Override
+    public void checkBlockedEntitlement(Subscription subscription) throws BlockingApiException {
+        if(getBlockedStateSubscription(subscription).isBlockEntitlement()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_ENTITLEMENT, TYPE_SUBSCRIPTION, subscription.getId().toString());
+        }
+    }
+
+    @Override
+    public void checkBlockedEntitlement(SubscriptionBundle bundle) throws BlockingApiException {
+        if(getBlockedStateBundle(bundle).isBlockEntitlement()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_ENTITLEMENT, TYPE_BUNDLE, bundle.getId().toString());
+        }
+    }
+
+    @Override
+    public void checkBlockedEntitlement(Account account) throws BlockingApiException {
+        if(getBlockedStateAccount(account).isBlockEntitlement()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_ENTITLEMENT, TYPE_ACCOUNT, account.getId().toString());
+        }
+    }
+
+    @Override
+    public void checkBlockedBilling(Subscription subscription) throws BlockingApiException {
+        if(getBlockedStateSubscription(subscription).isBlockBilling()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_BILLING, TYPE_SUBSCRIPTION, subscription.getId().toString());
+        }
     }
 
     @Override
-    public void checkBlocked(Subscription subscription) throws EntitlementUserApiException {
-        if(subscription.getBundleId() != null) {
-            SubscriptionBundle bundle = entitlementApi.getBundleFromId(subscription.getBundleId());
-            checkBlocked(bundle);
+    public void checkBlockedBilling(SubscriptionBundle bundle) throws BlockingApiException {
+        if(getBlockedStateBundle(bundle).isBlockBilling()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_BILLING, TYPE_BUNDLE, bundle.getId().toString());
         }
     }
 
     @Override
-    public void checkBlocked(SubscriptionBundle bundle) throws EntitlementUserApiException {
-        OverdueState<SubscriptionBundle> bundleState = bundle.getOverdueState();
-        if(bundleState != null && bundleState.blockChanges()) {
-            throw new EntitlementUserApiException(ErrorCode.ENT_BUNDLE_IS_OVERDUE_BLOCKED, bundle.getId(), bundle.getKey());
+    public void checkBlockedBilling(Account account) throws BlockingApiException {
+        if(getBlockedStateAccount(account).isBlockBilling()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_BILLING, TYPE_ACCOUNT, account.getId().toString());
         }
     }
 
- 
+    
 }
diff --git a/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateDao.java b/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateDao.java
index 992553d..b5b03ae 100644
--- a/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateDao.java
+++ b/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateDao.java
@@ -20,21 +20,20 @@ import java.util.SortedSet;
 import java.util.UUID;
 
 import com.ning.billing.junction.api.Blockable;
-import com.ning.billing.junction.api.BlockingState;
 import com.ning.billing.junction.api.Blockable.Type;
-import com.ning.billing.overdue.OverdueState;
+import com.ning.billing.junction.api.BlockingState;
 import com.ning.billing.util.clock.Clock;
 
 public interface BlockingStateDao {
 
     //Read
-    public String getBlockingStateFor(Blockable overdueable);
+    public BlockingState getBlockingStateFor(Blockable blockable);
 
-    public String getBlockingStateForIdAndType(UUID overdueableId, Type type);
+    public BlockingState getBlockingStateFor(UUID blockableId, Type type);
 
-    public SortedSet<BlockingState> getBlockingHistoryFor(Blockable overdueable);
+    public SortedSet<BlockingState> getBlockingHistoryFor(Blockable blockable);
 
-    public SortedSet<BlockingState> getBlockingHistoryForIdAndType(UUID overdueableId, Type type);
+    public SortedSet<BlockingState> getBlockingHistoryForIdAndType(UUID blockableId, Type type);
 
     //Write
     <T extends Blockable> void  setBlockingState(BlockingState state, Clock clock);
diff --git a/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateSqlDao.java b/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateSqlDao.java
index de6fb97..895724c 100644
--- a/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateSqlDao.java
+++ b/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateSqlDao.java
@@ -34,10 +34,10 @@ import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
 import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
 import org.skife.jdbi.v2.tweak.ResultSetMapper;
 
-import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.junction.api.Blockable;
 import com.ning.billing.junction.api.Blockable.Type;
 import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.junction.api.BlockingApiException;
 import com.ning.billing.junction.api.BlockingState;
 import com.ning.billing.overdue.OverdueState;
 import com.ning.billing.util.clock.Clock;
@@ -56,13 +56,13 @@ public interface BlockingStateSqlDao extends BlockingStateDao, CloseMe, Transmog
 
     @Override
     @SqlQuery
-    @Mapper(BlockingStateSqlMapper.class)
-    public abstract String getBlockingStateFor(@Bind(binder = BlockableBinder.class)Blockable overdueable) ;
+    @Mapper(BlockingHistorySqlMapper.class)
+    public abstract BlockingState getBlockingStateFor(@Bind(binder = BlockableBinder.class)Blockable overdueable) ;
     
     @Override
     @SqlQuery
-    @Mapper(BlockingStateSqlMapper.class)
-    public abstract String getBlockingStateForIdAndType(@Bind(binder = UUIDBinder.class) UUID overdueableId, @Bind(binder = BlockableTypeBinder.class)  Type type);
+    @Mapper(BlockingHistorySqlMapper.class)
+    public abstract BlockingState getBlockingStateFor(@Bind(binder = UUIDBinder.class) UUID overdueableId, @Bind(binder = BlockableTypeBinder.class)  Type type);
 
     @Override
     @SqlQuery
@@ -98,7 +98,7 @@ public interface BlockingStateSqlDao extends BlockingStateDao, CloseMe, Transmog
                 blockChange = r.getBoolean("block_change");
                 blockEntitlement = r.getBoolean("block_entitlement");
                 blockBilling = r.getBoolean("block_billing");
-            } catch (CatalogApiException e) {
+            } catch (BlockingApiException e) {
                 throw new SQLException(e);
             }
             return new BlockingState(blockableId, stateName, type, service, blockChange, blockEntitlement, blockBilling, timestamp);
diff --git a/junction/src/main/java/com/ning/billing/junction/glue/JunctionModule.java b/junction/src/main/java/com/ning/billing/junction/glue/JunctionModule.java
index f0b903d..ba09a36 100644
--- a/junction/src/main/java/com/ning/billing/junction/glue/JunctionModule.java
+++ b/junction/src/main/java/com/ning/billing/junction/glue/JunctionModule.java
@@ -16,15 +16,19 @@
 
 package com.ning.billing.junction.glue;
 
+import javax.inject.Singleton;
+
 import org.skife.jdbi.v2.IDBI;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
+import com.ning.billing.junction.api.BillingApi;
 import com.ning.billing.junction.api.BlockingApi;
 import com.ning.billing.junction.api.blocking.DefaultBlockingApi;
 import com.ning.billing.junction.dao.BlockingStateDao;
 import com.ning.billing.junction.dao.BlockingStateSqlDao;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingApi;
 
 public class JunctionModule extends AbstractModule {
 
@@ -32,6 +36,11 @@ public class JunctionModule extends AbstractModule {
     protected void configure() {
         bind(BlockingApi.class).to(DefaultBlockingApi.class);
         bind(BlockingStateDao.class).toProvider(BlockingDaoProvider.class);
+        installBillingApi();
+    }
+
+    protected void installBillingApi() {
+        bind(BillingApi.class).to(DefaultBillingApi.class).asEagerSingleton();
     }
 
     public static class BlockingDaoProvider implements Provider<BlockingStateDao>{
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java
new file mode 100644
index 0000000..3a6c110
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.junction.plumbing.billing;
+
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.Inject;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.account.api.MutableAccountData;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.entitlement.api.billing.BillingEvent;
+import com.ning.billing.entitlement.api.billing.ChargeThruApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.entitlement.api.user.SubscriptionEventTransition;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallContextFactory;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.UserType;
+
+public class DefaultBillingApi implements BillingApi {
+    private static final String API_USER_NAME = "Billing Api";
+    private static final Logger log = LoggerFactory.getLogger(DefaultBillingApi.class);
+    private final ChargeThruApi chargeThruApi;
+    private final CallContextFactory factory;
+    private final AccountUserApi accountApi;
+    private final BillCycleDayCalculator bcdCalculator;
+    private final EntitlementUserApi entitlementUserApi;
+
+    @Inject
+    public DefaultBillingApi(ChargeThruApi chargeThruApi, CallContextFactory factory, AccountUserApi accountApi, 
+            BillCycleDayCalculator bcdCalculator, EntitlementUserApi entitlementUserApi) {
+        this.chargeThruApi = chargeThruApi;
+        this.accountApi = accountApi;
+        this.bcdCalculator = bcdCalculator;
+        this.factory = factory;
+        this.entitlementUserApi = entitlementUserApi;
+    }
+
+    @Override
+    public SortedSet<BillingEvent> getBillingEventsForAccountAndUpdateAccountBCD(final UUID accountId) {
+        Account account = accountApi.getAccountById(accountId);
+        CallContext context = factory.createCallContext(API_USER_NAME, CallOrigin.INTERNAL, UserType.SYSTEM);
+
+        List<SubscriptionBundle> bundles = entitlementUserApi.getBundlesForAccount(accountId);
+        SortedSet<BillingEvent> result = new TreeSet<BillingEvent>();
+        for (final SubscriptionBundle bundle: bundles) {
+            List<Subscription> subscriptions = entitlementUserApi.getSubscriptionsForBundle(bundle.getId());
+
+            for (final Subscription subscription: subscriptions) {
+                for (final SubscriptionEventTransition transition : subscription.getBillingTransitions()) {
+                    try {
+                        int bcd = bcdCalculator.calculateBcd(bundle, subscription, transition, account);
+                        
+                        if(account.getBillCycleDay() == 0) {
+                            MutableAccountData modifiedData = account.toMutableAccountData();
+                            modifiedData.setBillCycleDay(bcd);
+                            accountApi.updateAccount(account.getExternalKey(), modifiedData, context);
+                        }
+
+                        BillingEvent event = new DefaultBillingEvent(account, transition, subscription, bcd, account.getCurrency());
+                        result.add(event);
+                    } catch (CatalogApiException e) {
+                        log.error("Failing to identify catalog components while creating BillingEvent from transition: " +
+                                transition.getId().toString(), e);
+                    } catch (Exception e) {
+                        log.warn("Failed while getting BillingEvent", e);
+                    }
+                }
+            }
+        }
+              
+        return result;
+    }
+
+
+    @Override
+    public UUID getAccountIdFromSubscriptionId(UUID subscriptionId) {
+        return chargeThruApi.getAccountIdFromSubscriptionId(subscriptionId);
+    }
+
+    @Override
+    public void setChargedThroughDate(UUID subscriptionId, DateTime ctd, CallContext context) {
+        chargeThruApi.setChargedThroughDate(subscriptionId, ctd, context);
+    }
+
+    @Override
+    public void setChargedThroughDateFromTransaction(Transmogrifier transactionalDao, UUID subscriptionId,
+            DateTime ctd, CallContext context) {
+        chargeThruApi.setChargedThroughDateFromTransaction(transactionalDao, subscriptionId, ctd, context);
+    }
+
+}
diff --git a/junction/src/test/java/com/ning/billing/junction/api/blocking/TestBlockingApi.java b/junction/src/test/java/com/ning/billing/junction/api/blocking/TestBlockingApi.java
index 2d27a3e..faaa848 100644
--- a/junction/src/test/java/com/ning/billing/junction/api/blocking/TestBlockingApi.java
+++ b/junction/src/test/java/com/ning/billing/junction/api/blocking/TestBlockingApi.java
@@ -102,13 +102,13 @@ public class TestBlockingApi {
         SubscriptionBundle bundle = BrainDeadProxyFactory.createBrainDeadProxyFor(SubscriptionBundle.class);
         ((ZombieControl)bundle).addResult("getId", uuid);
         
-        Assert.assertEquals(api.getBlockingStateNameFor(bundle), overdueStateName2);
-        Assert.assertEquals(api.getBlockingStateNameFor(bundle.getId(), Blockable.Type.SUBSCRIPTION_BUNDLE), overdueStateName2);
+        Assert.assertEquals(api.getBlockingStateFor(bundle).getStateName(), overdueStateName2);
+        Assert.assertEquals(api.getBlockingStateFor(bundle.getId(), Blockable.Type.SUBSCRIPTION_BUNDLE).getStateName(), overdueStateName2);
         
     }
     
     @Test(groups={"slow"}, enabled=true)
-    public void testApiHistory() throws CatalogApiException { 
+    public void testApiHistory() throws Exception { 
         UUID uuid = UUID.randomUUID();
         String overdueStateName = "WayPassedItMan";
         String service = "TEST";
diff --git a/junction/src/test/java/com/ning/billing/junction/blocking/MockBlockingChecker.java b/junction/src/test/java/com/ning/billing/junction/blocking/MockBlockingChecker.java
new file mode 100644
index 0000000..f188a6f
--- /dev/null
+++ b/junction/src/test/java/com/ning/billing/junction/blocking/MockBlockingChecker.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.junction.blocking;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.api.BlockingApiException;
+import com.ning.billing.junction.block.BlockingChecker;
+
+public class MockBlockingChecker implements BlockingChecker {
+
+    @Override
+    public void checkBlockedChange(Subscription subscription) throws BlockingApiException {
+        // Intentionally blank
+        
+    }
+
+    @Override
+    public void checkBlockedChange(SubscriptionBundle bundle) throws BlockingApiException {
+     // Intentionally blank
+        
+    }
+
+    @Override
+    public void checkBlockedChange(Account account) throws BlockingApiException {
+     // Intentionally blank
+        
+    }
+
+    @Override
+    public void checkBlockedEntitlement(Subscription subscription) throws BlockingApiException {
+     // Intentionally blank
+        
+    }
+
+    @Override
+    public void checkBlockedEntitlement(SubscriptionBundle bundle) throws BlockingApiException {
+     // Intentionally blank
+        
+    }
+
+    @Override
+    public void checkBlockedEntitlement(Account account) throws BlockingApiException {
+     // Intentionally blank
+        
+    }
+
+    @Override
+    public void checkBlockedBilling(Subscription subscription) throws BlockingApiException {
+     // Intentionally blank
+        
+    }
+
+    @Override
+    public void checkBlockedBilling(SubscriptionBundle bundleId) throws BlockingApiException {
+     // Intentionally blank
+        
+    }
+
+    @Override
+    public void checkBlockedBilling(Account account) throws BlockingApiException {
+     // Intentionally blank
+        
+    }
+
+   
+}
diff --git a/junction/src/test/java/com/ning/billing/junction/blocking/TestBlockingChecker.java b/junction/src/test/java/com/ning/billing/junction/blocking/TestBlockingChecker.java
new file mode 100644
index 0000000..b973bba
--- /dev/null
+++ b/junction/src/test/java/com/ning/billing/junction/blocking/TestBlockingChecker.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.junction.blocking;
+
+import java.util.SortedSet;
+import java.util.UUID;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.Blockable.Type;
+import com.ning.billing.junction.api.BlockingApiException;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.junction.block.BlockingChecker;
+import com.ning.billing.junction.block.DefaultBlockingChecker;
+import com.ning.billing.junction.dao.BlockingStateDao;
+import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.util.clock.Clock;
+
+
+public class TestBlockingChecker {
+   
+    private BlockingState bundleState;
+    private BlockingState subscriptionState;
+    private BlockingState accountState;
+    
+    private BlockingStateDao dao = new BlockingStateDao() {
+
+        @Override
+        public BlockingState getBlockingStateFor(Blockable blockable) {
+            if(blockable instanceof Account) {
+                return accountState;
+            } else  if(blockable instanceof Subscription) {
+                return subscriptionState;
+            } else {
+                return bundleState;
+            }
+        }
+
+        @Override
+        public BlockingState getBlockingStateFor(UUID blockableId, Type type) {
+            if(type == Blockable.Type.ACCOUNT) {
+                return accountState;
+            } else  if(type == Blockable.Type.SUBSCRIPTION) {
+                return subscriptionState;
+            } else {
+                return bundleState;
+            }
+        }
+
+        @Override
+        public SortedSet<BlockingState> getBlockingHistoryFor(Blockable overdueable) {
+            throw new NotImplementedException();
+        }
+
+        @Override
+        public SortedSet<BlockingState> getBlockingHistoryForIdAndType(UUID overdueableId, Type type) {
+            throw new NotImplementedException();
+        }
+
+        @Override
+        public <T extends Blockable> void setBlockingState(BlockingState state, Clock clock) {
+            throw new NotImplementedException();
+        }
+        
+    };
+    private BlockingChecker checker;
+    private Subscription subscription;
+    private Account account;
+    private SubscriptionBundle bundle;
+    
+    @BeforeClass(groups={"fast"})
+    public void setup() {
+        subscription = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class);
+        ((ZombieControl) subscription).addResult("getId", new UUID(0L,0L));
+        
+        bundle = BrainDeadProxyFactory.createBrainDeadProxyFor(SubscriptionBundle.class);
+        ((ZombieControl) bundle).addResult("getAccountId", new UUID(0L,0L));
+        ((ZombieControl) bundle).addResult("getId", new UUID(0L,0L));
+        ((ZombieControl) bundle).addResult("getKey", "key");
+        ((ZombieControl) subscription).addResult("getBundleId", new UUID(0L,0L));
+
+        account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
+        ((ZombieControl) account).addResult("getId", new UUID(0L,0L));
+       
+        Injector i = Guice.createInjector(new AbstractModule() {
+
+            @Override
+            protected void configure() {
+                bind(BlockingChecker.class).to(DefaultBlockingChecker.class).asEagerSingleton();
+                
+                bind(BlockingStateDao.class).toInstance(dao);             
+                
+                EntitlementUserApi entitlementUserApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementUserApi.class);
+                //((ZombieControl) entitlementDao).addResult("", result)
+                bind(EntitlementUserApi.class).toInstance(entitlementUserApi);
+                ((ZombieControl) entitlementUserApi).addResult("getBundleFromId",bundle);
+                
+            }
+            
+        });
+        checker = i.getInstance(BlockingChecker.class);
+    }
+
+
+    private void setStateBundle(boolean bC, boolean bE, boolean bB) {
+        bundleState = new BlockingState(UUID.randomUUID(), "state", Blockable.Type.SUBSCRIPTION_BUNDLE, "test-service", bC, bE,bB);
+    }
+
+    private void setStateAccount(boolean bC, boolean bE, boolean bB) {
+        accountState = new BlockingState(UUID.randomUUID(), "state", Blockable.Type.SUBSCRIPTION_BUNDLE, "test-service", bC, bE,bB);
+    }
+
+    private void setStateSubscription(boolean bC, boolean bE, boolean bB) {
+        subscriptionState = new BlockingState(UUID.randomUUID(), "state", Blockable.Type.SUBSCRIPTION_BUNDLE, "test-service", bC, bE,bB);
+    }
+
+    @Test(groups={"fast"}, enabled = true)
+    public void testSubscriptionChecker() throws Exception {
+        setStateAccount(false, false, false);
+        setStateBundle(false, false, false);
+        setStateSubscription(false, false, false);
+        checker.checkBlockedChange(subscription);
+        checker.checkBlockedEntitlement(subscription);
+        checker.checkBlockedBilling(subscription);
+        
+        //BLOCKED SUBSCRIPTION
+        setStateSubscription(true, false, false);
+        checker.checkBlockedEntitlement(subscription);
+        checker.checkBlockedBilling(subscription);
+        try {
+            checker.checkBlockedChange(subscription);
+            Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+        setStateSubscription(false, true, false);
+        checker.checkBlockedChange(subscription);
+        checker.checkBlockedBilling(subscription);
+        try {
+            checker.checkBlockedEntitlement(subscription);
+            Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+        setStateSubscription(false, false, true);
+        checker.checkBlockedChange(subscription);
+        checker.checkBlockedEntitlement(subscription);
+        try {
+           checker.checkBlockedBilling(subscription);
+           Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+
+        //BLOCKED BUNDLE
+        setStateSubscription(false, false, false);
+        setStateBundle(true, false, false);
+        checker.checkBlockedEntitlement(subscription);
+        checker.checkBlockedBilling(subscription);
+        try {
+            checker.checkBlockedChange(subscription);
+            Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+        setStateBundle(false, true, false);
+        checker.checkBlockedChange(subscription);
+        checker.checkBlockedBilling(subscription);
+        try {
+            checker.checkBlockedEntitlement(subscription);
+            Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+        setStateBundle(false, false, true);
+        checker.checkBlockedChange(subscription);
+        checker.checkBlockedEntitlement(subscription);
+        try {
+           checker.checkBlockedBilling(subscription);
+           Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+        
+        //BLOCKED Account
+        setStateSubscription(false, false, false);
+        setStateBundle(false, false, false);
+        setStateAccount(true, false, false);
+        checker.checkBlockedEntitlement(subscription);
+        checker.checkBlockedBilling(subscription);
+        try {
+            checker.checkBlockedChange(subscription);
+            Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+        setStateAccount(false, true, false);
+        checker.checkBlockedChange(subscription);
+        checker.checkBlockedBilling(subscription);
+        try {
+            checker.checkBlockedEntitlement(subscription);
+            Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+        setStateAccount(false, false, true);
+        checker.checkBlockedChange(subscription);
+        checker.checkBlockedEntitlement(subscription);
+        try {
+           checker.checkBlockedBilling(subscription);
+           Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+        
+    }
+    
+    @Test(groups={"fast"}, enabled = true)
+    public void testBundleChecker() throws Exception {
+        setStateAccount(false, false, false);
+        setStateBundle(false, false, false);
+        setStateSubscription(false, false, false);
+        checker.checkBlockedChange(bundle);
+        checker.checkBlockedEntitlement(bundle);
+        checker.checkBlockedBilling(bundle);
+
+        //BLOCKED BUNDLE
+        setStateSubscription(false, false, false);
+        setStateBundle(true, false, false);
+        checker.checkBlockedEntitlement(bundle);
+        checker.checkBlockedBilling(bundle);
+        try {
+            checker.checkBlockedChange(bundle);
+            Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+        setStateBundle(false, true, false);
+        checker.checkBlockedChange(bundle);
+        checker.checkBlockedBilling(bundle);
+        try {
+            checker.checkBlockedEntitlement(bundle);
+            Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+        setStateBundle(false, false, true);
+        checker.checkBlockedChange(bundle);
+        checker.checkBlockedEntitlement(bundle);
+        try {
+           checker.checkBlockedBilling(bundle);
+           Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+        
+        //BLOCKED Account
+        setStateSubscription(false, false, false);
+        setStateBundle(false, false, false);
+        setStateAccount(true, false, false);
+        checker.checkBlockedEntitlement(bundle);
+        checker.checkBlockedBilling(bundle);
+        try {
+            checker.checkBlockedChange(bundle);
+            Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+        setStateAccount(false, true, false);
+        checker.checkBlockedChange(bundle);
+        checker.checkBlockedBilling(bundle);
+        try {
+            checker.checkBlockedEntitlement(bundle);
+            Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+        setStateAccount(false, false, true);
+        checker.checkBlockedChange(bundle);
+        checker.checkBlockedEntitlement(bundle);
+        try {
+           checker.checkBlockedBilling(bundle);
+           Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+  
+    }
+    
+    @Test(groups={"fast"}, enabled = true)
+    public void testAccountChecker() throws Exception {
+        setStateAccount(false, false, false);
+        setStateBundle(false, false, false);
+        setStateSubscription(false, false, false);
+        checker.checkBlockedChange(account);
+        checker.checkBlockedEntitlement(account);
+        checker.checkBlockedBilling(account);
+
+        //BLOCKED Account
+        setStateSubscription(false, false, false);
+        setStateBundle(false, false, false);
+        setStateAccount(true, false, false);
+        checker.checkBlockedEntitlement(account);
+        checker.checkBlockedBilling(account);
+        try {
+            checker.checkBlockedChange(account);
+            Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+        setStateAccount(false, true, false);
+        checker.checkBlockedChange(account);
+        checker.checkBlockedBilling(account);
+        try {
+            checker.checkBlockedEntitlement(account);
+            Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+        setStateAccount(false, false, true);
+        checker.checkBlockedChange(account);
+        checker.checkBlockedEntitlement(account);
+        try {
+           checker.checkBlockedBilling(account);
+           Assert.fail("The call should have been blocked!");
+        } catch (BlockingApiException e) {
+            //Expected behavior
+        }
+        
+
+        
+    }
+    
+
+     
+}
diff --git a/junction/src/test/java/com/ning/billing/junction/dao/TestBlockingDao.java b/junction/src/test/java/com/ning/billing/junction/dao/TestBlockingDao.java
index 961e0d9..084f30f 100644
--- a/junction/src/test/java/com/ning/billing/junction/dao/TestBlockingDao.java
+++ b/junction/src/test/java/com/ning/billing/junction/dao/TestBlockingDao.java
@@ -30,18 +30,16 @@ import org.testng.annotations.Guice;
 import org.testng.annotations.Test;
 
 import com.google.inject.Inject;
-import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.junction.MockModule;
 import com.ning.billing.junction.api.Blockable;
 import com.ning.billing.junction.api.BlockingState;
-import com.ning.billing.junction.glue.JunctionModule;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
 import com.ning.billing.util.clock.ClockMock;
 
-@Guice(modules = {MockModule.class,  JunctionModule.class})
+@Guice(modules = {MockModule.class})
 public class TestBlockingDao {
     private Logger log = LoggerFactory.getLogger(TestBlockingDao.class);
     
@@ -91,13 +89,13 @@ public class TestBlockingDao {
         SubscriptionBundle bundle = BrainDeadProxyFactory.createBrainDeadProxyFor(SubscriptionBundle.class);
         ((ZombieControl)bundle).addResult("getId", uuid);
         
-        Assert.assertEquals(dao.getBlockingStateFor(bundle), overdueStateName2);
-        Assert.assertEquals(dao.getBlockingStateForIdAndType(bundle.getId(), Blockable.Type.SUBSCRIPTION_BUNDLE), overdueStateName2);
+        Assert.assertEquals(dao.getBlockingStateFor(bundle).getStateName(), state2.getStateName());
+        Assert.assertEquals(dao.getBlockingStateFor(bundle.getId(), Blockable.Type.SUBSCRIPTION_BUNDLE).getStateName(), overdueStateName2);
         
     }
     
     @Test(groups={"slow"}, enabled=true)
-    public void testDaoHistory() throws CatalogApiException { 
+    public void testDaoHistory() throws Exception { 
         ClockMock clock = new ClockMock();
         UUID uuid = UUID.randomUUID();
         String overdueStateName = "WayPassedItMan";
diff --git a/junction/src/test/java/com/ning/billing/junction/MockModule.java b/junction/src/test/java/com/ning/billing/junction/MockModule.java
index a8c4e75..0723fd8 100644
--- a/junction/src/test/java/com/ning/billing/junction/MockModule.java
+++ b/junction/src/test/java/com/ning/billing/junction/MockModule.java
@@ -24,18 +24,21 @@ import com.ning.billing.catalog.glue.CatalogModule;
 import com.ning.billing.dbi.DBIProvider;
 import com.ning.billing.dbi.DbiConfig;
 import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.junction.api.BillingApi;
 import com.ning.billing.junction.glue.JunctionModule;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingApi;
 import com.ning.billing.util.callcontext.CallContextFactory;
 import com.ning.billing.util.callcontext.DefaultCallContextFactory;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.clock.ClockMock;
 
 
-public class MockModule extends AbstractModule {
+public class MockModule extends JunctionModule {
     public static final String PLUGIN_NAME = "Booboo";
 
     @Override
     protected void configure() {
+        super.configure();
         bind(Clock.class).to(ClockMock.class).asEagerSingleton();
         bind(ClockMock.class).asEagerSingleton();
         bind(CallContextFactory.class).to(DefaultCallContextFactory.class).asEagerSingleton();
@@ -52,8 +55,10 @@ public class MockModule extends AbstractModule {
         }
 
        install(new CatalogModule());
-       install(new JunctionModule());
     }
     
+    protected void installBillingApi() {
+        // no billinggApi
+    }
 
 }

overdue/pom.xml 5(+5 -0)

diff --git a/overdue/pom.xml b/overdue/pom.xml
index 5a9aff4..b6f64a0 100644
--- a/overdue/pom.xml
+++ b/overdue/pom.xml
@@ -100,6 +100,11 @@
             <artifactId>mysql-connector-mxj-db-files</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>com.jayway.awaitility</groupId>
+            <artifactId>awaitility</artifactId>
+            <scope>test</scope>
+        </dependency>
         <!-- Strangely this is needed in order to run the tests in local db mode -->
         <dependency>
             <groupId>com.google.guava</groupId>
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 c4dd72f..092911d 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
@@ -53,7 +53,7 @@ public class DefaultOverdueUserApi implements OverdueUserApi{
     @Override
     public <T extends Blockable> OverdueState<T> getOverdueStateFor(T overdueable) throws OverdueError {
         try {
-            String stateName = accessApi.getBlockingStateNameFor(overdueable);
+            String stateName = accessApi.getBlockingStateFor(overdueable).getStateName();
             OverdueStateSet<SubscriptionBundle> states = overdueConfig.getBundleStateSet();
             return (OverdueState<T>) states.findState(stateName);
         } catch (CatalogApiException e) {
diff --git a/overdue/src/main/java/com/ning/billing/overdue/glue/OverdueModule.java b/overdue/src/main/java/com/ning/billing/overdue/glue/OverdueModule.java
index a94ccf5..8b0b15e 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/glue/OverdueModule.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/glue/OverdueModule.java
@@ -16,15 +16,18 @@
 
 package com.ning.billing.overdue.glue;
 
+import org.skife.config.ConfigurationObjectFactory;
+
 import com.google.inject.AbstractModule;
+import com.ning.billing.ovedue.OverdueProperties;
 
 
 public class OverdueModule extends AbstractModule {
 
     @Override
     protected void configure() {
-        // TODO Auto-generated method stub
-        
+        final OverdueProperties config = new ConfigurationObjectFactory(System.getProperties()).build(OverdueProperties.class);
+        bind(OverdueProperties.class).toInstance(config);
     }
     
 
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 1c0b02b..892ad05 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
@@ -51,7 +51,7 @@ public class OverdueWrapper<T extends Blockable> {
     public OverdueState<T> refresh() throws OverdueError, CatalogApiException {
         OverdueState<T> nextOverdueState;
         BillingState<T> billingState = billingStateCalcuator.calculateBillingState(overdueable);
-        String previousOverdueStateName = api.getBlockingStateNameFor(overdueable);
+        String previousOverdueStateName = api.getBlockingStateFor(overdueable).getStateName();
         nextOverdueState = overdueStateSet.calculateOverdueState(billingState, clock.getUTCNow());
         if(!previousOverdueStateName.equals(nextOverdueState.getName())) {
             overdueStateApplicator.apply(overdueable, nextOverdueState, nextOverdueState, overdueStateSet.dateOfNextCheck(billingState, clock.getUTCNow())); 
diff --git a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java
index 6873c4c..d542e24 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java
@@ -47,12 +47,12 @@ public class OverdueWrapperFactory {
     }
 
     @SuppressWarnings("unchecked")
-    public <T extends Blockable> OverdueWrapper<T> createOverdueWrapperFor(T overdueable) throws OverdueError {
-        if(overdueable instanceof SubscriptionBundle) {
-            return (OverdueWrapper<T>)new OverdueWrapper<SubscriptionBundle>((SubscriptionBundle)overdueable, api, overdueConfig.getBundleStateSet(), 
+    public <T extends Blockable> OverdueWrapper<T> createOverdueWrapperFor(T bloackable) throws OverdueError {
+        if(bloackable instanceof SubscriptionBundle) {
+            return (OverdueWrapper<T>)new OverdueWrapper<SubscriptionBundle>((SubscriptionBundle)bloackable, api, overdueConfig.getBundleStateSet(), 
                     clock, billingStateCalcuatorBundle, overdueStateApplicatorBundle );
         } else {
-            throw new OverdueError(ErrorCode.OVERDUE_OVERDUEABLE_NOT_SUPPORTED, overdueable.getClass());
+            throw new OverdueError(ErrorCode.OVERDUE_TYPE_NOT_SUPPORTED, bloackable.getId(), bloackable.getClass());
         }
     }
 
diff --git a/overdue/src/test/java/com/ning/billing/overdue/notification/MockOverdueCheckPoster.java b/overdue/src/test/java/com/ning/billing/overdue/notification/MockOverdueCheckPoster.java
new file mode 100644
index 0000000..29d30ca
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/notification/MockOverdueCheckPoster.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.overdue.notification;
+
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.ovedue.notification.OverdueCheckPoster;
+
+public class MockOverdueCheckPoster implements OverdueCheckPoster {
+    
+    @Override
+    public void insertOverdueCheckNotification(Transmogrifier transactionalDao, Blockable overdueable,
+            DateTime futureNotificationTime) {
+        // TODO Auto-generated method stub
+        
+    }
+}
diff --git a/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueCheckNotifier.java b/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueCheckNotifier.java
new file mode 100644
index 0000000..d45e221
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueCheckNotifier.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.overdue.notification;
+
+import static com.jayway.awaitility.Awaitility.await;
+import static java.util.concurrent.TimeUnit.MINUTES;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+
+import org.apache.commons.io.IOUtils;
+import org.joda.time.DateTime;
+import org.skife.config.ConfigurationObjectFactory;
+import org.skife.jdbi.v2.IDBI;
+import org.skife.jdbi.v2.Transaction;
+import org.skife.jdbi.v2.TransactionStatus;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.catalog.DefaultCatalogService;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.config.CatalogConfig;
+import com.ning.billing.config.InvoiceConfig;
+import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.entitlement.api.billing.ChargeThruApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.plumbing.billing.DefaultBillingApi;
+import com.ning.billing.lifecycle.KillbillService.ServiceException;
+import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.ovedue.OverdueProperties;
+import com.ning.billing.ovedue.notification.DefaultOverdueCheckNotifier;
+import com.ning.billing.ovedue.notification.DefaultOverdueCheckPoster;
+import com.ning.billing.ovedue.notification.OverdueCheckPoster;
+import com.ning.billing.ovedue.notification.OverdueListener;
+import com.ning.billing.overdue.glue.OverdueModule;
+import com.ning.billing.util.bus.Bus;
+import com.ning.billing.util.bus.InMemoryBus;
+import com.ning.billing.util.callcontext.CallContextFactory;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.ClockMock;
+import com.ning.billing.util.customfield.dao.AuditedCustomFieldDao;
+import com.ning.billing.util.customfield.dao.CustomFieldDao;
+import com.ning.billing.util.globallocker.GlobalLocker;
+import com.ning.billing.util.globallocker.MySqlGlobalLocker;
+import com.ning.billing.util.notificationq.DefaultNotificationQueueService;
+import com.ning.billing.util.notificationq.DummySqlTest;
+import com.ning.billing.util.notificationq.NotificationQueueService;
+import com.ning.billing.util.notificationq.dao.NotificationSqlDao;
+import com.ning.billing.util.tag.dao.AuditedTagDao;
+import com.ning.billing.util.tag.dao.TagDao;
+
+public class TestOverdueCheckNotifier {
+	private Clock clock;
+	private DefaultOverdueCheckNotifier notifier;
+	private DummySqlTest dao;
+	private Bus eventBus;
+	private MysqlTestingHelper helper;
+	private OverdueListenerMock listener;
+	private NotificationQueueService notificationQueueService;
+
+	private static final class OverdueListenerMock extends OverdueListener {
+		int eventCount = 0;
+		UUID latestSubscriptionId = null;
+
+		public OverdueListenerMock() {
+			super();
+		}
+
+		@Override
+		public void handleNextOverdueCheck(UUID subscriptionId, DateTime eventDateTime) {
+			eventCount++;
+			latestSubscriptionId=subscriptionId;
+		}
+
+		public int getEventCount() {
+			return eventCount;
+		}
+
+		public UUID getLatestSubscriptionId(){
+			return latestSubscriptionId;
+		}
+
+	}
+
+
+	@BeforeClass(groups={"slow"})
+	public void setup() throws ServiceException, IOException, ClassNotFoundException, SQLException {
+		//TestApiBase.loadSystemPropertiesFromClasspath("/entitlement.properties");
+        final Injector g = Guice.createInjector(Stage.PRODUCTION,  new OverdueModule() {
+			
+            protected void configure() {
+                super.configure();
+                bind(Clock.class).to(ClockMock.class).asEagerSingleton();
+                bind(CallContextFactory.class).to(DefaultCallContextFactory.class).asEagerSingleton();
+                bind(Bus.class).to(InMemoryBus.class).asEagerSingleton();
+                bind(NotificationQueueService.class).to(DefaultNotificationQueueService.class).asEagerSingleton();
+                final InvoiceConfig invoiceConfig = new ConfigurationObjectFactory(System.getProperties()).build(InvoiceConfig.class);
+                bind(InvoiceConfig.class).toInstance(invoiceConfig);
+                final CatalogConfig catalogConfig = new ConfigurationObjectFactory(System.getProperties()).build(CatalogConfig.class);
+                bind(CatalogConfig.class).toInstance(catalogConfig);
+                bind(CatalogService.class).to(DefaultCatalogService.class).asEagerSingleton();
+                final MysqlTestingHelper helper = new MysqlTestingHelper();
+                bind(MysqlTestingHelper.class).toInstance(helper);
+                IDBI dbi = helper.getDBI();
+                bind(IDBI.class).toInstance(dbi);
+                bind(TagDao.class).to(AuditedTagDao.class).asEagerSingleton();
+                bind(CustomFieldDao.class).to(AuditedCustomFieldDao.class).asEagerSingleton();
+                bind(GlobalLocker.class).to(MySqlGlobalLocker.class).asEagerSingleton();
+                bind(BillingApi.class).to(DefaultBillingApi.class).asEagerSingleton();
+                bind(AccountUserApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class));
+                bind(ChargeThruApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(ChargeThruApi.class));
+                bind(EntitlementUserApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementUserApi.class));
+            }
+        });
+
+        clock = g.getInstance(Clock.class);
+        IDBI dbi = g.getInstance(IDBI.class);
+        dao = dbi.onDemand(DummySqlTest.class);
+        eventBus = g.getInstance(Bus.class);
+        helper = g.getInstance(MysqlTestingHelper.class);
+        notificationQueueService = g.getInstance(NotificationQueueService.class);
+        
+        OverdueProperties properties = g.getInstance(OverdueProperties.class);
+
+        Subscription subscription = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class);
+        EntitlementUserApi entitlementUserApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementUserApi.class);
+        ((ZombieControl) entitlementUserApi).addResult("getSubscriptionFromId", subscription);
+
+//        CallContextFactory factory = new DefaultCallContextFactory(clock);
+        listener = new OverdueListenerMock();
+        notifier = new DefaultOverdueCheckNotifier(notificationQueueService,
+                 properties, listener);
+        startMysql();
+	}
+
+	private void startMysql() throws IOException, ClassNotFoundException, SQLException {
+		final String ddl = IOUtils.toString(NotificationSqlDao.class.getResourceAsStream("/com/ning/billing/util/ddl.sql"));
+		final String testDdl = IOUtils.toString(NotificationSqlDao.class.getResourceAsStream("/com/ning/billing/util/ddl_test.sql"));
+
+		helper.startMysql();
+		helper.initDb(ddl);
+		helper.initDb(testDdl);
+	}
+
+	@Test(enabled=true, groups="slow")
+	public void test() throws Exception {
+		final UUID subscriptionId = new UUID(0L,1L);
+		final Blockable blockable = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class);
+		((ZombieControl)blockable).addResult("getId", subscriptionId);
+		final DateTime now = new DateTime();
+		final DateTime readyTime = now.plusMillis(2000);
+		final OverdueCheckPoster poster = new DefaultOverdueCheckPoster(notificationQueueService);
+
+		eventBus.start();
+		notifier.initialize();
+		notifier.start();
+
+
+		dao.inTransaction(new Transaction<Void, DummySqlTest>() {
+			@Override
+			public Void inTransaction(DummySqlTest transactional,
+					TransactionStatus status) throws Exception {
+
+				poster.insertOverdueCheckNotification(transactional, blockable, readyTime);
+				return null;
+			}
+		});
+
+
+		// Move time in the future after the notification effectiveDate
+		((ClockMock) clock).setDeltaFromReality(3000);
+
+
+	    await().atMost(1, MINUTES).until(new Callable<Boolean>() {
+	            @Override
+	            public Boolean call() throws Exception {
+	                return listener.getEventCount() == 1;
+	            }
+	        });
+
+		Assert.assertEquals(listener.getEventCount(), 1);
+		Assert.assertEquals(listener.getLatestSubscriptionId(), subscriptionId);
+	}
+
+	@AfterClass(alwaysRun = true)
+    public void tearDown() {
+	    eventBus.stop();
+        notifier.stop();
+        helper.stopMysql();
+    }
+
+}
diff --git a/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithEmbeddedDb.java b/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithEmbeddedDb.java
index 8faf1f3..b2b28de 100644
--- a/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithEmbeddedDb.java
+++ b/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithEmbeddedDb.java
@@ -21,7 +21,7 @@ import org.apache.commons.collections.MapUtils;
 import com.google.common.collect.ImmutableMap;
 import com.google.inject.Provider;
 import com.ning.billing.config.PaymentConfig;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
+import com.ning.billing.junction.api.BillingApi;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.payment.provider.MockPaymentProviderPluginModule;
 import com.ning.billing.util.bus.Bus;
@@ -30,10 +30,10 @@ import com.ning.billing.util.notificationq.DefaultNotificationQueueService;
 import com.ning.billing.util.notificationq.NotificationQueueService;
 
 public class PaymentTestModuleWithEmbeddedDb extends PaymentModule {
-	public static class MockProvider implements Provider<EntitlementBillingApi> {
+	public static class MockProvider implements Provider<BillingApi> {
 		@Override
-		public EntitlementBillingApi get() {
-			return BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementBillingApi.class);
+		public BillingApi get() {
+			return BrainDeadProxyFactory.createBrainDeadProxyFor(BillingApi.class);
 		}
 
 	}
@@ -51,7 +51,7 @@ public class PaymentTestModuleWithEmbeddedDb extends PaymentModule {
     protected void configure() {
         super.configure();
         bind(Bus.class).to(InMemoryBus.class).asEagerSingleton();
-        bind(EntitlementBillingApi.class).toProvider(MockProvider.class);
+        bind(BillingApi.class).toProvider(MockProvider.class);
         bind(NotificationQueueService.class).to(DefaultNotificationQueueService.class).asEagerSingleton();
     }
 }
diff --git a/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithMocks.java b/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithMocks.java
index b0999da..64d409e 100644
--- a/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithMocks.java
+++ b/payment/src/test/java/com/ning/billing/payment/setup/PaymentTestModuleWithMocks.java
@@ -23,9 +23,9 @@ import com.google.inject.Provider;
 import com.ning.billing.account.dao.AccountDao;
 import com.ning.billing.account.dao.MockAccountDao;
 import com.ning.billing.config.PaymentConfig;
-import com.ning.billing.entitlement.api.billing.EntitlementBillingApi;
 import com.ning.billing.invoice.dao.InvoiceDao;
 import com.ning.billing.invoice.dao.MockInvoiceDao;
+import com.ning.billing.junction.api.BillingApi;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.payment.dao.MockPaymentDao;
 import com.ning.billing.payment.dao.PaymentDao;
@@ -36,10 +36,10 @@ import com.ning.billing.util.notificationq.MockNotificationQueueService;
 import com.ning.billing.util.notificationq.NotificationQueueService;
 
 public class PaymentTestModuleWithMocks extends PaymentModule {
-	public static class MockProvider implements Provider<EntitlementBillingApi> {
+	public static class MockProvider implements Provider<BillingApi> {
 		@Override
-		public EntitlementBillingApi get() {
-			return BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementBillingApi.class);
+		public BillingApi get() {
+			return BrainDeadProxyFactory.createBrainDeadProxyFor(BillingApi.class);
 		}
 
 	}
@@ -68,7 +68,7 @@ public class PaymentTestModuleWithMocks extends PaymentModule {
         bind(AccountDao.class).to(MockAccountDao.class);
         bind(MockInvoiceDao.class).asEagerSingleton();
         bind(InvoiceDao.class).to(MockInvoiceDao.class);
-        bind(EntitlementBillingApi.class).toProvider( MockProvider.class );
+        bind(BillingApi.class).toProvider( MockProvider.class );
         bind(NotificationQueueService.class).to(MockNotificationQueueService.class).asEagerSingleton();
     }
 }