killbill-aplcache

Merge branch 'integration' of github.com:ning/killbill

5/29/2012 5:28:26 PM

Changes

junction/pom.xml 19(+12 -7)

pom.xml 20(+13 -7)

Details

diff --git a/api/src/main/java/com/ning/billing/junction/api/BillingApi.java b/api/src/main/java/com/ning/billing/junction/api/BillingApi.java
index cff8ee7..bb38e8d 100644
--- a/api/src/main/java/com/ning/billing/junction/api/BillingApi.java
+++ b/api/src/main/java/com/ning/billing/junction/api/BillingApi.java
@@ -16,10 +16,8 @@
 
 package com.ning.billing.junction.api;
 
-import java.util.SortedSet;
 import java.util.UUID;
 
-import com.ning.billing.entitlement.api.billing.BillingEvent;
 import com.ning.billing.entitlement.api.billing.ChargeThruApi;
 
 public interface BillingApi extends ChargeThruApi {
@@ -29,5 +27,5 @@ public interface BillingApi extends ChargeThruApi {
      * @return an ordered list of billing event for the given accounts
      *
      */
-    public SortedSet<BillingEvent> getBillingEventsForAccountAndUpdateAccountBCD(UUID accountId);
+    public BillingEventSet getBillingEventsForAccountAndUpdateAccountBCD(UUID accountId);
 }
diff --git a/api/src/main/java/com/ning/billing/junction/api/BillingEventSet.java b/api/src/main/java/com/ning/billing/junction/api/BillingEventSet.java
index 3a7b66d..aed5c6a 100644
--- a/api/src/main/java/com/ning/billing/junction/api/BillingEventSet.java
+++ b/api/src/main/java/com/ning/billing/junction/api/BillingEventSet.java
@@ -27,5 +27,7 @@ public interface BillingEventSet extends SortedSet<BillingEvent> {
     public abstract boolean isAccountAutoInvoiceOff();
 
     public abstract List<UUID> getSubscriptionIdsWithAutoInvoiceOff();
+    
+    public boolean isLast(BillingEvent event);
 
 }
\ No newline at end of file
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
index a94cf5d..a107bb2 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
@@ -187,7 +187,6 @@ public class TestOverdueIntegration extends TestIntegrationBase {
     
         clock.addDays(15); // DAY 45 - 15 days after invoice
         assertTrue(busHandler.isCompleted(DELAY));
-        overdueApi.refreshOverdueStateFor(bundle); // trigger a refresh because there are no events to do it for us
         //should still be in clear state
         checkODState(BlockingApi.CLEAR_STATE_NAME);
 
@@ -200,14 +199,12 @@ public class TestOverdueIntegration extends TestIntegrationBase {
           
         clock.addDays(2); //DAY 67 - 37 days after invoice
         assertTrue(busHandler.isCompleted(DELAY));
-        overdueApi.refreshOverdueStateFor(bundle); // trigger a refresh because there are no events to do it for us
         // should still be in OD1
         checkODState("OD1");
 
         //busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT_ERROR);
         clock.addDays(8); //DAY 75 - 45 days after invoice
         assertTrue(busHandler.isCompleted(DELAY));
-        overdueApi.refreshOverdueStateFor(bundle); // trigger a refresh because there are no events to do it for us
         // should still be in OD1
         checkODState("OD2");
         
@@ -229,7 +226,6 @@ public class TestOverdueIntegration extends TestIntegrationBase {
             }
         }
         
-        overdueApi.refreshOverdueStateFor(bundle);
         checkODState(BlockingApi.CLEAR_STATE_NAME);
 
     }
@@ -240,6 +236,7 @@ public class TestOverdueIntegration extends TestIntegrationBase {
             await().atMost(10, SECONDS).until(new Callable<Boolean>() {
                 @Override
                 public Boolean call() throws Exception {
+                    overdueApi.refreshOverdueStateFor(bundle); 
                     return expected.equals(blockingApi.getBlockingStateFor(bundle).getStateName()) ;
                 }
             });
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultDuration.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultDuration.java
index 71bfe50..34860be 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultDuration.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultDuration.java
@@ -16,16 +16,18 @@
 
 package com.ning.billing.catalog;
 
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.joda.time.DateTime;
+import org.joda.time.Period;
+
 import com.ning.billing.catalog.api.Duration;
 import com.ning.billing.catalog.api.TimeUnit;
 import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationError;
 import com.ning.billing.util.config.ValidationErrors;
-import org.joda.time.DateTime;
-import org.joda.time.Period;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
 
 @XmlAccessorType(XmlAccessType.NONE)
 public class DefaultDuration extends ValidatingConfig<StandaloneCatalog> implements Duration {
@@ -71,6 +73,12 @@ public class DefaultDuration extends ValidatingConfig<StandaloneCatalog> impleme
 
     @Override
 	public ValidationErrors validate(StandaloneCatalog catalog, ValidationErrors errors) {
+        //Validation: TimeUnit UNLIMITED iff number == -1
+        if((unit == TimeUnit.UNLIMITED && number != -1)) {
+            errors.add(new ValidationError("Duration can only have 'UNLIMITED' unit if the number is omitted.", 
+                    catalog.getCatalogURI(), DefaultPlanPhase.class, ""));
+        }
+
 		//TODO MDW - Validation TimeUnit UNLIMITED iff number == -1
 		return errors;
 	}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java
index 0f021c3..8feff37 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java
@@ -144,20 +144,26 @@ public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implem
 					catalog.getCatalogURI(), DefaultPlanPhase.class, type.toString()));
 		}
 
-		//Validation: if there is no recurring price there should be no billing period
-		if((recurringPrice == null) && billingPeriod != BillingPeriod.NO_BILLING_PERIOD) {
-			errors.add(new ValidationError(String.format("Phase %s of plan %s has no recurring price but does have a billing period. The billing period should be set to '%s'",
-					type.toString(), plan.getName(), BillingPeriod.NO_BILLING_PERIOD), 
-					catalog.getCatalogURI(), DefaultPlanPhase.class, type.toString()));
-		}
-		
+        //Validation: if there is no recurring price there should be no billing period
+        if((recurringPrice == null) && billingPeriod != BillingPeriod.NO_BILLING_PERIOD) {
+            errors.add(new ValidationError(String.format("Phase %s of plan %s has no recurring price but does have a billing period. The billing period should be set to '%s'",
+                    type.toString(), plan.getName(), BillingPeriod.NO_BILLING_PERIOD), 
+                    catalog.getCatalogURI(), DefaultPlanPhase.class, type.toString()));
+        }
+        
+        //Validation: if there BP is set to NO_BILLING_PERIOD there must be a fixed price
+        if((billingPeriod == BillingPeriod.NO_BILLING_PERIOD && fixedPrice == null)) {
+            errors.add(new ValidationError(String.format("Phase %s of plan %s has no billing period. It must have a fixed price set.",
+                    type.toString(), plan.getName()), 
+                    catalog.getCatalogURI(), DefaultPlanPhase.class, type.toString()));
+        }
+        
 		//Validation: there must be at least one of recurringPrice or fixedPrice
 		if((recurringPrice == null) && fixedPrice == null) {
 			errors.add(new ValidationError(String.format("Phase %s of plan %s has neither a recurring price or a fixed price.",
 					type.toString(), plan.getName()), 
 					catalog.getCatalogURI(), DefaultPlanPhase.class, type.toString()));
 		}
