killbill-memoizeit

Details

diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBasic.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBasic.java
index ad0738f..55efa97 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBasic.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestBasic.java
@@ -217,8 +217,8 @@ public class TestBasic {
         Iterator<InvoiceItem> invoiceItemIterator = invoiceItems.iterator();
         while (invoiceItemIterator.hasNext()) {
             InvoiceItem item = invoiceItemIterator.next();
-            if (item.getStartDate().compareTo(removeMillis(startDate)) == 0) {
-                if (item.getEndDate().compareTo(removeMillis(endDate)) == 0) {
+            if (item.getStartDate().compareTo(startDate) == 0) {
+                if (item.getEndDate().compareTo(endDate) == 0) {
                     if (item.getAmount().compareTo(amount) == 0) {
                         wasFound = true;
                         break;
@@ -233,11 +233,7 @@ public class TestBasic {
         assertNotNull(ctd);
         log.info("Checking CTD: " + ctd.toString() + "; clock is " + clock.getUTCNow().toString());
         assertTrue(clock.getUTCNow().isBefore(ctd));
-        assertTrue(ctd.compareTo(removeMillis(chargeThroughDate)) == 0);
-    }
-
-    private DateTime removeMillis(DateTime input) {
-        return input.toMutableDateTime().millisOfSecond().set(0).toDateTime();
+        assertTrue(ctd.compareTo(chargeThroughDate) == 0);
     }
 
     @Test(groups = "fast", enabled = false)
@@ -291,7 +287,7 @@ public class TestBasic {
 
     private void testBasePlanComplete(DateTime initialCreationDate, int billingDay,
                                       boolean proRationExpected) throws Exception {
-        long DELAY = 5000 * 10;
+        long DELAY = 5000;
 
         Account account = accountUserApi.createAccount(getAccountData(billingDay), null, null);
         UUID accountId = account.getId();
@@ -343,7 +339,7 @@ public class TestBasic {
         // VERIFY AGAIN CTD HAS BEEN SET
         //
         startDate = subscription.getCurrentPhaseStart();
-        endDate = startDate.plusMonths(1);
+        endDate = startDate.plusDays(30);
         price = subscription.getCurrentPhase().getFixedPrice().getPrice(Currency.USD);
         verifyTestResult(accountId, subscription.getId(), startDate, endDate, price, endDate);
 
@@ -363,6 +359,16 @@ public class TestBasic {
 
         assertTrue(busHandler.isCompleted(DELAY));
 
+        startDate = subscription.getCurrentPhaseStart();
+        int numberOfDaysToProRate = billingDay - startDate.dayOfMonth().get();
+        DateTime firstEndDate = startDate.plusDays(numberOfDaysToProRate);
+        DateTime secondEndDate = firstEndDate.plusMonths(1);
+
+        BigDecimal rate = subscription.getCurrentPhase().getRecurringPrice().getPrice(Currency.USD);
+        price = rate.multiply(new BigDecimal(numberOfDaysToProRate).setScale(4)).setScale(4).divide(new BigDecimal("29.0000"), 6);
+        verifyTestResult(accountId, subscription.getId(), startDate, firstEndDate, price, secondEndDate);
+        verifyTestResult(accountId, subscription.getId(), firstEndDate, secondEndDate, rate, secondEndDate);
+
         //
         // CHANGE PLAN EOT AND EXPECT NOTHING
         //
@@ -387,17 +393,23 @@ public class TestBasic {
         assertTrue(busHandler.isCompleted(DELAY));
         log.info("testSimple passed fourth busHandler checkpoint.");
 
+        startDate = secondEndDate;
+        endDate = secondEndDate.plusMonths(1);
+        price = subscription.getCurrentPhase().getRecurringPrice().getPrice(Currency.USD);
+        verifyTestResult(accountId, subscription.getId(), startDate, endDate, price, endDate);
+
         //
         // MOVE TIME AFTER NEXT BILL CYCLE DAY AND EXPECT EVENT : NextEvent.INVOICE
         //
         int maxCycles = 3;
-        startDate = endDate;
-        endDate = startDate.plusMonths(1);
         do {
             busHandler.pushExpectedEvent(NextEvent.INVOICE);
             busHandler.pushExpectedEvent(NextEvent.PAYMENT);
             clock.addDeltaFromReality(AT_LEAST_ONE_MONTH_MS + 1000);
             assertTrue(busHandler.isCompleted(DELAY));
+
+            startDate = endDate;
+            endDate = startDate.plusMonths(1);
             verifyTestResult(accountId, subscription.getId(), startDate, endDate, price, endDate);
         } while (maxCycles-- > 0);
 
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
index f4bb22b..9a0ef55 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
@@ -202,11 +202,12 @@ public class SubscriptionData implements Subscription {
     }
 
     public SubscriptionTransition getPreviousTransition() {
-
         if (transitions == null) {
             return null;
         }
-        SubscriptionTransition latestSubscription = null;
+
+        // ensure that the latestSubscription is always set; prevents NPEs
+        SubscriptionTransition latestSubscription = transitions.get(0);
         for (SubscriptionTransition cur : transitions) {
             if (cur.getEffectiveTransitionTime().isAfter(clock.getUTCNow())) {
                 break;
@@ -330,10 +331,12 @@ public class SubscriptionData implements Subscription {
                 // Skip future events
                 continue;
             }
-            if (cur.getEventType() == EventType.PHASE) {
+            if (cur.getEventType() == EventType.PHASE
+                    || (cur.getEventType() == EventType.API_USER && cur.getApiEventType() == ApiEventType.CHANGE)) {
                 return cur.getEffectiveTransitionTime();
             }
         }
+
         // CREATE event
         return transitions.get(0).getEffectiveTransitionTime();
     }
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 4d3dff9..971d353 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
@@ -149,7 +149,7 @@ public class InAdvanceBillingMode implements BillingMode {
         BigDecimal daysInPeriod = new BigDecimal(daysBetween);
         BigDecimal days = new BigDecimal(Days.daysBetween(startDate, nextBillingCycleDate).getDays());
 
-        return days.divide(daysInPeriod, NUMBER_OF_DECIMALS, ROUNDING_METHOD);
+        return days.divide(daysInPeriod, 2 * NUMBER_OF_DECIMALS, ROUNDING_METHOD);
     }
 
     private int calculateNumberOfWholeBillingPeriods(final DateTime startDate, final DateTime endDate, final BillingPeriod billingPeriod) {
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 f0de1ce..18a3df3 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
@@ -131,8 +131,8 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         assertEquals(invoice.getNumberOfItems(), 2);
 
         BigDecimal expectedNumberOfBillingCycles;
-        expectedNumberOfBillingCycles = ONE.add(FOURTEEN.divide(THIRTY_ONE, NUMBER_OF_DECIMALS, ROUNDING_METHOD));
-        BigDecimal expectedAmount = expectedNumberOfBillingCycles.multiply(rate).setScale(NUMBER_OF_DECIMALS);
+        expectedNumberOfBillingCycles = ONE.add(FOURTEEN.divide(THIRTY_ONE, 2 * NUMBER_OF_DECIMALS, ROUNDING_METHOD));
+        BigDecimal expectedAmount = expectedNumberOfBillingCycles.multiply(rate).setScale(NUMBER_OF_DECIMALS, ROUNDING_METHOD);
         assertEquals(invoice.getTotalAmount(), expectedAmount);
     }
 
@@ -373,7 +373,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
         // on 6/21/2011, create add-on (subscription 5)
         events.add(createBillingEvent(subscriptionId5, plan5StartDate, plan5, plan5Phase1, 10));
-        expectedAmount = TWENTY.multiply(NINETEEN.divide(THIRTY, NUMBER_OF_DECIMALS, ROUNDING_METHOD)).setScale(NUMBER_OF_DECIMALS);
+        expectedAmount = TWENTY.multiply(NINETEEN).divide(THIRTY, NUMBER_OF_DECIMALS, ROUNDING_METHOD);
         testInvoiceGeneration(events, invoiceItems, plan5StartDate, 1, expectedAmount);
 
         // on 7/7/2011, invoice subscription 4 (plan 1)
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java
index a24b0c0..122b13b 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/ProRationTestBase.java
@@ -66,7 +66,7 @@ public abstract class ProRationTestBase extends InvoicingTestBase {
             numberOfBillingCycles = numberOfBillingCycles.add(item.getNumberOfCycles());
         }
 
-        return numberOfBillingCycles;
+        return numberOfBillingCycles.setScale(NUMBER_OF_DECIMALS, ROUNDING_METHOD);
     }
 
     protected BigDecimal calculateNumberOfBillingCycles(DateTime startDate, DateTime targetDate, int billingCycleDay) throws InvalidDateSequenceException {
@@ -77,6 +77,6 @@ public abstract class ProRationTestBase extends InvoicingTestBase {
             numberOfBillingCycles = numberOfBillingCycles.add(item.getNumberOfCycles());
         }
 
-        return numberOfBillingCycles;
+        return numberOfBillingCycles.setScale(NUMBER_OF_DECIMALS, ROUNDING_METHOD);
     }
 }
\ No newline at end of file
diff --git a/util/src/test/java/com/ning/billing/util/clock/ClockMock.java b/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
index ad3e5d3..8787cd1 100644
--- a/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
+++ b/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
@@ -150,7 +150,7 @@ public class ClockMock extends DefaultClock {
     }
 
     private DateTime adjustFromAbsolute(DateTime input) {
-        return input.plus(deltaFromRealityMs);
+        return truncateMs(input.plus(deltaFromRealityMs));
     }
 
 }