killbill-memoizeit

Changes

Details

diff --git a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
index 3740a57..8c3041a 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
@@ -227,7 +227,7 @@ public class TestAnalyticsService extends AnalyticsTestSuiteWithEmbeddedDB {
                 INVOICE_AMOUNT, ACCOUNT_CURRENCY);
         invoice.addInvoiceItem(invoiceItem);
 
-        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), true, context);
         final List<Invoice> invoices = invoiceDao.getInvoicesByAccount(account.getId());
         Assert.assertEquals(invoices.size(), 1);
         Assert.assertEquals(invoices.get(0).getInvoiceItems().size(), 1);
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/BeatrixModule.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/BeatrixModule.java
index 96fcca7..ed59b21 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/BeatrixModule.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/BeatrixModule.java
@@ -34,6 +34,7 @@ import com.ning.billing.analytics.setup.AnalyticsModule;
 import com.ning.billing.beatrix.integration.overdue.IntegrationTestOverdueModule;
 import com.ning.billing.beatrix.lifecycle.DefaultLifecycle;
 import com.ning.billing.beatrix.lifecycle.Lifecycle;
+import com.ning.billing.beatrix.util.InvoiceChecker;
 import com.ning.billing.catalog.api.CatalogService;
 import com.ning.billing.catalog.glue.CatalogModule;
 import com.ning.billing.config.PaymentConfig;