-		//TODO : if there BP is set to NO_BILLING_PERIOD there must be a recurring price
         return errors;
 	}
 	
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 40dc146..ac090de 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
@@ -184,20 +184,17 @@ public class MockCatalog extends StandaloneCatalog implements Catalog {
 
     @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);
     }
 
@@ -208,13 +205,11 @@ public class MockCatalog extends StandaloneCatalog implements Catalog {
 
     @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;
     }
 
diff --git a/catalog/src/test/java/com/ning/billing/mock/catalog/MockPlan.java b/catalog/src/test/java/com/ning/billing/mock/catalog/MockPlan.java
index 0657fd4..2199eb9 100644
--- a/catalog/src/test/java/com/ning/billing/mock/catalog/MockPlan.java
+++ b/catalog/src/test/java/com/ning/billing/mock/catalog/MockPlan.java
@@ -46,57 +46,48 @@ public class MockPlan implements Plan {
 
 	@Override
 	public boolean isRetired() {
-		// TODO Auto-generated method stub
-		return false;
+				return false;
 	}
 
 	@Override
 	public Iterator<PlanPhase> getInitialPhaseIterator() {
-		// TODO Auto-generated method stub
-		return null;
+				return null;
 	}
 
 	@Override
 	public PlanPhase getFinalPhase() {
-		// TODO Auto-generated method stub
-		return null;
+				return null;
 	}
 
 	@Override
 	public BillingPeriod getBillingPeriod() {
-		// TODO Auto-generated method stub
-		return null;
+				return null;
 	}
 
 	@Override
 	public int getPlansAllowedInBundle() {
-		// TODO Auto-generated method stub
-		return 0;
+				return 0;
 	}
 
 	@Override
 	public PlanPhase[] getAllPhases() {
-		// TODO Auto-generated method stub
-		return null;
+				return null;
 	}
 
 	@Override
 	public Date getEffectiveDateForExistingSubscriptons() {
-		// TODO Auto-generated method stub
-		return null;
+				return null;
 	}
 
 	@Override
 	public PlanPhase findPhase(String name) throws CatalogApiException {
-		// TODO Auto-generated method stub
-		return null;
+				return null;
 	}
 
 	@Override
 	public DateTime dateOfFirstRecurringNonZeroCharge(
 			DateTime subscriptionStartDate) {
-		// TODO Auto-generated method stub
-		return null;
+				return null;
 	}
 
 }
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java
index 7990084..9aede3c 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiAddOn.java
@@ -324,7 +324,6 @@ public class TestUserApiAddOn extends TestApiBase {
         }
     }
 
