killbill-aplcache

Changes

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..4801182 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
@@ -26,6 +26,8 @@ public interface BillingEventSet extends SortedSet<BillingEvent> {
 
     public abstract boolean isAccountAutoInvoiceOff();
 
-    public abstract List<UUID> getSubscriptionIdsWithAutoInvoiceOff();
+    public abstract List<UUID> getSubscriptionAndBundleIdsWithAutoInvoiceOff();
+    
+    public boolean isLast(BillingEvent event);
 
 }
\ No newline at end of file
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..978bd53 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
@@ -20,7 +20,6 @@ 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 +36,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,8 +144,11 @@ 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);
+            
+            if (billingEvents.isAccountAutoInvoiceOff()) {
+                return null; //nothing to do invoicing is off on this account
+            }
 
             Currency targetCurrency = account.getCurrency();
 
@@ -155,7 +157,7 @@ public class InvoiceDispatcher {
 
             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 +170,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 c24215c..2fd686d 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 {
@@ -70,12 +71,15 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
 
         validateTargetDate(targetDate);
 
-        Collections.sort(events);
-
         List<InvoiceItem> existingItems = new ArrayList<InvoiceItem>();
         if (existingInvoices != null) {
             for (Invoice invoice : existingInvoices) {
-                existingItems.addAll(invoice.getInvoiceItems());
+                for(InvoiceItem item : invoice.getInvoiceItems()) {
+                    if(!events.getSubscriptionAndBundleIdsWithAutoInvoiceOff()
+                            .contains(item.getBundleId())) { //don't add items with auto_invoice_off tag 
+                        existingItems.add(item);
+                    }
+                }
             }
 
             Collections.sort(existingItems);
@@ -246,16 +250,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.getSubscriptionAndBundleIdsWithAutoInvoiceOff().
+                    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..2610f9f
--- /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> getSubscriptionAndBundleIdsWithAutoInvoiceOff() {
+        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 6c3dd65..dd12f26 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
@@ -27,7 +27,6 @@ import java.util.UUID;
 
 import javax.annotation.Nullable;
 
-import com.ning.billing.invoice.model.DefaultInvoicePayment;
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
@@ -46,10 +45,11 @@ 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.model.DefaultInvoiceGenerator;
+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;
@@ -95,7 +95,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testWithEmptyEventSet() throws InvoiceApiException {
-        BillingEventSet events = new BillingEventSet();
+        MockBillingEventSet events = new MockBillingEventSet();
 
         UUID accountId = UUID.randomUUID();
         Invoice invoice = generator.generateInvoice(accountId, events, null, new DateTime(), Currency.USD);
@@ -105,7 +105,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testWithSingleMonthlyEvent() throws InvoiceApiException, CatalogApiException {
-        BillingEventSet events = new BillingEventSet();
+        MockBillingEventSet events = new MockBillingEventSet();
 
         Subscription sub = createZombieSubscription();
         DateTime startDate = buildDateTime(2011, 9, 1);
@@ -141,7 +141,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testWithSingleMonthlyEventWithLeadingProRation() throws InvoiceApiException, CatalogApiException {
-        BillingEventSet events = new BillingEventSet();
+        MockBillingEventSet events = new MockBillingEventSet();
 
         Subscription sub = createZombieSubscription();
         DateTime startDate = buildDateTime(2011, 9, 1);
@@ -167,7 +167,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testTwoMonthlySubscriptionsWithAlignedBillingDates() throws InvoiceApiException, CatalogApiException {
-        BillingEventSet events = new BillingEventSet();
+        MockBillingEventSet events = new MockBillingEventSet();
 
         Plan plan1 = new MockPlan();
         BigDecimal rate1 = FIVE;
@@ -196,7 +196,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testOnePlan_TwoMonthlyPhases_ChangeImmediate() throws InvoiceApiException, CatalogApiException {
-        BillingEventSet events = new BillingEventSet();
+        MockBillingEventSet events = new MockBillingEventSet();
 
         Plan plan1 = new MockPlan();
         BigDecimal rate1 = FIVE;
@@ -233,7 +233,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testOnePlan_ThreeMonthlyPhases_ChangeEOT() throws InvoiceApiException, CatalogApiException {
-        BillingEventSet events = new BillingEventSet();
+        MockBillingEventSet events = new MockBillingEventSet();
 
         Plan plan1 = new MockPlan();
         BigDecimal rate1 = FIVE;
@@ -264,7 +264,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testSingleEventWithExistingInvoice() throws InvoiceApiException, CatalogApiException {
-        BillingEventSet events = new BillingEventSet();
+        MockBillingEventSet events = new MockBillingEventSet();
 
         Subscription sub = createZombieSubscription();
         DateTime startDate = buildDateTime(2011, 9, 1);
@@ -340,7 +340,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
         BigDecimal expectedAmount;
         List<Invoice> invoices = new ArrayList<Invoice>();
-        BillingEventSet events = new BillingEventSet();
+        MockBillingEventSet events = new MockBillingEventSet();
 
         // on 1/5/2011, create subscription 1 (trial)
         events.add(createBillingEvent(subscriptionId1, plan1StartDate, plan1, plan1Phase1, 5));
@@ -453,7 +453,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     public void testZeroDollarEvents() throws InvoiceApiException, CatalogApiException {
         Plan plan = new MockPlan();
         PlanPhase planPhase = createMockMonthlyPlanPhase(ZERO);
-        BillingEventSet events = new BillingEventSet();
+        MockBillingEventSet events = new MockBillingEventSet();
         DateTime targetDate = buildDateTime(2011, 1, 1);
         events.add(createBillingEvent(UUID.randomUUID(), targetDate, plan, planPhase, 1));
 
@@ -466,7 +466,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     public void testEndDateIsCorrect() throws InvoiceApiException, CatalogApiException {
         Plan plan = new MockPlan();
         PlanPhase planPhase = createMockMonthlyPlanPhase(ZERO);
-        BillingEventSet events = new BillingEventSet();
+        MockBillingEventSet events = new MockBillingEventSet();
         DateTime targetDate = new DateTime();
         events.add(createBillingEvent(UUID.randomUUID(), targetDate, plan, planPhase, targetDate.getDayOfMonth()));
 
@@ -491,7 +491,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
         DateTime changeDate = new DateTime("2012-04-1T00:00:00.000-08:00");
 
-        BillingEventSet events = new BillingEventSet();
+        MockBillingEventSet events = new MockBillingEventSet();
 
         BillingEvent event1 = createMockBillingEvent(null, subscription, new DateTime("2012-01-1T00:00:00.000-08:00"),
                 plan, phase1,
@@ -528,7 +528,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         BigDecimal fixedCost = TEN;
         PlanPhase phase1 = createMockMonthlyPlanPhase(monthlyRate, fixedCost, PhaseType.TRIAL);
 
-        BillingEventSet events = new BillingEventSet();
+        MockBillingEventSet events = new MockBillingEventSet();
         UUID subscriptionId = UUID.randomUUID();
         UUID accountId = UUID.randomUUID();
 
@@ -564,7 +564,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         PlanPhase phase1 = createMockMonthlyPlanPhase(null, fixedCost1, PhaseType.TRIAL);
         PlanPhase phase2 = createMockMonthlyPlanPhase(null, fixedCost2, PhaseType.EVERGREEN);
 
-        BillingEventSet events = new BillingEventSet();
+        MockBillingEventSet events = new MockBillingEventSet();
         UUID subscriptionId = UUID.randomUUID();
         UUID accountId = UUID.randomUUID();
 
@@ -595,7 +595,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     @Test
     public void testNutsFailure() throws InvoiceApiException, CatalogApiException {
-        BillingEventSet events = new BillingEventSet();
+        MockBillingEventSet events = new MockBillingEventSet();
         UUID subscriptionId = UUID.randomUUID();
         UUID accountId = UUID.randomUUID();
         final int BILL_CYCLE_DAY = 15;
@@ -651,7 +651,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();
+        MockBillingEventSet events = new MockBillingEventSet();
         Plan plan1 = new MockPlan();
         PlanPhase phase1 = createMockMonthlyPlanPhase(null, ZERO, PhaseType.TRIAL);
         events.add(createBillingEvent(UUID.randomUUID(), DateTime.now(), plan1, phase1, 1));
@@ -698,7 +698,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
                 billCycleDay, BillingModeType.IN_ADVANCE, "Test", 1L, SubscriptionTransitionType.CREATE);
     }
 
-    private void testInvoiceGeneration(final UUID accountId, final BillingEventSet events, final List<Invoice> existingInvoices,
+    private void testInvoiceGeneration(final UUID accountId, final MockBillingEventSet events, final List<Invoice> existingInvoices,
                                        final DateTime targetDate, final int expectedNumberOfItems,
                                        final BigDecimal expectedAmount) throws InvoiceApiException {
         Currency currency = Currency.USD;
@@ -724,7 +724,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();
+        MockBillingEventSet events = new MockBillingEventSet();
         events.add(createBillingEvent(baseSubscription.getId(), april25, basePlan, basePlanEvergreen, 25));
 
         // generate invoice
@@ -757,7 +757,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);
@@ -786,7 +786,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();
+        MockBillingEventSet events = new MockBillingEventSet();
         events.add(createBillingEvent(originalSubscription.getId(), april25, originalPlan, originalPlanEvergreen, 25));
 
         Invoice invoice1 = generator.generateInvoice(accountId, events, null, april25, Currency.USD);
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
+}
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..0e8b9ba 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) != 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,49 @@ 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) != null) {
+                result.getSubscriptionAndBundleIdsWithAutoInvoiceOff().add(bundle.getId());
+                for (final Subscription subscription: subscriptions) { // billing is off so list sub ids in set to be excluded
+                    result.getSubscriptionAndBundleIdsWithAutoInvoiceOff().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..69740d9 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
@@ -43,7 +43,7 @@ public class DefaultBillingEventSet extends TreeSet<BillingEvent> implements Sor
      * @see com.ning.billing.junction.plumbing.billing.BillingEventSet#getSubscriptionIdsWithAutoInvoiceOff()
      */
     @Override
-    public List<UUID> getSubscriptionIdsWithAutoInvoiceOff() {
+    public List<UUID> getSubscriptionAndBundleIdsWithAutoInvoiceOff() {
         return subscriptionIdsWithAutoInvoiceOff;
     }
 
@@ -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/TestBillingApiWithAutoInvoiceOff.java b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApiWithAutoInvoiceOff.java
new file mode 100644
index 0000000..5cbc9dc
--- /dev/null
+++ b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApiWithAutoInvoiceOff.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.junction.plumbing.billing;
+
+public class TestBillingApiWithAutoInvoiceOff {
+
+    
+    //TODO MDW - write this class TestBillingApiWithAutoInvoiceOff
+}
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/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 7fba2ef..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
@@ -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
     }