@@ -105,6 +106,8 @@ public class BeatrixModule extends AbstractModule {
         install(new PaymentPluginMockModule());
         install(new DefaultJunctionModule());
         install(new IntegrationTestOverdueModule());
+
+        bind(InvoiceChecker.class).asEagerSingleton();
     }
 
     private static final class PaymentPluginMockModule extends PaymentModule {
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestAnalytics.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestAnalytics.java
index cad4fd1..8728ac9 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestAnalytics.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestAnalytics.java
@@ -67,6 +67,9 @@ import static org.testng.Assert.assertTrue;
 
 @Guice(modules = BeatrixModule.class)
 public class TestAnalytics extends TestIntegrationBase {
+
+    private Account account;
+
     private Plan subscriptionPlan;
 
     @BeforeMethod(groups = "slow")
@@ -119,6 +122,11 @@ public class TestAnalytics extends TestIntegrationBase {
         overdueWrapperFactory.setOverdueConfig(config);
 
         busService.getBus().register(analyticsListener);
+
+        final DateTime initialDate = new DateTime(2012, 8, 1, 0, 15, 42, 0, testTimeZone);
+        clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
+
+        account = verifyAccountCreation(initialDate.plusDays(30).getDayOfMonth());
     }
 
     @AfterMethod(groups = "slow")
@@ -130,8 +138,6 @@ public class TestAnalytics extends TestIntegrationBase {
 
     @Test(groups = "slow")
     public void testCreateAndCancelSubscription() throws Exception {
-        // Create an account
-        final Account account = verifyAccountCreation();
 
         // Create a bundle
         final SubscriptionBundle bundle = verifyFirstBundle(account);
@@ -140,10 +146,10 @@ public class TestAnalytics extends TestIntegrationBase {
         Subscription subscription = verifyFirstSubscription(account, bundle);
 
         // Move after trial
-        clock.addDeltaFromReality(AT_LEAST_ONE_MONTH_MS);
         busHandler.pushExpectedEvent(TestApiListener.NextEvent.PHASE);
         busHandler.pushExpectedEvent(TestApiListener.NextEvent.INVOICE);
         busHandler.pushExpectedEvent(TestApiListener.NextEvent.PAYMENT);
+        clock.addDeltaFromReality(AT_LEAST_ONE_MONTH_MS);
         Assert.assertTrue(busHandler.isCompleted(DELAY));
 
         // Check BST - nothing should have changed
@@ -169,8 +175,6 @@ public class TestAnalytics extends TestIntegrationBase {
 
     @Test(groups = "slow")
     public void testCreateAndUpdateSubscription() throws Exception {
-        // Create an account
-        final Account account = verifyAccountCreation();
 
         // Update some fields
         verifyAccountUpdate(account);
@@ -190,10 +194,8 @@ public class TestAnalytics extends TestIntegrationBase {
 
     @Test(groups = "slow")
     public void testOverdue() throws Exception {
-        paymentPlugin.makeAllInvoicesFailWithError(true);
 
-        // Create an account
-        final Account account = verifyAccountCreation();
+        paymentPlugin.makeAllInvoicesFailWithError(true);
 
         // Create a bundle
         final SubscriptionBundle bundle = verifyFirstBundle(account);
@@ -314,8 +316,9 @@ public class TestAnalytics extends TestIntegrationBase {
         Assert.assertEquals(analyticsUserApi.getOverdueStatusesForBundle(bundle.getKey()).get(2).getAccountKey(), account.getExternalKey());
     }
 
-    private Account verifyAccountCreation() throws Exception {
-        final AccountData accountData = getAccountData(1);
+    private Account verifyAccountCreation(int billCycleDay) throws Exception {
+
+        final AccountData accountData = getAccountData(billCycleDay);
 
         // Verify BAC is empty
         Assert.assertNull(analyticsUserApi.getAccountByKey(accountData.getExternalKey()));
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBundleTransfer.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBundleTransfer.java
index cdd35dd..de00151 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBundleTransfer.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBundleTransfer.java
@@ -21,6 +21,7 @@ import static org.testng.Assert.assertTrue;
 
 import java.math.BigDecimal;
 import java.util.List;
+import java.util.UUID;
 
 import junit.framework.Assert;
 
@@ -29,8 +30,10 @@ import org.joda.time.LocalDate;
 import org.testng.annotations.Guice;
 import org.testng.annotations.Test;
 
+import com.google.common.collect.ImmutableList;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.api.TestApiListener.NextEvent;
+import com.ning.billing.beatrix.util.InvoiceChecker.ExpectedItemCheck;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.PriceListSet;
@@ -39,6 +42,7 @@ import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.InvoiceItemType;
 
 @Guice(modules = {BeatrixModule.class})
 public class TestBundleTransfer extends TestIntegrationBase {
@@ -99,8 +103,8 @@ public class TestBundleTransfer extends TestIntegrationBase {
         final List<InvoiceItem> invoiceItems = invoices.get(0).getInvoiceItems();
         assertEquals(invoiceItems.size(), 1);
         InvoiceItem theItem = invoiceItems.get(0);
-        Assert.assertTrue(theItem.getStartDate().compareTo(new LocalDate(2012,05,11)) == 0);
-        Assert.assertTrue(theItem.getEndDate().compareTo(new LocalDate(2013,05,11)) == 0);
+        Assert.assertTrue(theItem.getStartDate().compareTo(new LocalDate(2012,5,11)) == 0);
+        Assert.assertTrue(theItem.getEndDate().compareTo(new LocalDate(2013,5,11)) == 0);
         Assert.assertTrue(theItem.getAmount().compareTo(new BigDecimal("2399.9500")) == 0);
     }
 
@@ -159,8 +163,84 @@ public class TestBundleTransfer extends TestIntegrationBase {
         final List<InvoiceItem> invoiceItems = invoices.get(0).getInvoiceItems();
         assertEquals(invoiceItems.size(), 1);
         InvoiceItem theItem = invoiceItems.get(0);
-        Assert.assertTrue(theItem.getStartDate().compareTo(new LocalDate(2012,05,03)) == 0);
-        Assert.assertTrue(theItem.getEndDate().compareTo(new LocalDate(2012,05,15)) == 0);
+        Assert.assertTrue(theItem.getStartDate().compareTo(new LocalDate(2012,5,3)) == 0);
+        Assert.assertTrue(theItem.getEndDate().compareTo(new LocalDate(2012,5,15)) == 0);
         Assert.assertTrue(theItem.getAmount().compareTo(new BigDecimal("99.98")) == 0);
     }
+
+    @Test(groups = "slow")
+    public void testBundleTransferWithBPMonthlyOnlyWIthCancellationImm() throws Exception {
+
+        final Account account = createAccountWithPaymentMethod(getAccountData(9));
+
+        // Set clock to the initial start date - we implicitly assume here that the account timezone is UTC
+
+        final DateTime initialDate = new DateTime(2012, 4, 1, 0, 15, 42, 0, testTimeZone);
+
+        clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
+        final SubscriptionBundle bundle = entitlementUserApi.createBundleForAccount(account.getId(), "mycutebundle", context);
+
+        final String productName = "Shotgun";
+        final BillingPeriod term = BillingPeriod.MONTHLY;
+        final String planSetName = PriceListSet.DEFAULT_PRICELIST_NAME;
+        //
+        // CREATE SUBSCRIPTION AND EXPECT BOTH EVENTS: NextEvent.CREATE NextEvent.INVOICE
+        //
+        busHandler.pushExpectedEvents(NextEvent.CREATE, NextEvent.INVOICE);
+        final PlanPhaseSpecifier bpPlanPhaseSpecifier = new PlanPhaseSpecifier(productName, ProductCategory.BASE, term, planSetName, null);
+        final SubscriptionData bpSubscription = subscriptionDataFromSubscription(entitlementUserApi.createSubscription(bundle.getId(),
+                                                                                                                       bpPlanPhaseSpecifier,
+                                                                                                                       null,
+                                                                                                                       context));
+        assertNotNull(bpSubscription);
+        assertTrue(busHandler.isCompleted(DELAY));
+        assertListenerStatus();
+        assertEquals(invoiceUserApi.getInvoicesByAccount(account.getId()).size(), 1);
+
+        assertEquals(entitlementUserApi.getSubscriptionFromId(bpSubscription.getId()).getCurrentPlan().getBillingPeriod(), BillingPeriod.MONTHLY);
+
+        // Move out of trials for interesting invoices adjustments
+        busHandler.pushExpectedEvent(NextEvent.PHASE);
+        busHandler.pushExpectedEvent(NextEvent.INVOICE);
+        busHandler.pushExpectedEvent(NextEvent.PAYMENT);
+        clock.addDays(32);
+        assertTrue(busHandler.isCompleted(DELAY));
+        assertListenerStatus();
+
+        // BUNDLE TRANSFER
+        final Account newAccount = createAccountWithPaymentMethod(getAccountData(15));
+
+        busHandler.pushExpectedEvent(NextEvent.CANCEL);
+        busHandler.pushExpectedEvent(NextEvent.TRANSFER);
+        busHandler.pushExpectedEvent(NextEvent.INVOICE);
+        busHandler.pushExpectedEvent(NextEvent.INVOICE);
+        busHandler.pushExpectedEvent(NextEvent.PAYMENT);
+        transferApi.transferBundle(account.getId(), newAccount.getId(), "mycutebundle", clock.getUTCNow(), false, true, context);
+        assertTrue(busHandler.isCompleted(DELAY));
+        assertListenerStatus();
+
+        List<Invoice> invoices =invoiceUserApi.getInvoicesByAccount(account.getId());
+        assertEquals(invoices.size(), 3);
+
+
+        // CHECK OLD ACCOUNTS ITEMS
+        ImmutableList<ExpectedItemCheck> toBeChecked = ImmutableList.<ExpectedItemCheck>of(
+                new ExpectedItemCheck(new LocalDate(2012,5,1), new LocalDate(2012,5,9), InvoiceItemType.RECURRING, new BigDecimal("66.66")),
+                new ExpectedItemCheck(new LocalDate(2012,5,1), new LocalDate(2012,5,9), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-66.66")),
+                new ExpectedItemCheck(new LocalDate(2012,5,3), new LocalDate(2012,5,3), InvoiceItemType.CBA_ADJ, new BigDecimal("66.66")));
+        invoiceChecker.checkInvoice(invoices.get(1).getId(), toBeChecked);
+
+        toBeChecked = ImmutableList.<ExpectedItemCheck>of(
+                new ExpectedItemCheck(new LocalDate(2012,5,1), new LocalDate(2012,5,3), InvoiceItemType.RECURRING, new BigDecimal("16.67")),
+                new ExpectedItemCheck(new LocalDate(2012,5,3), new LocalDate(2012,5,3), InvoiceItemType.CBA_ADJ, new BigDecimal("-16.67")));
+        invoiceChecker.checkInvoice(invoices.get(2).getId(), toBeChecked);
+
+        // CHECK NEW ACCOUNT ITEMS
+        invoices =invoiceUserApi.getInvoicesByAccount(newAccount.getId());
+        assertEquals(invoices.size(), 1);
+
+        toBeChecked = ImmutableList.<ExpectedItemCheck>of(
+                new ExpectedItemCheck(new LocalDate(2012,5,3), new LocalDate(2012,5,15), InvoiceItemType.RECURRING, new BigDecimal("99.98")));
+        invoiceChecker.checkInvoice(invoices.get(0).getId(), toBeChecked);
+    }
 }
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestEntitlement.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestEntitlement.java
index 57220ce..7d322e0 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestEntitlement.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestEntitlement.java
@@ -16,12 +16,17 @@
 
 package com.ning.billing.beatrix.integration;
 
+import java.math.BigDecimal;
+import java.util.List;
+
 import org.joda.time.LocalDate;
 import org.testng.annotations.Guice;
 import org.testng.annotations.Test;
 
+import com.google.common.collect.ImmutableList;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.api.TestApiListener.NextEvent;
+import com.ning.billing.beatrix.util.InvoiceChecker.ExpectedItemCheck;
 import com.ning.billing.catalog.api.ActionPolicy;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
@@ -29,6 +34,8 @@ import com.ning.billing.catalog.api.PriceListSet;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItemType;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
@@ -68,21 +75,69 @@ public class TestEntitlement extends TestIntegrationBase {
         assertEquals(entitlementUserApi.getSubscriptionFromId(bpSubscription.getId()).getCurrentPlan().getBillingPeriod(), BillingPeriod.ANNUAL);
 
         // Move out of trials for interesting invoices adjustments
-        busHandler.pushExpectedEvent(NextEvent.PHASE);
+        busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT);
         clock.addDays(40);
         assertTrue(busHandler.isCompleted(DELAY));
         assertListenerStatus();
 
+        List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId());
+        assertEquals(invoices.size(), 2);
+        ImmutableList<ExpectedItemCheck> toBeChecked = ImmutableList.<ExpectedItemCheck>of(
+                new ExpectedItemCheck(new LocalDate(2012,5,1), new LocalDate(2013,5,1), InvoiceItemType.RECURRING, new BigDecimal("2399.95")));
+        invoiceChecker.checkInvoice(invoices.get(1).getId(), toBeChecked);
+
         //
         // FORCE AN IMMEDIATE CHANGE OF THE BILLING PERIOD
         //
+        busHandler.pushExpectedEvents(NextEvent.CHANGE, NextEvent.INVOICE);
         assertTrue(bpSubscription.changePlanWithPolicy(productName, BillingPeriod.MONTHLY, planSetName, clock.getUTCNow(), ActionPolicy.IMMEDIATE, context));
         assertEquals(entitlementUserApi.getSubscriptionFromId(bpSubscription.getId()).getCurrentPlan().getBillingPeriod(), BillingPeriod.MONTHLY);
+        assertTrue(busHandler.isCompleted(DELAY));
+        assertListenerStatus();
+
+        invoices = invoiceUserApi.getInvoicesByAccount(account.getId());
+        assertEquals(invoices.size(), 3);
+        toBeChecked = ImmutableList.<ExpectedItemCheck>of(
+                new ExpectedItemCheck(new LocalDate(2012,5,1), new LocalDate(2013,5,1), InvoiceItemType.RECURRING, new BigDecimal("2399.95")),
+                new ExpectedItemCheck(new LocalDate(2012,5,1), new LocalDate(2013,5,1), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-2399.95")),
+                new ExpectedItemCheck(new LocalDate(2012,5,11), new LocalDate(2012,5,11), InvoiceItemType.CBA_ADJ, new BigDecimal("2399.95")));
+        invoiceChecker.checkInvoice(invoices.get(1).getId(), toBeChecked);
+
+        toBeChecked = ImmutableList.<ExpectedItemCheck>of(
+                new ExpectedItemCheck(new LocalDate(2012,5,1), new LocalDate(2012,5,11), InvoiceItemType.RECURRING, new BigDecimal("65.76")),
+                new ExpectedItemCheck(new LocalDate(2012,5,11), new LocalDate(2012,6,1), InvoiceItemType.RECURRING, new BigDecimal("169.32")),
+                new ExpectedItemCheck(new LocalDate(2012,5,11), new LocalDate(2012,5,11), InvoiceItemType.CBA_ADJ, new BigDecimal("-235.08")));
+        invoiceChecker.checkInvoice(invoices.get(2).getId(), toBeChecked);
+
+
 
         //
         // FORCE ANOTHER CHANGE
         //
+        busHandler.pushExpectedEvents(NextEvent.CHANGE, NextEvent.INVOICE);
         assertTrue(bpSubscription.changePlanWithPolicy(productName, BillingPeriod.ANNUAL, planSetName, clock.getUTCNow(), ActionPolicy.IMMEDIATE, context));
         assertEquals(entitlementUserApi.getSubscriptionFromId(bpSubscription.getId()).getCurrentPlan().getBillingPeriod(), BillingPeriod.ANNUAL);
+        assertTrue(busHandler.isCompleted(DELAY));
+        assertListenerStatus();
+
+        invoices = invoiceUserApi.getInvoicesByAccount(account.getId());
+        assertEquals(invoices.size(), 4);
+
+
+        toBeChecked = ImmutableList.<ExpectedItemCheck>of(
+                new ExpectedItemCheck(new LocalDate(2012,5,1), new LocalDate(2012,5,11), InvoiceItemType.RECURRING, new BigDecimal("65.76")),
+                new ExpectedItemCheck(new LocalDate(2012,5,11), new LocalDate(2012,6,1), InvoiceItemType.RECURRING, new BigDecimal("169.32")),
+                new ExpectedItemCheck(new LocalDate(2012,5,11), new LocalDate(2012,5,11), InvoiceItemType.CBA_ADJ, new BigDecimal("-235.08")),
+                new ExpectedItemCheck(new LocalDate(2012,5,11), new LocalDate(2012,6,1), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-169.32")),
+                new ExpectedItemCheck(new LocalDate(2012,5,11), new LocalDate(2012,5,11), InvoiceItemType.CBA_ADJ, new BigDecimal("169.32")));
+        invoiceChecker.checkInvoice(invoices.get(2).getId(), toBeChecked);
+
+
+        toBeChecked = ImmutableList.<ExpectedItemCheck>of(
+                new ExpectedItemCheck(new LocalDate(2012,5,11), new LocalDate(2012,6,1), InvoiceItemType.RECURRING, new BigDecimal("137.76")),
+                new ExpectedItemCheck(new LocalDate(2012,5,11), new LocalDate(2012,5,11), InvoiceItemType.CBA_ADJ, new BigDecimal("-137.76")));
+        invoiceChecker.checkInvoice(invoices.get(3).getId(), toBeChecked);
+
+
     }
 }
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java
index 36854d4..9bb0ed4 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java
@@ -92,11 +92,14 @@ public class TestIntegration extends TestIntegrationBase {
         //
         busHandler.pushExpectedEvents(NextEvent.CANCEL, NextEvent.CANCEL, NextEvent.INVOICE);
         bpSubscription.cancel(clock.getUTCNow(), false, context);
+
+        //Thread.sleep(10000000);
+
         assertTrue(busHandler.isCompleted(DELAY));
         assertListenerStatus();
 
         final List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId());
-        assertEquals(invoices.size(), 3);
+        assertEquals(invoices.size(), 2);
         // The first invoice is for the trial BP
         assertEquals(invoices.get(0).getNumberOfItems(), 1);
         assertEquals(invoices.get(0).getInvoiceItems().get(0).getStartDate().compareTo(today), 0);
@@ -120,8 +123,6 @@ public class TestIntegration extends TestIntegrationBase {
                 assertEquals(item.getAmount().compareTo(new BigDecimal("399.9500")), 0);
             }
         }
-        // Null invoice
-        assertEquals(invoices.get(2).getNumberOfItems(), 0);
     }
 
     @Test(groups = "slow")
@@ -520,9 +521,11 @@ public class TestIntegration extends TestIntegrationBase {
         //waitForDebug();
 
         assertTrue(busHandler.isCompleted(DELAY));
-
         startDate = chargeThroughDate;
-        DateTime endDate = chargeThroughDate.plusMonths(1);
+
+        // Resync latest with real CTD so test does not drift
+        DateTime realChargeThroughDate = entitlementUserApi.getSubscriptionFromId(subscription.getId()).getChargedThroughDate();
+        DateTime endDate = realChargeThroughDate;
         price = subscription.getCurrentPhase().getRecurringPrice().getPrice(Currency.USD);
         invoiceItemCount += 1;
         verifyTestResult(accountId, subscription.getId(), startDate, endDate, price, endDate, invoiceItemCount);
@@ -558,7 +561,8 @@ public class TestIntegration extends TestIntegrationBase {
 
         // MOVE AFTER CANCEL DATE AND EXPECT EVENT : NextEvent.CANCEL
         busHandler.pushExpectedEvent(NextEvent.CANCEL);
-        final Interval it = new Interval(clock.getUTCNow(), endDate);
+        realChargeThroughDate = entitlementUserApi.getSubscriptionFromId(subscription.getId()).getChargedThroughDate();
+        final Interval it = new Interval(clock.getUTCNow(), realChargeThroughDate.plusSeconds(5));
         clock.addDeltaFromReality(it.toDurationMillis());
         assertTrue(busHandler.isCompleted(DELAY));
 
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
index 4aa10d8..2339a8f 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
@@ -49,6 +49,7 @@ import com.ning.billing.api.TestApiListener;
 import com.ning.billing.api.TestListenerStatus;
 import com.ning.billing.beatrix.BeatrixTestSuiteWithEmbeddedDB;
 import com.ning.billing.beatrix.lifecycle.Lifecycle;
+import com.ning.billing.beatrix.util.InvoiceChecker;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.entitlement.api.EntitlementService;
@@ -97,7 +98,7 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
     protected static final BigDecimal THIRTY_ONE = new BigDecimal("31.0000").setScale(NUMBER_OF_DECIMALS);
 
     protected static final Logger log = LoggerFactory.getLogger(TestIntegration.class);
-    protected static long AT_LEAST_ONE_MONTH_MS = 31L * 24L * 3600L * 1000L + 2000L;
+    protected static long AT_LEAST_ONE_MONTH_MS = 32L * 24L * 3600L * 1000L;
 
     protected static final long DELAY = 5000;
 
@@ -161,6 +162,9 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
     @Inject
     protected AnalyticsListener analyticsListener;
 
+    @Inject
+    protected InvoiceChecker invoiceChecker;
+
     protected TestApiListener busHandler;
 
     private boolean isListenerFailed;
@@ -251,8 +255,7 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
         log.info("Checking CTD: " + ctd.toString() + "; clock is " + clock.getUTCNow().toString());
         // Either the ctd is today (start of the trial) or the clock is strictly before the CTD
         assertTrue(clock.getUTCToday().compareTo(new LocalDate(ctd)) == 0 || clock.getUTCNow().isBefore(ctd));
-        // The CTD is rounded too
-        assertTrue(ctd.compareTo(new DateTime(chargeThroughDate.getYear(), chargeThroughDate.getMonthOfYear(), chargeThroughDate.getDayOfMonth(), 0, 0, testTimeZone)) == 0);
+        assertTrue(ctd.toDateTime(testTimeZone).toLocalDate().compareTo(new LocalDate(chargeThroughDate.getYear(), chargeThroughDate.getMonthOfYear(), chargeThroughDate.getDayOfMonth())) == 0);
     }
 
     protected SubscriptionData subscriptionDataFromSubscription(final Subscription sub) {
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/util/InvoiceChecker.java b/beatrix/src/test/java/com/ning/billing/beatrix/util/InvoiceChecker.java
new file mode 100644
index 0000000..dca65a5
--- /dev/null
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/util/InvoiceChecker.java
@@ -0,0 +1,108 @@
+/*
+ * 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.beatrix.util;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+
+
+import org.joda.time.LocalDate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+
+import com.google.inject.Inject;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.InvoiceItemType;
+import com.ning.billing.invoice.api.InvoiceUserApi;
+
+public class InvoiceChecker {
+
+    private final static Logger log = LoggerFactory.getLogger(InvoiceChecker.class);
+
+    private final InvoiceUserApi invoiceUserApi;
+
+    @Inject
+    public InvoiceChecker(final InvoiceUserApi invoiceUserApi) {
+       this.invoiceUserApi = invoiceUserApi;
+    }
+
+    public void checkInvoice(final UUID invoiceId, final List<ExpectedItemCheck> expected) {
+        final Invoice invoice =invoiceUserApi.getInvoice(invoiceId);
+        Assert.assertNotNull(invoice);
+
+        final List<InvoiceItem> actual = invoice.getInvoiceItems();
+        Assert.assertEquals(expected.size(), actual.size());
+        for (ExpectedItemCheck cur : expected) {
+            boolean found = false;
+            for (InvoiceItem in : actual) {
+                // Match first on type and start date
+                if (in.getInvoiceItemType() != cur.getType() || (in.getStartDate().compareTo(cur.getStartDate()) != 0)) {
+                    continue;
+                }
+                if (in.getAmount().compareTo(cur.getAmount()) != 0) {
+                    log.info(String.format("Found item type = %s and startDate = %s but amount differ (actual = %s, expected = %s) ",
+                            cur.getType(), cur.getStartDate(), in.getAmount(), cur.getAmount()));
+                    continue;
+                }
+
+                if ((cur.getEndDate() == null && in.getEndDate() == null) ||
+                        (cur.getEndDate() != null && in.getEndDate() != null && cur.getEndDate().compareTo(in.getEndDate()) == 0)) {
+                    found = true;
+                    break;
+                }
+                log.info(String.format("Found item type = %s and startDate = %s, amount = %s but endDate differ (actual = %s, expected = %s) ",
+                        cur.getType(), cur.getStartDate(), in.getAmount(), in.getEndDate(), cur.getEndDate()));
+            }
+            if (!found) {
+                Assert.fail(String.format("Failed to find invoice item type = %s and startDate = %s, amount = %s, endDate = %s",
+                        cur.getType(), cur.getStartDate(), cur.getAmount(), cur.getEndDate()));
+            }
+        }
+    }
+
+    public static class ExpectedItemCheck {
+
+        private final LocalDate startDate;
+        private final LocalDate endDate;
+        private final InvoiceItemType type;
+        private final BigDecimal Amount;
+
+        public ExpectedItemCheck(final LocalDate startDate, final LocalDate endDate,
+                final InvoiceItemType type, final BigDecimal amount) {
+            this.startDate = startDate;
+            this.endDate = endDate;
+            this.type = type;
+            Amount = amount;
+        }
+
+        public LocalDate getStartDate() {
+            return startDate;
+        }
+        public LocalDate getEndDate() {
+            return endDate;
+        }
+        public InvoiceItemType getType() {
+            return type;
+        }
+        public BigDecimal getAmount() {
+            return Amount;
+        }
+    }
+
+}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/AuditedEntitlementDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/AuditedEntitlementDao.java
index 455fe64..d2cd173 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/AuditedEntitlementDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/AuditedEntitlementDao.java
@@ -705,6 +705,13 @@ public class AuditedEntitlementDao implements EntitlementDao {
         final List<EntityAudit> audits = new ArrayList<EntityAudit>();
         Long recordId;
         final SubscriptionBundleData bundleData = bundleTransferData.getData();
+
+        final SubscriptionBundle existingBundle = transBundleDao.getBundleFromAccountAndKey(bundleData.getAccountId().toString(), bundleData.getKey());
+        if (existingBundle != null) {
+            log.error(String.format("Attempted to create a bundle for account %s and key %s that already existed, skip...", bundleData.getAccountId().toString(), bundleData.getKey()));
+            return;
+        }
+
         for (final SubscriptionMigrationData curSubscription : bundleTransferData.getSubscriptions()) {
             final SubscriptionData subData = curSubscription.getData();
             for (final EntitlementEvent curEvent : curSubscription.getInitialEvents()) {
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EntitlementEventSqlDao.sql.stg b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EntitlementEventSqlDao.sql.stg
index 09bf42d..f10428d 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EntitlementEventSqlDao.sql.stg
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EntitlementEventSqlDao.sql.stg
@@ -90,8 +90,6 @@ getFutureActiveEventForSubscription() ::= <<
       and effective_date > :now
     order by
       effective_date asc
-      , created_date asc
-      , requested_date asc
       , record_id asc
     ;
 >> 
@@ -103,8 +101,6 @@ getEventsForSubscription() ::= <<
       subscription_id = :subscriptionId
     order by
       effective_date asc
-      , created_date asc
-      , requested_date asc
       , record_id asc
     ;      
 >>
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/migration/DefaultInvoiceMigrationApi.java b/invoice/src/main/java/com/ning/billing/invoice/api/migration/DefaultInvoiceMigrationApi.java
index f007eac..f45509c 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/migration/DefaultInvoiceMigrationApi.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/migration/DefaultInvoiceMigrationApi.java
@@ -70,7 +70,7 @@ public class DefaultInvoiceMigrationApi implements InvoiceMigrationApi {
         final InvoiceItem migrationInvoiceItem = new MigrationInvoiceItem(migrationInvoice.getId(), accountId, targetDate, balance, currency);
         migrationInvoice.addInvoiceItem(migrationInvoiceItem);
 
-        dao.create(migrationInvoice, account.getBillCycleDay().getDayOfMonthUTC(), context);
+        dao.create(migrationInvoice, account.getBillCycleDay().getDayOfMonthUTC(), true, context);
         return migrationInvoice.getId();
     }
 }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
index 54c87da..a2f9a9b 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
@@ -158,7 +158,7 @@ public class DefaultInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public void create(final Invoice invoice, final int billCycleDayUTC, final CallContext context) {
+    public void create(final Invoice invoice, final int billCycleDayUTC, final boolean isRealInvoice, final CallContext context) {
         invoiceSqlDao.inTransaction(new Transaction<Void, InvoiceSqlDao>() {
             @Override
             public Void inTransaction(final InvoiceSqlDao transactional, final TransactionStatus status) throws Exception {
@@ -166,9 +166,14 @@ public class DefaultInvoiceDao implements InvoiceDao {
                 if (currentInvoice == null) {
                     final List<EntityAudit> audits = new ArrayList<EntityAudit>();
 
-                    transactional.create(invoice, context);
-                    final Long recordId = transactional.getRecordId(invoice.getId().toString());
-                    audits.add(new EntityAudit(TableName.INVOICES, recordId, ChangeType.INSERT));
+                    // We only want to insert that invoice if there are real invoiceItems associated to it-- if not, this is just
+                    // a shell invoice and we only need to insert the invoiceItems-- for the already existing invoices
+
+                    if (isRealInvoice) {
+                        transactional.create(invoice, context);
+                        final Long recordId = transactional.getRecordId(invoice.getId().toString());
+                        audits.add(new EntityAudit(TableName.INVOICES, recordId, ChangeType.INSERT));
+                    }
 
                     List<Long> recordIdList;
 
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
index d385802..a9104f9 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
@@ -35,7 +35,7 @@ import com.ning.billing.util.callcontext.CallContext;
 
 public interface InvoiceDao {
 
-    void create(final Invoice invoice, final int billCycleDayUTC, final CallContext context);
+    void create(final Invoice invoice, final int billCycleDayUTC, final boolean isRealInvoice, final CallContext context);
 
     Invoice getById(final UUID id);
 
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 694330d..087cf4a 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
@@ -62,6 +62,8 @@ import com.ning.billing.util.globallocker.GlobalLocker;
 import com.ning.billing.util.globallocker.GlobalLocker.LockerType;
 import com.ning.billing.util.globallocker.LockFailedException;
 
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
 import com.google.inject.Inject;
 
 public class InvoiceDispatcher {
@@ -178,7 +180,16 @@ public class InvoiceDispatcher {
                 }
                 outputDebugData(billingEvents, invoices);
                 if (!dryRun) {
-                    invoiceDao.create(invoice, account.getBillCycleDay().getDayOfMonthUTC(), context);
+
+                    // We need to check whether this is just a 'shell' invoice or a real invoice with items on it
+                    final boolean isRealInvoiceWithItems = Collections2.filter(invoice.getInvoiceItems(), new Predicate<InvoiceItem>() {
+                        @Override
+                        public boolean apply(InvoiceItem input) {
+                            return input.getInvoiceId().equals(invoice.getId());
+                        }
+                    }).size() > 0;
+
+                    invoiceDao.create(invoice, account.getBillCycleDay().getDayOfMonthUTC(), isRealInvoiceWithItems, context);
 
                     final List<InvoiceItem> fixedPriceInvoiceItems = invoice.getInvoiceItems(FixedPriceInvoiceItem.class);
                     final List<InvoiceItem> recurringInvoiceItems = invoice.getInvoiceItems(RecurringInvoiceItem.class);
@@ -236,16 +247,17 @@ public class InvoiceDispatcher {
             final UUID subscriptionId = item.getSubscriptionId();
             final DateTime endDate;
             if (item.getEndDate() != null) {
-                endDate = new DateTime(item.getEndDate().toDateTimeAtStartOfDay(), DateTimeZone.UTC);
+                endDate = new DateTime(item.getEndDate().toDateTime(clock.getUTCNow()) , DateTimeZone.UTC);
             } else {
                 // item end date is null for fixed price items for instance
-                endDate = new DateTime(item.getStartDate().toDateTimeAtStartOfDay(), DateTimeZone.UTC);
+                endDate = new DateTime(item.getStartDate().toDateTime(clock.getUTCNow()), DateTimeZone.UTC);
             }
 
             if (chargeThroughDates.containsKey(subscriptionId)) {
                 if (chargeThroughDates.get(subscriptionId).isBefore(endDate)) {
                     // The CTD should always align with the BCD
-                    chargeThroughDates.put(subscriptionId, InvoiceDateUtils.calculateBillingCycleDateOnOrAfter(endDate, billCycleDay.getDayOfMonthLocal()));
+                    final DateTime ctd = InvoiceDateUtils.calculateBillingCycleDateOnOrAfter(endDate, billCycleDay.getDayOfMonthLocal());
+                    chargeThroughDates.put(subscriptionId, ctd);
                 }
             } else {
                 chargeThroughDates.put(subscriptionId, endDate);
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/InAdvanceBillingMode.java b/invoice/src/main/java/com/ning/billing/invoice/model/InAdvanceBillingMode.java
index 07e385b..69193f6 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/InAdvanceBillingMode.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/InAdvanceBillingMode.java
@@ -53,10 +53,28 @@ public class InAdvanceBillingMode implements BillingMode {
 
         final List<RecurringInvoiceItemData> results = new ArrayList<RecurringInvoiceItemData>();
 
-        // beginning from the start date, find the first billing date
         final LocalDate firstBillingCycleDate = calculateBillingCycleDateOnOrAfter(startDate, accountTimeZone, billingCycleDayLocal);
 
-        // add pro-ration item if needed
+        // We are not billing for less than a day (we could...)
+        if (endDate != null && endDate.equals(startDate)) {
+            return results;
+        }
+        //
+        // If there is an endDate and that endDate is before our first coming firstBillingCycleDate, all we have to do
+        // is to charge for that period
+        //
+        if (endDate != null && !endDate.isAfter(firstBillingCycleDate)) {
+            final BigDecimal leadingProRationPeriods = calculateProRationBeforeFirstBillingPeriod(startDate, endDate, billingPeriod);
+            final RecurringInvoiceItemData itemData = new RecurringInvoiceItemData(startDate, endDate, leadingProRationPeriods);
+            results.add(itemData);
+            return results;
+        }
+
+        //
+        // Leading proration if
+        // i) The first firstBillingCycleDate is strictly after our start date AND
+        // ii) The endDate is is not null and is strictly after our firstBillingCycleDate (previous check)
+        //
         if (firstBillingCycleDate.isAfter(startDate)) {
             final BigDecimal leadingProRationPeriods = calculateProRationBeforeFirstBillingPeriod(startDate, firstBillingCycleDate, billingPeriod);
             if (leadingProRationPeriods != null && leadingProRationPeriods.compareTo(BigDecimal.ZERO) > 0) {
@@ -67,7 +85,11 @@ public class InAdvanceBillingMode implements BillingMode {
             }
         }
 
-        // add one item per billing period
+        //
+        // Calculate the effectiveEndDate from the firstBillingCycleDate:
+        // - If endDate != null and targetDate is after endDate => this is the endDate and will lead to a trailing pro-ration
+        // - If not, this is the last billingCycleDate calculation right after the targetDate
+        //
         final LocalDate effectiveEndDate;
         if (endDate != null) {
             effectiveEndDate = calculateEffectiveEndDate(firstBillingCycleDate, targetDate, endDate, billingPeriod);
@@ -75,6 +97,9 @@ public class InAdvanceBillingMode implements BillingMode {
             effectiveEndDate = calculateEffectiveEndDate(firstBillingCycleDate, targetDate, billingPeriod);
         }
 
+        //
+        // Based on what we calculated previously, code recompute one more time the numberOfWholeBillingPeriods
+        //
         final LocalDate lastBillingCycleDate = calculateLastBillingCycleDateBefore(effectiveEndDate, firstBillingCycleDate, billingCycleDayLocal, billingPeriod);
         final int numberOfWholeBillingPeriods = calculateNumberOfWholeBillingPeriods(firstBillingCycleDate, lastBillingCycleDate, billingPeriod);
         final int numberOfMonthsPerBillingPeriod = billingPeriod.getNumberOfMonths();
@@ -97,7 +122,9 @@ public class InAdvanceBillingMode implements BillingMode {
             results.add(new RecurringInvoiceItemData(servicePeriodStartDate, servicePeriodEndDate, BigDecimal.ONE));
         }
 
-        // check to see if a trailing pro-ration amount is needed
+        //
+        // Now we check if indeed we need a trailing proration and add that incomplete item
+        //
         if (effectiveEndDate.isAfter(lastBillingCycleDate)) {
             final BigDecimal trailingProRationPeriods = calculateProRationAfterLastBillingCycleDate(effectiveEndDate, lastBillingCycleDate, billingPeriod);
             if (trailingProRationPeriods.compareTo(BigDecimal.ZERO) > 0) {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
index 1164797..301866c 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
@@ -49,7 +49,7 @@ public class MockInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public void create(final Invoice invoice, final int billCycleDay, final CallContext context) {
+    public void create(final Invoice invoice, final int billCycleDay, final boolean isRealInvoice, final CallContext context) {
         synchronized (monitor) {
             invoices.put(invoice.getId(), invoice);
         }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java
index b71d6de..55a2e61 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java
@@ -80,7 +80,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final Invoice invoice = new DefaultInvoice(accountId, clock.getUTCToday(), clock.getUTCToday(), Currency.USD);
         final LocalDate invoiceDate = invoice.getInvoiceDate();
 
-        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), true, context);
 
         final List<Invoice> invoices = invoiceDao.getInvoicesByAccount(accountId);
         assertNotNull(invoices);
@@ -106,7 +106,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
                                                                  new BigDecimal("21.00"), new BigDecimal("7.00"), Currency.USD);
 
         invoice.addInvoiceItem(invoiceItem);
-        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), true, context);
 
         final Invoice savedInvoice = invoiceDao.getById(invoiceId);
         assertNotNull(savedInvoice);
@@ -151,7 +151,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // Create invoice 1 (subscriptions 1-4)
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, context);
 
         final UUID invoiceId1 = invoice1.getId();
 
@@ -176,7 +176,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // Create invoice 2 (subscriptions 1-3)
         final DefaultInvoice invoice2 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, context);
 
         final UUID invoiceId2 = invoice2.getId();
 
@@ -227,7 +227,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // Create invoice 1 (subscriptions 1-4)
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, context);
 
         final UUID invoiceId1 = invoice1.getId();
 
@@ -252,7 +252,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // create invoice 2 (subscriptions 1-3)
         final DefaultInvoice invoice2 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, context);
 
         final UUID invoiceId2 = invoice2.getId();
 
@@ -303,7 +303,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // Create invoice 1 (subscriptions 1-4)
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, context);
 
         final UUID invoiceId1 = invoice1.getId();
 
@@ -344,7 +344,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         // create invoice 2 (subscriptions 1-3)
         final DefaultInvoice invoice2 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, context);
 
         final UUID invoiceId2 = invoice2.getId();
 
@@ -393,11 +393,11 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID accountId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true,  context);
 
         final LocalDate targetDate2 = new LocalDate(2011, 12, 6);
         final Invoice invoice2 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate2, Currency.USD);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, context);
 
         List<Invoice> invoices;
         invoices = invoiceDao.getInvoicesByAccount(accountId, new LocalDate(2011, 1, 1));
@@ -422,7 +422,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, context);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
         final LocalDate endDate = startDate.plusMonths(1);
@@ -452,7 +452,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, context);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
         final LocalDate endDate = startDate.plusMonths(1);
@@ -476,7 +476,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, context);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
         final LocalDate endDate = startDate.plusMonths(1);
@@ -501,7 +501,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID accountId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, context);
 
         final BigDecimal payment1 = new BigDecimal("48.0");
         final InvoicePayment payment = new DefaultInvoicePayment(InvoicePaymentType.ATTEMPT, UUID.randomUUID(), invoice1.getId(), new DateTime(), payment1, Currency.USD);
@@ -527,7 +527,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, context);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
         final LocalDate endDate = startDate.plusMonths(1);
@@ -593,7 +593,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, context);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
         final LocalDate endDate = startDate.plusMonths(1);
@@ -660,7 +660,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, context);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
         final LocalDate endDate = startDate.plusMonths(1);
@@ -722,7 +722,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         // NEXT RECURRING on invoice 2
 
         final Invoice invoice2 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1.plusMonths(1), Currency.USD);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, context);
 
         final RecurringInvoiceItem nextItem = new RecurringInvoiceItem(invoice2.getId(), accountId, bundleId, UUID.randomUUID(), "test plan", "test bla", startDate.plusMonths(1),
                                                                        endDate.plusMonths(1), rate2, rate2, Currency.USD);
@@ -810,7 +810,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         // Crete one invoice with a fixed invoice item
         final LocalDate targetDate = new LocalDate(2011, 2, 15);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, context);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
 
@@ -853,7 +853,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final UUID bundleId = UUID.randomUUID();
         final LocalDate targetDate1 = new LocalDate(2011, 10, 6);
         final Invoice invoice1 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate1, Currency.USD);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, context);
 
         final LocalDate startDate = new LocalDate(2011, 3, 1);
         final LocalDate endDate = startDate.plusMonths(1);
@@ -882,7 +882,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         final LocalDate targetDate2 = new LocalDate(2011, 7, 1);
         final Invoice invoice2 = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate2, Currency.USD);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, context);
 
         final LocalDate startDate2 = new LocalDate(2011, 6, 1);
         final LocalDate endDate2 = startDate2.plusMonths(3);
@@ -952,8 +952,8 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         assertEquals(invoice2.getBalance(), FIVE);
         invoiceList.add(invoice2);
 
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, context);
 
         final Invoice savedInvoice1 = invoiceDao.getById(invoice1.getId());
         assertEquals(savedInvoice1.getBalance(), ZERO);
@@ -1095,7 +1095,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         assertEquals(invoice.getNumberOfItems(), 2);
         assertEquals(invoice.getBalance().compareTo(cheapAmount), 0);
 
-        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), true, context);
         final Invoice savedInvoice = invoiceDao.getById(invoice.getId());
 
         assertNotNull(savedInvoice);
@@ -1131,7 +1131,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
 
         Invoice invoice1 = generator.generateInvoice(UUID.randomUUID(), events, invoices, new LocalDate(targetDate1), DateTimeZone.UTC, Currency.USD);
         invoices.add(invoice1);
-        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice1, invoice1.getTargetDate().getDayOfMonth(), true, context);
         invoice1 = invoiceDao.getById(invoice1.getId());
         assertNotNull(invoice1.getInvoiceNumber());
 
@@ -1141,7 +1141,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
                                                            "testEvent2", 2L, SubscriptionTransitionType.CHANGE);
         events.add(event2);
         Invoice invoice2 = generator.generateInvoice(UUID.randomUUID(), events, invoices, new LocalDate(targetDate2), DateTimeZone.UTC, Currency.USD);
-        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice2, invoice2.getTargetDate().getDayOfMonth(), true, context);
         invoice2 = invoiceDao.getById(invoice2.getId());
         assertNotNull(invoice2.getInvoiceNumber());
     }
@@ -1168,7 +1168,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         events.add(event1);
 
         final Invoice invoice = generator.generateInvoice(UUID.randomUUID(), events, null, new LocalDate(targetDate1), DateTimeZone.UTC, Currency.USD);
-        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), true, context);
         invoiceDao.setWrittenOff(invoice.getId(), context);
 
         final TagDao tagDao = new AuditedTagDao(dbi, tagEventBuilder, bus);
@@ -1199,7 +1199,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         events.add(event1);
 
         final Invoice invoice = generator.generateInvoice(UUID.randomUUID(), events, null, new LocalDate(targetDate1), DateTimeZone.UTC, Currency.USD);
-        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), context);
+        invoiceDao.create(invoice, invoice.getTargetDate().getDayOfMonth(), true, context);
         invoiceDao.setWrittenOff(invoice.getId(), context);
 
         final TagDao tagDao = new AuditedTagDao(dbi, tagEventBuilder, bus);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceItemDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceItemDao.java
index f8766f9..4c98b52 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceItemDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceItemDao.java
@@ -115,7 +115,7 @@ public class TestInvoiceItemDao extends InvoiceDaoTestBase {
         final LocalDate targetDate = new LocalDate(2011, 5, 23);
         final DefaultInvoice invoice = new DefaultInvoice(accountId, clock.getUTCToday(), targetDate, Currency.USD);
 
-        invoiceDao.create(invoice, targetDate.getDayOfMonth(), context);
+        invoiceDao.create(invoice, targetDate.getDayOfMonth(), true, context);
 
         final UUID invoiceId = invoice.getId();
         final LocalDate startDate = new LocalDate(2011, 3, 1);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/model/TestInAdvanceBillingMode.java b/invoice/src/test/java/com/ning/billing/invoice/model/TestInAdvanceBillingMode.java
index 10ded27..fccd7b1 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/model/TestInAdvanceBillingMode.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/model/TestInAdvanceBillingMode.java
@@ -41,8 +41,6 @@ public class TestInAdvanceBillingMode {
         final int billingCycleDayLocal = 15;
 
         final LinkedHashMap<LocalDate, LocalDate> expectedDates = new LinkedHashMap<LocalDate, LocalDate>();
-        expectedDates.put(new LocalDate(2012, 7, 16), new LocalDate(2012, 8, 15));
-
         verifyInvoiceItems(startDate, endDate, targetDate, TIMEZONE, billingCycleDayLocal, BILLING_PERIOD, expectedDates);
     }
 
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 9777935..19f0f28 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
@@ -113,9 +113,9 @@ public class DefaultBillingApi implements BillingApi {
 
 
     private void debugLog(final SortedSet<BillingEvent> result, final String title) {
-        log.debug(title);
+        log.info(title);
         for (final BillingEvent aResult : result) {
-            log.debug(aResult.toString());
+            log.info(aResult.toString());
         }
     }
 
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java b/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java
index 94ae280..6f8fa5a 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java
@@ -125,7 +125,7 @@ public class TestBundle extends TestJaxrsBase {
 
         final SubscriptionJsonNoEvents subscriptionJson = createSubscription(bundleJson.getBundleId(), productName, ProductCategory.BASE.toString(), term.toString(), true);
         Assert.assertNotNull(subscriptionJson.getChargedThroughDate());
-        Assert.assertEquals(subscriptionJson.getChargedThroughDate().toString(), "2012-04-25T00:00:00.000Z");
+        Assert.assertEquals(subscriptionJson.getChargedThroughDate().toString(), "2012-04-25T00:03:43.000Z");
 
         final AccountJson newAccount = createAccountWithDefaultPaymentMethod("dst", "dst", "dst@yahoo.com");
 
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestSubscription.java b/server/src/test/java/com/ning/billing/jaxrs/TestSubscription.java
index da9b666..dd22fad 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestSubscription.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestSubscription.java
@@ -57,7 +57,7 @@ public class TestSubscription extends TestJaxrsBase {
 
         final SubscriptionJsonNoEvents subscriptionJson = createSubscription(bundleJson.getBundleId(), productName, ProductCategory.BASE.toString(), term.toString(), true);
         Assert.assertNotNull(subscriptionJson.getChargedThroughDate());
-        Assert.assertEquals(subscriptionJson.getChargedThroughDate().toString(), "2012-04-25T00:00:00.000Z");
+        Assert.assertEquals(subscriptionJson.getChargedThroughDate().toString(), "2012-04-25T00:03:43.000Z");
 
         String uri = JaxrsResource.SUBSCRIPTIONS_PATH + "/" + subscriptionJson.getSubscriptionId();
 
@@ -144,7 +144,7 @@ public class TestSubscription extends TestJaxrsBase {
 
         final SubscriptionJsonNoEvents subscriptionJson = createSubscription(bundleJson.getBundleId(), productName, ProductCategory.BASE.toString(), term.toString(), true);
         Assert.assertNotNull(subscriptionJson.getChargedThroughDate());
-        Assert.assertEquals(subscriptionJson.getChargedThroughDate().toString(), "2012-04-25T00:00:00.000Z");
+        Assert.assertEquals(subscriptionJson.getChargedThroughDate().toString(), "2012-04-25T00:03:43.000Z");
 
         final String uri = JaxrsResource.SUBSCRIPTIONS_PATH + "/" + subscriptionJson.getSubscriptionId();