-    //TODO MDW - debugging reenable if you find this
     @Test(enabled=true, groups={"slow"})
     public void testAddonCreateWithSubscriptionAlign() {
 
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 32d444d..b982a3f 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
@@ -16,11 +16,11 @@
 
 package com.ning.billing.invoice;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.SortedSet;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
@@ -37,18 +37,18 @@ import com.ning.billing.entitlement.api.billing.BillingEvent;
 import com.ning.billing.entitlement.api.billing.EntitlementBillingApiException;
 import com.ning.billing.entitlement.api.user.SubscriptionEvent;
 import com.ning.billing.invoice.api.Invoice;
-import com.ning.billing.invoice.api.InvoiceCreationEvent;
-import com.ning.billing.invoice.api.InvoiceNotifier;
 import com.ning.billing.invoice.api.InvoiceApiException;
+import com.ning.billing.invoice.api.InvoiceCreationEvent;
 import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.InvoiceNotifier;
 import com.ning.billing.invoice.api.user.DefaultEmptyInvoiceEvent;
 import com.ning.billing.invoice.api.user.DefaultInvoiceCreationEvent;
 import com.ning.billing.invoice.dao.InvoiceDao;
-import com.ning.billing.invoice.model.BillingEventSet;
 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.api.BillingApi;
+import com.ning.billing.junction.api.BillingEventSet;
 import com.ning.billing.util.bus.Bus;
 import com.ning.billing.util.bus.Bus.EventBusException;
 import com.ning.billing.util.bus.BusEvent;
@@ -145,17 +145,21 @@ public class InvoiceDispatcher {
             final boolean dryRun, final CallContext context) throws InvoiceApiException {
         try {
             Account account = accountUserApi.getAccountById(accountId);
-            SortedSet<BillingEvent> events = billingApi.getBillingEventsForAccountAndUpdateAccountBCD(accountId);
-            BillingEventSet billingEvents = new BillingEventSet(events);
+            BillingEventSet billingEvents = billingApi.getBillingEventsForAccountAndUpdateAccountBCD(accountId);
+            
+            List<Invoice> invoices = new ArrayList<Invoice>();
+            if (!billingEvents.isAccountAutoInvoiceOff()) {
+                invoices = invoiceDao.getInvoicesByAccount(accountId); //no need to fetch, invoicing is off on this account
+            } 
 
             Currency targetCurrency = account.getCurrency();
 
-            List<Invoice> invoices = invoiceDao.getInvoicesByAccount(accountId);
+            
             Invoice invoice = generator.generateInvoice(accountId, billingEvents, invoices, targetDate, targetCurrency);
 
             if (invoice == null) {
                 log.info("Generated null invoice.");
-                outputDebugData(events, invoices);
+                outputDebugData(billingEvents, invoices);
                 if (!dryRun) {
                     BusEvent event = new DefaultEmptyInvoiceEvent(accountId, clock.getUTCNow(), context.getUserToken());
                     postEvent(event, accountId);
@@ -168,7 +172,7 @@ public class InvoiceDispatcher {
                         log.info(item.toString());
                     }
                 }
-                outputDebugData(events, invoices);
+                outputDebugData(billingEvents, invoices);
                 if (!dryRun) {
                     invoiceDao.create(invoice, context);
 
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java
index f20d07a..8f4554d 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java
@@ -41,6 +41,7 @@ import com.ning.billing.entitlement.api.billing.BillingModeType;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.junction.api.BillingEventSet;
 import com.ning.billing.util.clock.Clock;
 
 public class DefaultInvoiceGenerator implements InvoiceGenerator {
@@ -64,18 +65,24 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
                                          @Nullable final List<Invoice> existingInvoices,
                                          DateTime targetDate,
                                          final Currency targetCurrency) throws InvoiceApiException {
-        if ((events == null) || (events.size() == 0)) {
+        if ((events == null) || (events.size() == 0) || events.isAccountAutoInvoiceOff()) {
             return null;
         }
 
         validateTargetDate(targetDate);
-
-        Collections.sort(events);
+        //TODO MDW can use subscription Id - not bundle
+        //TODO MDW worry about null sub id
 
         List<InvoiceItem> existingItems = new ArrayList<InvoiceItem>();
         if (existingInvoices != null) {
             for (Invoice invoice : existingInvoices) {
-                existingItems.addAll(invoice.getInvoiceItems());
+                for(InvoiceItem item : invoice.getInvoiceItems()) {
+                    if(item.getSubscriptionId() == null || // Always include migration invoices, credits etc.  
+                      !events.getSubscriptionIdsWithAutoInvoiceOff()
+                            .contains(item.getSubscriptionId())) { //don't add items with auto_invoice_off tag 
+                        existingItems.add(item);
+                    }
+                }
             }
 
             Collections.sort(existingItems);
@@ -228,16 +235,36 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
     private List<InvoiceItem> generateInvoiceItems(final UUID invoiceId, final UUID accountId, final BillingEventSet events,
                                                    final DateTime targetDate, final Currency currency) throws InvoiceApiException {
         List<InvoiceItem> items = new ArrayList<InvoiceItem>();
+        
+        if(events.size() == 0) {
+            return items;
+        }
 
-        for (int i = 0; i < events.size(); i++) {
-            BillingEvent thisEvent = events.get(i);
-            BillingEvent nextEvent = events.isLast(thisEvent) ? null : events.get(i + 1);
-            if (nextEvent != null) {
-                nextEvent = (thisEvent.getSubscription().getId() == nextEvent.getSubscription().getId()) ? nextEvent : null;
-            }
+        Iterator<BillingEvent> eventIt = events.iterator();
 
-            items.addAll(processEvents(invoiceId, accountId, thisEvent, nextEvent, targetDate, currency));
+        BillingEvent nextEvent = eventIt.next();
+        while(eventIt.hasNext()) {
+            BillingEvent thisEvent = nextEvent;
+            nextEvent = eventIt.next();
+            if(!events.getSubscriptionIdsWithAutoInvoiceOff().
+                    contains(thisEvent.getSubscription().getId())) { // don't consider events for subscriptions that have auto_invoice_off
+                BillingEvent adjustedNextEvent = (thisEvent.getSubscription().getId() == nextEvent.getSubscription().getId()) ? nextEvent : null;
+                items.addAll(processEvents(invoiceId, accountId, thisEvent, adjustedNextEvent, targetDate, currency));
+            }
         }
+        items.addAll(processEvents(invoiceId, accountId, nextEvent, null, targetDate, currency));
+        
+// The above should reproduce the semantics of the code below using iterator instead of list.
+//
+//        for (int i = 0; i < events.size(); i++) {
+//            BillingEvent thisEvent = events.get(i);
+//            BillingEvent nextEvent = events.isLast(thisEvent) ? null : events.get(i + 1);
+//            if (nextEvent != null) {
+//                nextEvent = (thisEvent.getSubscription().getId() == nextEvent.getSubscription().getId()) ? nextEvent : null;
+//            }
+//
+//            items.addAll(processEvents(invoiceId, accountId, thisEvent, nextEvent, targetDate, currency));
+//        }
 
         return items;
     }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceGenerator.java b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceGenerator.java
index f903087..e1c7e00 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceGenerator.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/InvoiceGenerator.java
@@ -16,15 +16,17 @@
 
 package com.ning.billing.invoice.model;
 
+import java.util.List;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import org.joda.time.DateTime;
+
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
-import com.ning.billing.invoice.api.InvoiceItem;
-import org.joda.time.DateTime;
-
-import javax.annotation.Nullable;
-import java.util.List;
-import java.util.UUID;
+import com.ning.billing.junction.api.BillingEventSet;
 
 public interface InvoiceGenerator {
     public Invoice generateInvoice(UUID accountId, @Nullable BillingEventSet events, @Nullable List<Invoice> existingInvoices,
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 efedbaf..05f7179 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
@@ -19,11 +19,8 @@ package com.ning.billing.invoice.api.migration;
 import java.math.BigDecimal;
 import java.util.Collection;
 import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
 import java.util.UUID;
 
-import com.ning.billing.invoice.tests.InvoicingTestBase;
 import org.apache.commons.io.IOUtils;
 import org.joda.time.DateTime;
 import org.slf4j.Logger;
@@ -45,10 +42,10 @@ import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.entitlement.api.SubscriptionTransitionType;
-import com.ning.billing.entitlement.api.billing.BillingEvent;
 import com.ning.billing.entitlement.api.billing.BillingModeType;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.invoice.InvoiceDispatcher;
+import com.ning.billing.invoice.MockBillingEventSet;
 import com.ning.billing.invoice.TestInvoiceDispatcher;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceMigrationApi;
@@ -58,7 +55,9 @@ 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.invoice.notification.NullInvoiceNotifier;
+import com.ning.billing.invoice.tests.InvoicingTestBase;
 import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.junction.api.BillingEventSet;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
 import com.ning.billing.util.bus.BusService;
@@ -179,7 +178,7 @@ public class TestDefaultInvoiceMigrationApi extends InvoicingTestBase {
 		Subscription subscription =  BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class);
         ((ZombieControl)subscription).addResult("getId", subscriptionId);
         ((ZombieControl)subscription).addResult("getBundleId", new UUID(0L,0L));
-		SortedSet<BillingEvent> events = new TreeSet<BillingEvent>();
+		BillingEventSet events = new MockBillingEventSet();
 		Plan plan = MockPlan.createBicycleNoTrialEvergreen1USD();
 		PlanPhase planPhase = MockPlanPhase.create1USDMonthlyEvergreen();
 		DateTime effectiveDate = new DateTime().minusDays(1);
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 809c141..e47e152 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
@@ -28,10 +28,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
-import com.ning.billing.util.dao.ObjectType;
-import com.ning.billing.util.tag.Tag;
-import com.ning.billing.util.tag.dao.AuditedTagDao;
-import com.ning.billing.util.tag.dao.TagDao;
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
@@ -49,17 +45,22 @@ import com.ning.billing.entitlement.api.SubscriptionTransitionType;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
 import com.ning.billing.entitlement.api.billing.BillingModeType;
 import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.invoice.MockBillingEventSet;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.api.InvoicePayment;
-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.api.BillingEventSet;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.util.dao.ObjectType;
 import com.ning.billing.util.tag.ControlTagType;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.dao.AuditedTagDao;
+import com.ning.billing.util.tag.dao.TagDao;
 
 @Test(groups = {"slow", "invoicing", "invoicing-invoiceDao"})
 public class InvoiceDaoTests extends InvoiceDaoTestBase {
@@ -417,7 +418,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
                 recurringPrice.getPrice(currency), currency, BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
                 "testEvent1", 1L, SubscriptionTransitionType.CREATE);
 
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         events.add(event1);
 
         Invoice invoice1 = generator.generateInvoice(accountId, events, invoiceList, targetDate, Currency.USD);
@@ -466,7 +467,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
         BillingEvent event = createMockBillingEvent(null, subscription, effectiveDate, plan, phase, null,
                 recurringPrice.getPrice(currency), currency, BillingPeriod.MONTHLY, 15, BillingModeType.IN_ADVANCE,
                 "testEvent", 1L, SubscriptionTransitionType.CREATE);
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         events.add(event);
 
         DateTime targetDate = buildDateTime(2011, 1, 15);
@@ -505,7 +506,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
         BillingEvent event1 = createMockBillingEvent(null, subscription, effectiveDate1, plan, phase1, fixedPrice.getPrice(currency),
                 null, currency, BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
                 "testEvent1", 1L, SubscriptionTransitionType.CREATE);
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         events.add(event1);
 
         UUID accountId = UUID.randomUUID();
@@ -539,7 +540,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
 
     @Test
     public void testInvoiceForEmptyEventSet() throws InvoiceApiException {
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         Invoice invoice = generator.generateInvoice(UUID.randomUUID(), events, null, new DateTime(), Currency.USD);
         assertNull(invoice);
     }
@@ -565,7 +566,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
                 fixedPrice.getPrice(currency), null, currency,
                 BillingPeriod.MONTHLY, 1, BillingModeType.IN_ADVANCE,
                 "testEvent1", 1L, SubscriptionTransitionType.CREATE);
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         events.add(event1);
 
         DateTime effectiveDate2 = effectiveDate1.plusDays(30);
@@ -604,7 +605,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
         PlanPhase phase2 = BrainDeadProxyFactory.createBrainDeadProxyFor(PlanPhase.class);
         ((ZombieControl) phase2).addResult("getName", "plan-phase2");
 
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         List<Invoice> invoices = new ArrayList<Invoice>();
 
         BillingEvent event1 = createMockBillingEvent(null, subscription, targetDate1, plan, phase1, null,
@@ -648,7 +649,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
                 TEN, currency,
                 BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
                 "testEvent1", 1L, SubscriptionTransitionType.CHANGE);
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         events.add(event1);
 
         Invoice invoice = generator.generateInvoice(UUID.randomUUID(), events, null, targetDate1, Currency.USD);
@@ -679,7 +680,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
                 TEN, currency,
                 BillingPeriod.MONTHLY, 31, BillingModeType.IN_ADVANCE,
                 "testEvent1", 1L, SubscriptionTransitionType.CHANGE);
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         events.add(event1);
 
         Invoice invoice = generator.generateInvoice(UUID.randomUUID(), events, null, targetDate1, Currency.USD);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/MockBillingEventSet.java b/invoice/src/test/java/com/ning/billing/invoice/MockBillingEventSet.java
new file mode 100644
index 0000000..3ab1f0d
--- /dev/null
+++ b/invoice/src/test/java/com/ning/billing/invoice/MockBillingEventSet.java
@@ -0,0 +1,49 @@
+/*
+ * 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.invoice;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import com.ning.billing.entitlement.api.billing.BillingEvent;
+import com.ning.billing.junction.api.BillingEventSet;
+
+public class MockBillingEventSet extends TreeSet<BillingEvent> implements BillingEventSet {
+
+    private static final long serialVersionUID = 1L;
+
+    private boolean isAccountInvoiceOff;
+    private List<UUID> subscriptionIdsWithAutoInvoiceOff = new ArrayList<UUID>();
+    
+    @Override
+    public boolean isLast(BillingEvent event) {
+        return isAccountInvoiceOff;
+    }
+
+    @Override
+    public boolean isAccountAutoInvoiceOff() {
+        return false;
+    }
+
+    @Override
+    public List<UUID> getSubscriptionIdsWithAutoInvoiceOff() {
+        return subscriptionIdsWithAutoInvoiceOff;
+    }
+
+}
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 992274d..679049a 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
@@ -16,16 +16,10 @@
 
 package com.ning.billing.invoice;
 
-import java.io.IOException;
 import java.math.BigDecimal;
 import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
 import java.util.UUID;
 
-import com.ning.billing.invoice.api.InvoiceNotifier;
-import com.ning.billing.invoice.notification.NullInvoiceNotifier;
-import com.ning.billing.invoice.tests.InvoicingTestBase;
 import org.apache.commons.io.IOUtils;
 import org.joda.time.DateTime;
 import org.slf4j.Logger;
@@ -47,18 +41,20 @@ import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.entitlement.api.SubscriptionTransitionType;
-import com.ning.billing.entitlement.api.billing.BillingEvent;
 import com.ning.billing.entitlement.api.billing.BillingModeType;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
+import com.ning.billing.invoice.api.InvoiceNotifier;
 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.invoice.notification.NullInvoiceNotifier;
+import com.ning.billing.invoice.tests.InvoicingTestBase;
 import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.junction.api.BillingEventSet;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
-import com.ning.billing.mock.glue.MockJunctionModule;
 import com.ning.billing.util.bus.BusService;
 import com.ning.billing.util.bus.DefaultBusService;
 import com.ning.billing.util.callcontext.CallContext;
@@ -145,7 +141,7 @@ public class TestInvoiceDispatcher extends InvoicingTestBase {
 		Subscription subscription =  BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class);
         ((ZombieControl)subscription).addResult("getId", subscriptionId);
         ((ZombieControl)subscription).addResult("getBundleId", new UUID(0L,0L));
-		SortedSet<BillingEvent> events = new TreeSet<BillingEvent>();
+        BillingEventSet events = new MockBillingEventSet();
 		Plan plan = MockPlan.createBicycleNoTrialEvergreen1USD();
 		PlanPhase planPhase = MockPlanPhase.create1USDMonthlyEvergreen();
 		DateTime effectiveDate = new DateTime().minusDays(1);
@@ -184,5 +180,7 @@ public class TestInvoiceDispatcher extends InvoicingTestBase {
 		Assert.assertEquals(invoices.size(),1);
 
 	}
+    
+    //MDW add a test to cover when the account auto-invoice-off tag is present
 
 }
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 68e071b..bf63662 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
@@ -28,10 +28,6 @@ import java.util.UUID;
 
 import javax.annotation.Nullable;
 
-import com.ning.billing.invoice.api.InvoiceItem;
-import com.ning.billing.invoice.model.CreditInvoiceItem;
-import com.ning.billing.invoice.model.DefaultInvoice;
-import com.ning.billing.invoice.model.DefaultInvoicePayment;
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
@@ -50,13 +46,18 @@ import com.ning.billing.entitlement.api.SubscriptionTransitionType;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
 import com.ning.billing.entitlement.api.billing.BillingModeType;
 import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.invoice.MockBillingEventSet;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
-import com.ning.billing.invoice.model.BillingEventSet;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.model.CreditInvoiceItem;
 import com.ning.billing.invoice.model.DefaultInvoiceGenerator;
+import com.ning.billing.invoice.model.DefaultInvoice;
+import com.ning.billing.invoice.model.DefaultInvoicePayment;
 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.api.BillingEventSet;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
 import com.ning.billing.util.clock.Clock;
@@ -99,7 +100,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testWithEmptyEventSet() throws InvoiceApiException {
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
 
         UUID accountId = UUID.randomUUID();
         Invoice invoice = generator.generateInvoice(accountId, events, null, new DateTime(), Currency.USD);
@@ -109,7 +110,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testWithSingleMonthlyEvent() throws InvoiceApiException, CatalogApiException {
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
 
         Subscription sub = createZombieSubscription();
         DateTime startDate = buildDateTime(2011, 9, 1);
@@ -145,7 +146,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testWithSingleMonthlyEventWithLeadingProRation() throws InvoiceApiException, CatalogApiException {
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
 
         Subscription sub = createZombieSubscription();
         DateTime startDate = buildDateTime(2011, 9, 1);
@@ -171,7 +172,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testTwoMonthlySubscriptionsWithAlignedBillingDates() throws InvoiceApiException, CatalogApiException {
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
 
         Plan plan1 = new MockPlan();
         BigDecimal rate1 = FIVE;
@@ -200,7 +201,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testOnePlan_TwoMonthlyPhases_ChangeImmediate() throws InvoiceApiException, CatalogApiException {
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
 
         Plan plan1 = new MockPlan();
         BigDecimal rate1 = FIVE;
@@ -237,7 +238,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testOnePlan_ThreeMonthlyPhases_ChangeEOT() throws InvoiceApiException, CatalogApiException {
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
 
         Plan plan1 = new MockPlan();
         BigDecimal rate1 = FIVE;
@@ -268,7 +269,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testSingleEventWithExistingInvoice() throws InvoiceApiException, CatalogApiException {
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
 
         Subscription sub = createZombieSubscription();
         DateTime startDate = buildDateTime(2011, 9, 1);
@@ -344,7 +345,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
         BigDecimal expectedAmount;
         List<Invoice> invoices = new ArrayList<Invoice>();
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
 
         // on 1/5/2011, create subscription 1 (trial)
         events.add(createBillingEvent(subscriptionId1, plan1StartDate, plan1, plan1Phase1, 5));
@@ -457,7 +458,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     public void testZeroDollarEvents() throws InvoiceApiException, CatalogApiException {
         Plan plan = new MockPlan();
         PlanPhase planPhase = createMockMonthlyPlanPhase(ZERO);
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         DateTime targetDate = buildDateTime(2011, 1, 1);
         events.add(createBillingEvent(UUID.randomUUID(), targetDate, plan, planPhase, 1));
 
@@ -470,7 +471,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     public void testEndDateIsCorrect() throws InvoiceApiException, CatalogApiException {
         Plan plan = new MockPlan();
         PlanPhase planPhase = createMockMonthlyPlanPhase(ZERO);
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         DateTime targetDate = new DateTime();
         events.add(createBillingEvent(UUID.randomUUID(), targetDate, plan, planPhase, targetDate.getDayOfMonth()));
 
@@ -495,7 +496,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
         DateTime changeDate = new DateTime("2012-04-1T00:00:00.000-08:00");
 
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
 
         BillingEvent event1 = createMockBillingEvent(null, subscription, new DateTime("2012-01-1T00:00:00.000-08:00"),
                 plan, phase1,
@@ -532,7 +533,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         BigDecimal fixedCost = TEN;
         PlanPhase phase1 = createMockMonthlyPlanPhase(monthlyRate, fixedCost, PhaseType.TRIAL);
 
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         UUID subscriptionId = UUID.randomUUID();
         UUID accountId = UUID.randomUUID();
 
@@ -568,7 +569,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         PlanPhase phase1 = createMockMonthlyPlanPhase(null, fixedCost1, PhaseType.TRIAL);
         PlanPhase phase2 = createMockMonthlyPlanPhase(null, fixedCost2, PhaseType.EVERGREEN);
 
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         UUID subscriptionId = UUID.randomUUID();
         UUID accountId = UUID.randomUUID();
 
@@ -599,7 +600,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testNutsFailure() throws InvoiceApiException, CatalogApiException {
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         UUID subscriptionId = UUID.randomUUID();
         UUID accountId = UUID.randomUUID();
         final int BILL_CYCLE_DAY = 15;
@@ -655,7 +656,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     @Test(expectedExceptions = {InvoiceApiException.class})
     public void testTargetDateRestrictionFailure() throws InvoiceApiException, CatalogApiException {
         DateTime targetDate = DateTime.now().plusMonths(60);
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         Plan plan1 = new MockPlan();
         PlanPhase phase1 = createMockMonthlyPlanPhase(null, ZERO, PhaseType.TRIAL);
         events.add(createBillingEvent(UUID.randomUUID(), DateTime.now(), plan1, phase1, 1));
@@ -728,7 +729,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         MockInternationalPrice price20 = new MockInternationalPrice(new DefaultPrice(TWENTY, Currency.USD));
         PlanPhase basePlanEvergreen = new MockPlanPhase(price10, null, BillingPeriod.MONTHLY, PhaseType.EVERGREEN);
 
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         events.add(createBillingEvent(baseSubscription.getId(), april25, basePlan, basePlanEvergreen, 25));
 
         // generate invoice
@@ -761,7 +762,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
         // perform a repair (change base plan; remove one add-on)
         // event stream should include just two plans
-        BillingEventSet newEvents = new BillingEventSet();
+        MockBillingEventSet newEvents = new MockBillingEventSet();
         Plan basePlan2 = new MockPlan("base plan 2");
         MockInternationalPrice price13 = new MockInternationalPrice(new DefaultPrice(THIRTEEN, Currency.USD));
         PlanPhase basePlan2Phase = new MockPlanPhase(price13, null, BillingPeriod.MONTHLY, PhaseType.EVERGREEN);
@@ -790,7 +791,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         MockInternationalPrice price10 = new MockInternationalPrice(new DefaultPrice(TEN, Currency.USD));
         PlanPhase originalPlanEvergreen = new MockPlanPhase(price10, null, BillingPeriod.MONTHLY, PhaseType.EVERGREEN);
 
-        BillingEventSet events = new BillingEventSet();
+        BillingEventSet events = new MockBillingEventSet();
         events.add(createBillingEvent(originalSubscription.getId(), april25, originalPlan, originalPlanEvergreen, 25));
 
         Invoice invoice1 = generator.generateInvoice(accountId, events, null, april25, Currency.USD);
@@ -837,14 +838,13 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test(enabled=false)
     public void testAutoInvoiceOff() {
-        BillingEventSet eventSet = new BillingEventSet();
-
+        //BillingEventSet eventSet = new MockBillingEventSet();
         fail();
     }
 
     @Test
     public void testAccountCredit() throws CatalogApiException, InvoiceApiException {
-        BillingEventSet billingEventSet = new BillingEventSet();
+        BillingEventSet billingEventSet = new MockBillingEventSet();
 
         DateTime startDate = new DateTime(2012, 3, 1, 0, 0, 0, 0);
         UUID accountId = UUID.randomUUID();
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/TestDefaultInvoiceGeneratorWithAutoInvoiceOff.java b/invoice/src/test/java/com/ning/billing/invoice/tests/TestDefaultInvoiceGeneratorWithAutoInvoiceOff.java
new file mode 100644
index 0000000..b34ee4c
--- /dev/null
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/TestDefaultInvoiceGeneratorWithAutoInvoiceOff.java
@@ -0,0 +1,23 @@
+/*
+ * 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.invoice.tests;
+
+public class TestDefaultInvoiceGeneratorWithAutoInvoiceOff {
+
+    
+    //TODO MDW - write this test TestDefaultInvoiceGeneratorWithAutoInvoiceOff
+}

junction/pom.xml 19(+12 -7)

diff --git a/junction/pom.xml b/junction/pom.xml
index 4efa966..1824a28 100644
--- a/junction/pom.xml
+++ b/junction/pom.xml
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- ~ 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. -->
+	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. -->
 
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
@@ -73,6 +73,11 @@
             <artifactId>killbill-catalog</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <scope>test</scope>
+        </dependency>
          <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BlockingCalculator.java b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BlockingCalculator.java
index 999c5d6..e33c063 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BlockingCalculator.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/BlockingCalculator.java
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.SortedSet;
 import java.util.TreeSet;
 import java.util.UUID;
+import java.util.concurrent.atomic.AtomicLong;
 
 import org.joda.time.DateTime;
 
@@ -36,12 +37,13 @@ import com.ning.billing.entitlement.api.SubscriptionTransitionType;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
 import com.ning.billing.entitlement.api.billing.BillingModeType;
 import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.junction.api.Blockable;
 import com.ning.billing.junction.api.BlockingApi;
 import com.ning.billing.junction.api.BlockingState;
 import com.ning.billing.junction.api.DefaultBlockingState;
 
 public class BlockingCalculator {
+    private static AtomicLong globaltotalOrder = new AtomicLong();
+    
     private final BlockingApi blockingApi;
 
     protected static class DisabledDuration {
@@ -196,7 +198,7 @@ public class BlockingCalculator {
         final BillingModeType billingModeType = previousEvent.getBillingMode();
         final BillingPeriod billingPeriod = previousEvent.getBillingPeriod();
         final SubscriptionTransitionType type = SubscriptionTransitionType.CANCEL;
-        final Long totalOrdering = 0L; //TODO
+        final Long totalOrdering = globaltotalOrder.getAndIncrement(); 
 
         return new DefaultBillingEvent(account, subscription, effectiveDate, plan, planPhase,
                 fixedPrice, recurringPrice, currency,
@@ -218,7 +220,7 @@ public class BlockingCalculator {
         final BillingModeType billingModeType = previousEvent.getBillingMode();
         final BillingPeriod billingPeriod = previousEvent.getBillingPeriod();
         final SubscriptionTransitionType type = SubscriptionTransitionType.RE_CREATE;
-        final Long totalOrdering = 0L; //TODO
+        final Long totalOrdering = globaltotalOrder.getAndIncrement();  
 
         return new DefaultBillingEvent(account, subscription, effectiveDate, plan, planPhase,
                 fixedPrice, recurringPrice, currency,
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
index 43e8a2a..cee92dc 100644
--- 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
@@ -17,7 +17,7 @@
 package com.ning.billing.junction.plumbing.billing;
 
 import java.util.List;
-import java.util.SortedSet;
+import java.util.Map;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
@@ -41,10 +41,14 @@ import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionEvent;
 import com.ning.billing.junction.api.BillingApi;
 import com.ning.billing.junction.api.BillingEventSet;
+import com.ning.billing.util.api.TagUserApi;
 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.dao.ObjectType;
+import com.ning.billing.util.tag.ControlTagType;
+import com.ning.billing.util.tag.Tag;
 
 public class DefaultBillingApi implements BillingApi {
     private static final String API_USER_NAME = "Billing Api";
@@ -56,12 +60,12 @@ public class DefaultBillingApi implements BillingApi {
     private final EntitlementUserApi entitlementUserApi;
     private final CatalogService catalogService;
     private final BlockingCalculator blockCalculator;
-//    private final TagUserApi tagApi;
+    private final TagUserApi tagApi;
 
     @Inject
     public DefaultBillingApi(final ChargeThruApi chargeThruApi, final CallContextFactory factory, final AccountUserApi accountApi, 
             final BillCycleDayCalculator bcdCalculator, final EntitlementUserApi entitlementUserApi, final BlockingCalculator blockCalculator,
-            final CatalogService catalogService) { //, final TagUserApi tagApi) {
+            final CatalogService catalogService, final TagUserApi tagApi) {
 
         this.chargeThruApi = chargeThruApi;
         this.accountApi = accountApi;
@@ -70,46 +74,28 @@ public class DefaultBillingApi implements BillingApi {
         this.entitlementUserApi = entitlementUserApi;
         this.catalogService = catalogService;
         this.blockCalculator = blockCalculator;
-  //      this.tagApi = tagApi;
+        this.tagApi = tagApi;
     }
 
     @Override
-    public SortedSet<BillingEvent> getBillingEventsForAccountAndUpdateAccountBCD(final UUID accountId) {
+    public BillingEventSet getBillingEventsForAccountAndUpdateAccountBCD(final UUID accountId) {
         CallContext context = factory.createCallContext(API_USER_NAME, CallOrigin.INTERNAL, UserType.SYSTEM);
 
         List<SubscriptionBundle> bundles = entitlementUserApi.getBundlesForAccount(accountId);
-        BillingEventSet result = new DefaultBillingEventSet();
+        DefaultBillingEventSet result = new DefaultBillingEventSet();
 
         try {
             Account account = accountApi.getAccountById(accountId);
-            
-
-            for (final SubscriptionBundle bundle: bundles) {
-                List<Subscription> subscriptions = entitlementUserApi.getSubscriptionsForBundle(bundle.getId());
-
-                for (final Subscription subscription: subscriptions) {
-                    for (final SubscriptionEvent 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(), catalogService.getFullCatalog());
-                            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);
-                        }
 
-                    }
-                }
+            // Check to see if billing is off for the account
+            Map<String,Tag> accountTags = tagApi.getTags(accountId,ObjectType.ACCOUNT);
+            if(accountTags.get(ControlTagType.AUTO_INVOICING_OFF.name()) != null) {
+                result.setAccountAutoInvoiceIsOff(true);
+                return result; // billing is off, we are done
             }
+
+            addBillingEventsForBundles(bundles, account, context, result);         
+           
         } catch (AccountApiException e) {
             log.warn("Failed while getting BillingEvent", e);
         }
@@ -117,6 +103,48 @@ public class DefaultBillingApi implements BillingApi {
         return result;
     }
 
+    private void addBillingEventsForBundles(List<SubscriptionBundle> bundles, Account account, CallContext context,
+            DefaultBillingEventSet result) {
+        
+        for (final SubscriptionBundle bundle: bundles) {
+            List<Subscription> subscriptions = entitlementUserApi.getSubscriptionsForBundle(bundle.getId());
+
+            //Check if billing is off for the bundle
+            Map<String,Tag> bundleTags = tagApi.getTags(bundle.getId(), ObjectType.BUNDLE);
+            if(bundleTags.get(ControlTagType.AUTO_INVOICING_OFF.name()) != null) {
+                 for (final Subscription subscription: subscriptions) { // billing is off so list sub ids in set to be excluded
+                    result.getSubscriptionIdsWithAutoInvoiceOff().add(subscription.getId());
+                }
+            } else { // billing is not off
+                addBillingEventsForSubscription(subscriptions, bundle, account, context, result);                 
+            }
+        }        
+    }
+
+    private void addBillingEventsForSubscription(List<Subscription> subscriptions, SubscriptionBundle bundle, Account account, CallContext context, DefaultBillingEventSet result) {
+        for (final Subscription subscription: subscriptions) {
+            for (final SubscriptionEvent 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(), catalogService.getFullCatalog());
+                    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);
+                }
+
+            }
+        }
+    }
 
     @Override
     public UUID getAccountIdFromSubscriptionId(UUID subscriptionId) throws EntitlementBillingApiException {
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingEventSet.java b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingEventSet.java
index fdda46c..0962a73 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingEventSet.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingEventSet.java
@@ -55,5 +55,8 @@ public class DefaultBillingEventSet extends TreeSet<BillingEvent> implements Sor
         this.subscriptionIdsWithAutoInvoiceOff = subscriptionIdsWithAutoInvoiceOff;
     }
     
+    public boolean isLast(final BillingEvent event) {
+        return last() == event;
+    }
     
 }
diff --git a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBlockingCalculator.java b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBlockingCalculator.java
index 435ee50..b501c98 100644
--- a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBlockingCalculator.java
+++ b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBlockingCalculator.java
@@ -556,7 +556,7 @@ public class TestBlockingCalculator {
         final BillingModeType billingModeType = BillingModeType.IN_ADVANCE;
         final BillingPeriod billingPeriod = BillingPeriod.MONTHLY;
         final SubscriptionTransitionType type = SubscriptionTransitionType.CHANGE;
-        final Long totalOrdering = 0L; //TODO
+        final Long totalOrdering = 0L; 
 
         return new DefaultBillingEvent(account, subscription, effectiveDate, plan, planPhase,
                 fixedPrice, recurringPrice, currency,
diff --git a/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java b/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java
index 9f45075..d13fdef 100644
--- a/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java
+++ b/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java
@@ -29,6 +29,7 @@ import com.ning.billing.overdue.listener.OverdueListener;
 import com.ning.billing.overdue.service.DefaultOverdueService;
 import com.ning.billing.util.notificationq.NotificationQueue;
 import com.ning.billing.util.notificationq.NotificationQueueService;
+import com.ning.billing.util.notificationq.NotificationQueueService.NoSuchNotificationQueue;
 import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueAlreadyExists;
 import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueHandler;
 
@@ -94,6 +95,11 @@ public class DefaultOverdueCheckNotifier implements  OverdueCheckNotifier {
     public void stop() {
         if (overdueQueue != null) {
         	overdueQueue.stopQueue();
+        	try {
+        	    notificationQueueService.deleteNotificationQueue(overdueQueue.getServiceName(), overdueQueue.getQueueName());
+        	} catch (NoSuchNotificationQueue e) {
+        	    log.error("Error deleting a queue by its own name - this should never happen", e);
+        	}
         }
     }
 
diff --git a/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java b/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
index 958d8b9..cc0acb2 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
@@ -58,7 +58,7 @@ public class OverdueStateApplicator<T extends Blockable>{
             }
         } catch(OverdueApiException e) {
             if(e.getCode() != ErrorCode.OVERDUE_NO_REEVALUATION_INTERVAL.getCode()) {
-                new OverdueError(e);
+                throw new OverdueError(e);
             }
         }
 
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 6d3b967..0abc240 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
@@ -46,7 +46,7 @@ public class OverdueWrapperFactory {
     private final OverdueStateApplicator<SubscriptionBundle> overdueStateApplicatorBundle;
     private final BlockingApi api;
     private final Clock clock;
-    private OverdueStateSet<SubscriptionBundle> overdueStates;
+    private OverdueConfig config;
 
     @Inject
     public OverdueWrapperFactory(BlockingApi api, Clock clock, 
@@ -64,7 +64,7 @@ public class OverdueWrapperFactory {
     public <T extends Blockable> OverdueWrapper<T> createOverdueWrapperFor(T bloackable) throws OverdueError {
   
         if(bloackable instanceof SubscriptionBundle) {
-            return (OverdueWrapper<T>)new OverdueWrapper<SubscriptionBundle>((SubscriptionBundle)bloackable, api, overdueStates, 
+            return (OverdueWrapper<T>)new OverdueWrapper<SubscriptionBundle>((SubscriptionBundle)bloackable, api, getOverdueStateSetBundle(), 
                     clock, billingStateCalcuatorBundle, overdueStateApplicatorBundle);
         } else {
             throw new OverdueError(ErrorCode.OVERDUE_TYPE_NOT_SUPPORTED, bloackable.getId(), bloackable.getClass());
@@ -79,7 +79,7 @@ public class OverdueWrapperFactory {
             switch (state.getType()) {
             case SUBSCRIPTION_BUNDLE : {
                 SubscriptionBundle bundle = entitlementApi.getBundleFromId(id);
-                return (OverdueWrapper<T>) new OverdueWrapper<SubscriptionBundle>(bundle, api, overdueStates, 
+                return (OverdueWrapper<T>) new OverdueWrapper<SubscriptionBundle>(bundle, api, getOverdueStateSetBundle(), 
                         clock, billingStateCalcuatorBundle, overdueStateApplicatorBundle );
             }
             default : {
@@ -92,11 +92,9 @@ public class OverdueWrapperFactory {
         }
     }
     
-    public void setOverdueConfig(OverdueConfig config) {
-        if(config != null) {
-            overdueStates = config.getBundleStateSet();
-        } else {
-            overdueStates = new DefaultOverdueStateSet<SubscriptionBundle>() {
+    private OverdueStateSet<SubscriptionBundle> getOverdueStateSetBundle() {
+        if(config == null || config.getBundleStateSet() == null) {
+            return new DefaultOverdueStateSet<SubscriptionBundle>() {
 
                 @SuppressWarnings("unchecked")
                 @Override
@@ -104,7 +102,13 @@ public class OverdueWrapperFactory {
                     return new DefaultOverdueState[0];
                 }
             };
+        } else {
+           return config.getBundleStateSet();
         }
     }
+    
+    public void setOverdueConfig(OverdueConfig config) {   
+        this.config = config;
+    }
 
 }
diff --git a/overdue/src/test/java/com/ning/billing/overdue/applicator/ApplicatorMockJunctionModule.java b/overdue/src/test/java/com/ning/billing/overdue/applicator/ApplicatorMockJunctionModule.java
index 25721d5..0dcf12e 100644
--- a/overdue/src/test/java/com/ning/billing/overdue/applicator/ApplicatorMockJunctionModule.java
+++ b/overdue/src/test/java/com/ning/billing/overdue/applicator/ApplicatorMockJunctionModule.java
@@ -48,43 +48,37 @@ public class ApplicatorMockJunctionModule extends MockJunctionModule {
 
                     @Override
                     public Type getType() {
-                        // TODO Auto-generated method stub
+
                         return null;
                     }
 
                     @Override
                     public DateTime getTimestamp() {
-                        // TODO Auto-generated method stub
                         return null;
                     }
 
                     @Override
                     public boolean isBlockChange() {
-                        // TODO Auto-generated method stub
                         return false;
                     }
 
                     @Override
                     public boolean isBlockEntitlement() {
-                        // TODO Auto-generated method stub
                         return false;
                     }
 
                     @Override
                     public boolean isBlockBilling() {
-                        // TODO Auto-generated method stub
                         return false;
                     }
 
                     @Override
                     public int compareTo(BlockingState arg0) {
-                        // TODO Auto-generated method stub
                         return 0;
                     }
 
                     @Override
                     public String getDescription() {
-                        // TODO Auto-generated method stub
                         return null;
                     }
                     
diff --git a/overdue/src/test/java/com/ning/billing/overdue/applicator/TestOverdueStateApplicator.java b/overdue/src/test/java/com/ning/billing/overdue/applicator/TestOverdueStateApplicator.java
index e95740a..ca6f682 100644
--- a/overdue/src/test/java/com/ning/billing/overdue/applicator/TestOverdueStateApplicator.java
+++ b/overdue/src/test/java/com/ning/billing/overdue/applicator/TestOverdueStateApplicator.java
@@ -49,7 +49,7 @@ public class TestOverdueStateApplicator extends OverdueTestBase {
     @Inject
     OverdueStateApplicator<SubscriptionBundle> applicator;
         
-    @Test( groups={"slow"} , enabled = false)
+    @Test( groups={"slow"} , enabled = true)
      public void testApplicator() throws Exception {
          InputStream is = new ByteArrayInputStream(configXml.getBytes());
          config = XMLLoader.getObjectFromStreamNoValidation(is,  OverdueConfig.class);
@@ -73,9 +73,6 @@ public class TestOverdueStateApplicator extends OverdueTestBase {
          applicator.apply(bundle, BlockingApi.CLEAR_STATE_NAME, state);
          checkStateApplied(state);
         
-         
-        //TODO
-        // Check notification is posted with correct time delay
     }
 
 
diff --git a/overdue/src/test/java/com/ning/billing/overdue/OverdueTestBase.java b/overdue/src/test/java/com/ning/billing/overdue/OverdueTestBase.java
index f233a9a..ac5c134 100644
--- a/overdue/src/test/java/com/ning/billing/overdue/OverdueTestBase.java
+++ b/overdue/src/test/java/com/ning/billing/overdue/OverdueTestBase.java
@@ -22,11 +22,12 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
 
+import javax.management.RuntimeErrorException;
+
 import org.apache.commons.io.IOUtils;
 import org.joda.time.DateTime;
 import org.testng.Assert;
 import org.testng.annotations.AfterClass;
-import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Guice;
@@ -50,12 +51,11 @@ import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
 import com.ning.billing.mock.glue.MockClockModule;
 import com.ning.billing.mock.glue.MockInvoiceModule;
-import com.ning.billing.mock.glue.MockJunctionModule;
 import com.ning.billing.mock.glue.MockPaymentModule;
 import com.ning.billing.mock.glue.TestDbiModule;
 import com.ning.billing.overdue.applicator.ApplicatorMockJunctionModule;
-import com.ning.billing.overdue.applicator.TestOverdueStateApplicator;
 import com.ning.billing.overdue.applicator.ApplicatorMockJunctionModule.ApplicatorBlockingApi;
+import com.ning.billing.overdue.applicator.TestOverdueStateApplicator;
 import com.ning.billing.overdue.config.OverdueConfig;
 import com.ning.billing.overdue.glue.DefaultOverdueModule;
 import com.ning.billing.overdue.service.DefaultOverdueService;
@@ -64,6 +64,7 @@ import com.ning.billing.util.bus.BusService;
 import com.ning.billing.util.clock.ClockMock;
 import com.ning.billing.util.glue.BusModule;
 import com.ning.billing.util.glue.NotificationQueueModule;
+import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueAlreadyExists;
 
 //@Guice(modules = {MockJunctionModule.class, MockInvoiceModule.class, DefaultOverdueModule.class})
 @Guice( modules = {DefaultOverdueModule.class, MockClockModule.class, ApplicatorMockJunctionModule.class, CatalogModule.class, MockInvoiceModule.class, MockPaymentModule.class, BusModule.class, NotificationQueueModule.class, TestDbiModule.class})
@@ -119,14 +120,14 @@ public class OverdueTestBase {
 
     @Inject
     protected BlockingApi blockingApi;
-    
+
     @Inject
     protected OverdueWrapperFactory overdueWrapperFactory;
-    
+
     @Inject
     protected OverdueUserApi overdueApi;
-   
-    
+
+
     @Inject
     protected InvoiceUserApi invoiceApi;
 
@@ -135,7 +136,7 @@ public class OverdueTestBase {
     protected String productName;
     protected BillingPeriod term;
     protected String planSetName;
- 
+
     @Inject
     EntitlementUserApi entitlementApi;
 
@@ -153,13 +154,19 @@ public class OverdueTestBase {
         helper.initDb(utilDdl);
     }
 
-  
+
     @BeforeClass(groups = "slow")
     public void setup() throws Exception{
 
         setupMySQL();
         service.registerForBus();
-        service.initialize();
+        try {
+            service.initialize();
+        }catch (RuntimeException e) {
+            if(!(e.getCause() instanceof NotificationQueueAlreadyExists)) {
+                throw e;
+            } 
+        }
         service.start();
     }
 
@@ -198,7 +205,7 @@ public class OverdueTestBase {
         UUID bundleId = UUID.randomUUID();
         ((ZombieControl)bundle).addResult("getId", bundleId);
         ((ZombieControl)bundle).addResult("getAccountId", UUID.randomUUID());
-        
+
         Invoice invoice = BrainDeadProxyFactory.createBrainDeadProxyFor(Invoice.class);
         ((ZombieControl)invoice).addResult("getInvoiceDate",dateOfLastUnPaidInvoice);
         ((ZombieControl)invoice).addResult("getBalance",BigDecimal.TEN);
@@ -210,18 +217,18 @@ public class OverdueTestBase {
         items.add(item);
 
         ((ZombieControl)invoice).addResult("getInvoiceItems",items);
-        
+
         List<Invoice> invoices = new ArrayList<Invoice>();
         invoices.add(invoice);
         ((ZombieControl)invoiceApi).addResult("getUnpaidInvoicesByAccountId", invoices);
-        
-        
+
+
         Subscription base = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class);
         ((ZombieControl)base).addResult("getCurrentPlan", MockPlan.createBicycleNoTrialEvergreen1USD());
         ((ZombieControl)base).addResult("getCurrentPriceList", new MockPriceList());
         ((ZombieControl)base).addResult("getCurrentPhase", MockPlan.createBicycleNoTrialEvergreen1USD().getFinalPhase());
         ((ZombieControl)entitlementApi).addResult("getBaseSubscription", base);
-       
+
         return bundle;
     }
 }

pom.xml 20(+13 -7)

diff --git a/pom.xml b/pom.xml
index 2801091..f516c7a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,11 +1,11 @@
 <!-- ~ 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. -->
+	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. -->
 
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
@@ -344,6 +344,12 @@
                 <scope>test</scope>
             </dependency>
             <dependency>
+                <groupId>org.mockito</groupId>
+                <artifactId>mockito-all</artifactId>
+                <version>1.9.0</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
                 <groupId>com.samskivert</groupId>
                 <artifactId>jmustache</artifactId>
                 <version>1.5</version>