killbill-aplcache

Fix a bug in calculation of firstBillingCycleDay. Add unit

3/2/2014 12:08:18 AM

Details

diff --git a/invoice/src/main/java/com/ning/billing/invoice/generator/BillingIntervalDetail.java b/invoice/src/main/java/com/ning/billing/invoice/generator/BillingIntervalDetail.java
index 9c7de27..8c1d9cc 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/generator/BillingIntervalDetail.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/generator/BillingIntervalDetail.java
@@ -20,6 +20,8 @@ import org.joda.time.LocalDate;
 
 import com.ning.billing.catalog.api.BillingPeriod;
 
+import com.google.common.annotations.VisibleForTesting;
+
 public class BillingIntervalDetail {
 
     private final LocalDate startDate;
@@ -65,7 +67,8 @@ public class BillingIntervalDetail {
         calculateLastBillingCycleDate();
     }
 
-    private void calculateFirstBillingCycleDate() {
+    @VisibleForTesting
+    void calculateFirstBillingCycleDate() {
 
         final int lastDayOfMonth = startDate.dayOfMonth().getMaximumValue();
         final LocalDate billingCycleDate;
@@ -75,12 +78,10 @@ public class BillingIntervalDetail {
             billingCycleDate = new LocalDate(startDate.getYear(), startDate.getMonthOfYear(), billingCycleDay, startDate.getChronology());
         }
 
-        int numberOfPeriods = 0;
         final int numberOfMonthsInPeriod = billingPeriod.getNumberOfMonths();
         LocalDate proposedDate = billingCycleDate;
         while (proposedDate.isBefore(startDate)) {
-            proposedDate = proposedDate.plusMonths(numberOfPeriods * numberOfMonthsInPeriod);
-            numberOfPeriods += 1;
+            proposedDate = proposedDate.plusMonths(numberOfMonthsInPeriod);
         }
         firstBillingCycleDate = alignProposedBillCycleDate(proposedDate);
     }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/generator/TestBillingIntervalDetail.java b/invoice/src/test/java/com/ning/billing/invoice/generator/TestBillingIntervalDetail.java
index 65c692f..ce8f84e 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/generator/TestBillingIntervalDetail.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/generator/TestBillingIntervalDetail.java
@@ -25,6 +25,69 @@ import com.ning.billing.invoice.InvoiceTestSuiteNoDB;
 
 public class TestBillingIntervalDetail extends InvoiceTestSuiteNoDB {
 
+    /*
+     *
+     *         Start         BCD    END_MONTH
+     * |---------|------------|-------|
+     *
+     */
+    @Test(groups = "fast")
+    public void testCalculateFirstBillingCycleDate1() throws Exception {
+        final LocalDate from = new LocalDate("2012-01-16");
+        final int bcd = 17;
+        final BillingIntervalDetail billingIntervalDetail = new BillingIntervalDetail(from, null, new LocalDate(), bcd, BillingPeriod.ANNUAL);
+        billingIntervalDetail.calculateFirstBillingCycleDate();
+        Assert.assertEquals(billingIntervalDetail.getFirstBillingCycleDate(), new LocalDate("2012-01-17"));
+    }
+
+    /*
+     *
+     *         Start             END_MONTH    BCD
+     * |---------|-------------------| - - - -|
+     *
+     */
+    @Test(groups = "fast")
+    public void testCalculateFirstBillingCycleDate2() throws Exception {
+        final LocalDate from = new LocalDate("2012-02-16");
+        final int bcd = 30;
+        final BillingIntervalDetail billingIntervalDetail = new BillingIntervalDetail(from, null, new LocalDate(), bcd, BillingPeriod.ANNUAL);
+        billingIntervalDetail.calculateFirstBillingCycleDate();
+        Assert.assertEquals(billingIntervalDetail.getFirstBillingCycleDate(), new LocalDate("2012-02-29"));
+    }
+
+    /*
+     * Here the interesting part is that BCD is prior start and
+     *  i) we use MONTHLY billing period
+     * ii) on the next month, there is no such date (2012-02-30 does not exist)
+     *
+     *                                      Start
+     *                              BCD     END_MONTH
+     * |----------------------------|--------|
+     *
+     */
+    @Test(groups = "fast")
+    public void testCalculateFirstBillingCycleDate4() throws Exception {
+        final LocalDate from = new LocalDate("2012-01-31");
+        final int bcd = 30;
+        final BillingIntervalDetail billingIntervalDetail = new BillingIntervalDetail(from, null, new LocalDate(), bcd, BillingPeriod.MONTHLY);
+        billingIntervalDetail.calculateFirstBillingCycleDate();
+        Assert.assertEquals(billingIntervalDetail.getFirstBillingCycleDate(), new LocalDate("2012-02-29"));
+    }
+
+    /*
+     *
+     *         BCD                 Start      END_MONTH
+     * |---------|-------------------|-----------|
+     *
+     */
+    @Test(groups = "fast")
+    public void testCalculateFirstBillingCycleDate3() throws Exception {
+        final LocalDate from = new LocalDate("2012-02-16");
+        final int bcd = 14;
+        final BillingIntervalDetail billingIntervalDetail = new BillingIntervalDetail(from, null, new LocalDate(), bcd, BillingPeriod.ANNUAL);
+        billingIntervalDetail.calculateFirstBillingCycleDate();
+        Assert.assertEquals(billingIntervalDetail.getFirstBillingCycleDate(), new LocalDate("2013-02-14"));
+    }
 
     @Test(groups = "fast")
     public void testNextBCDShouldNotBeInThePast() throws Exception {
@@ -102,5 +165,4 @@ public class TestBillingIntervalDetail extends InvoiceTestSuiteNoDB {
         Assert.assertEquals(effectiveEndDate, new LocalDate("2012-05-31"));
     }
 
-
 }