killbill-aplcache

Details

diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
index 810e51b..47a1918 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
@@ -490,7 +490,7 @@ public class TestOverdueIntegration extends TestOverdueBase {
         assertEquals(invoiceUserApi.getAccountBalance(account.getId(), callContext).compareTo(new BigDecimal("-11.79")), 0);
     }
 
-    @Test(groups = "slow", description = "Test overdue stages and follow with an immediate change of plan and use of credit", enabled=false)
+    @Test(groups = "slow", description = "Test overdue stages and follow with an immediate change of plan and use of credit")
     public void testOverdueStagesFollowedWithImmediateChange2() throws Exception {
         clock.setTime(new DateTime(2012, 5, 1, 0, 3, 42, 0));
 
@@ -539,11 +539,12 @@ public class TestOverdueIntegration extends TestOverdueBase {
 
         allowPaymentsAndResetOverdueToClearByPayingAllUnpaidInvoices(false);
 
+
         invoiceChecker.checkInvoice(account.getId(), 2, callContext,
                                     // New invoice for the part that was unblocked up to the BCD
                                     new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 31), new LocalDate(2013, 5, 31), InvoiceItemType.RECURRING, new BigDecimal("2399.95")),
-                                    new ExpectedInvoiceItemCheck(new LocalDate(2012, 7, 10), new LocalDate(2012, 7, 23), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-85.4588")),
-                                    new ExpectedInvoiceItemCheck(new LocalDate(2012, 7, 31), new LocalDate(2013, 5, 31), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-1998.9012")),
+                                    new ExpectedInvoiceItemCheck(new LocalDate(2012, 7, 10), new LocalDate(2012, 7, 23), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-85.46")),
+                                    new ExpectedInvoiceItemCheck(new LocalDate(2012, 7, 31), new LocalDate(2013, 5, 31), InvoiceItemType.REPAIR_ADJ, new BigDecimal("-1998.90")),
                                     new ExpectedInvoiceItemCheck(new LocalDate(2012, 7, 23), new LocalDate(2012, 7, 23), InvoiceItemType.CBA_ADJ, new BigDecimal("2084.36")));
 
 
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 c6d30c9..77104d0 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
@@ -111,7 +111,7 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implemen
     protected static final Logger log = LoggerFactory.getLogger(TestIntegrationBase.class);
     protected static long AT_LEAST_ONE_MONTH_MS = 32L * 24L * 3600L * 1000L;
 
-    protected static final long DELAY = 10000;
+    protected static final long DELAY = 10000; // * 100000;
 
     @Inject
     protected Lifecycle lifecycle;
diff --git a/invoice/src/main/java/com/ning/billing/invoice/tree/AccountItemTree.java b/invoice/src/main/java/com/ning/billing/invoice/tree/AccountItemTree.java
new file mode 100644
index 0000000..53cc8cc
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/tree/AccountItemTree.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2010-2014 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.tree;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import com.ning.billing.invoice.api.InvoiceItem;
+
+public class AccountItemTree {
+
+    private final UUID accountId;
+    private final Map<UUID, SubscriptionItemTree> subscriptionItemTree;
+
+    public AccountItemTree(final UUID accountId) {
+        this.accountId = accountId;
+        this.subscriptionItemTree = new HashMap<UUID, SubscriptionItemTree>();
+    }
+
+    public void addItem(final InvoiceItem item) {
+        if (!subscriptionItemTree.containsKey(item.getSubscriptionId())) {
+            subscriptionItemTree.put(item.getSubscriptionId(), new SubscriptionItemTree(item.getSubscriptionId()));
+        }
+        final SubscriptionItemTree tree = subscriptionItemTree.get(item.getSubscriptionId());
+        tree.addItem(item);
+    }
+
+    public List<InvoiceItem> computeNewItems(final List<InvoiceItem> proposedItems) {
+
+        final SubscriptionItemTree curTree = null;
+        for (InvoiceItem cur : proposedItems) {
+            // STEPH
+            if (curTree == null || curTree.getSubscriptionId().equals("foo")) {
+
+            }
+        }
+        return null;
+    }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/tree/ItemsInterval.java b/invoice/src/main/java/com/ning/billing/invoice/tree/ItemsInterval.java
index 99739c0..69552d0 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/tree/ItemsInterval.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/tree/ItemsInterval.java
@@ -1,22 +1,50 @@
+/*
+ * Copyright 2010-2014 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.tree;
 
 import java.math.BigDecimal;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
+import java.util.UUID;
 
+import org.joda.time.Days;
 import org.joda.time.LocalDate;
 
 import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.api.InvoiceItemType;
+import com.ning.billing.invoice.generator.InvoiceDateUtils;
+import com.ning.billing.invoice.model.InvoicingConfiguration;
 import com.ning.billing.invoice.model.RecurringInvoiceItem;
 
 import com.google.common.collect.Lists;
 
 public class ItemsInterval {
 
-    private List<InvoiceItem> items;
+    private static final int ROUNDING_MODE = InvoicingConfiguration.getRoundingMode();
+    private static final int NUMBER_OF_DECIMALS = InvoicingConfiguration.getNumberOfDecimals();
+
+
+    private LinkedList<InvoiceItem> items;
 
     public ItemsInterval() {
         this(null);
@@ -34,8 +62,8 @@ public class ItemsInterval {
         while (it.hasNext()) {
             final InvoiceItem cur = it.next();
             if (cur.getInvoiceItemType() == InvoiceItemType.RECURRING) {
-                // TODO STEPH calculate amount
-                final BigDecimal amount = BigDecimal.ONE;
+                int nbTotalRepairedDays = Days.daysBetween(cur.getStartDate(), cur.getEndDate()).getDays();
+                final BigDecimal amount = InvoiceDateUtils.calculateProrationBetweenDates(startDate, endDate, nbTotalRepairedDays).multiply(cur.getRate()).setScale(NUMBER_OF_DECIMALS, ROUNDING_MODE);
                 return new RecurringInvoiceItem(cur.getInvoiceId(), cur.getAccountId(), cur.getBundleId(), cur.getSubscriptionId(),
                                                 cur.getPlanName(), cur.getPhaseName(), startDate, endDate, amount, cur.getRate(), cur.getCurrency());
             }
@@ -47,28 +75,25 @@ public class ItemsInterval {
         return items;
     }
 
-    // Remove cancelling items
     public void build(final List<InvoiceItem> output) {
 
-        boolean foundRecuring = false;
 
-        Iterator<InvoiceItem> it = items.iterator();
-        while (it.hasNext()) {
-            final InvoiceItem cur = it.next();
+        final Set<UUID> repairedIds = new HashSet<UUID>();
+        ListIterator<InvoiceItem> it = items.listIterator(items.size());
+        while (it.hasPrevious()) {
+            final InvoiceItem cur = it.previous();
             switch (cur.getInvoiceItemType()) {
                 case FIXED:
-                    // TODO Not implemented
-                    break;
-
                 case RECURRING:
-                    foundRecuring = true;
-                    output.add(cur);
+                    // The only time we could see that true is a case of full repair, when the repair
+                    // points to an item that will end up in the same ItemsInterval
+                    if (!repairedIds.contains(cur.getId())) {
+                        output.add(cur);
+                    }
                     break;
 
                 case REPAIR_ADJ:
-                    if (!foundRecuring) {
-                        output.add(cur);
-                    }
+                    repairedIds.add(cur.getLinkedItemId());
                     break;
 
                 case ITEM_ADJ:
diff --git a/invoice/src/main/java/com/ning/billing/invoice/tree/SubscriptionItemTree.java b/invoice/src/main/java/com/ning/billing/invoice/tree/SubscriptionItemTree.java
index f82ee25..137469a 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/tree/SubscriptionItemTree.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/tree/SubscriptionItemTree.java
@@ -1,5 +1,22 @@
+/*
+ * Copyright 2010-2014 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.tree;
 
+import java.util.LinkedList;
 import java.util.List;
 import java.util.UUID;
 
@@ -10,6 +27,8 @@ public class SubscriptionItemTree {
     private final UUID subscriptionId;
     private final NodeInterval root;
 
+    private List<InvoiceItem> fixedOrRecuringItems;
+
     public SubscriptionItemTree(final UUID subscriptionId) {
         this.subscriptionId = subscriptionId;
         this.root = new NodeInterval();
@@ -20,11 +39,19 @@ public class SubscriptionItemTree {
     }
 
 
-    public void build(final List<InvoiceItem> output) {
-        // compute start and end for root
+    public void build() {
+        if (fixedOrRecuringItems == null) {
+            fixedOrRecuringItems = new LinkedList<InvoiceItem>();
+            root.build(fixedOrRecuringItems);
+        }
+    }
 
-        root.build(output);
+    public List<InvoiceItem> getSimplifiedView() {
+        return fixedOrRecuringItems;
+    }
 
+    public UUID getSubscriptionId() {
+        return subscriptionId;
     }
 
     @Override
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tree/TestSubscriptionItemTree.java b/invoice/src/test/java/com/ning/billing/invoice/tree/TestSubscriptionItemTree.java
index 086c74e..912ae26 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tree/TestSubscriptionItemTree.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tree/TestSubscriptionItemTree.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2010-2014 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.tree;
 
 import java.math.BigDecimal;
@@ -5,7 +21,6 @@ import java.util.List;
 import java.util.UUID;
 
 import org.joda.time.LocalDate;
-import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import com.ning.billing.catalog.api.Currency;
@@ -47,35 +62,32 @@ public class TestSubscriptionItemTree /* extends InvoiceTestSuiteNoDB  */ {
         final InvoiceItem repair = new RepairAdjInvoiceItem(invoiceId, accountId, repairDate, endDate, amount1.negate(), currency, initial.getId());
 
         final List<InvoiceItem> expectedResult = Lists.newLinkedList();
-        final InvoiceItem expected1 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, repairDate, BigDecimal.ONE, rate1, currency);
+        final InvoiceItem expected1 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, repairDate, new BigDecimal("8.52"), rate1, currency);
         expectedResult.add(expected1);
         final InvoiceItem expected2 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, "someelse", "someelse", repairDate, endDate, amount2, rate2, currency);
         expectedResult.add(expected2);
 
         // First test with items in order
-        List<InvoiceItem> result = Lists.newLinkedList();
         SubscriptionItemTree tree = new SubscriptionItemTree(subscriptionId);
         tree.addItem(initial);
         tree.addItem(newItem);
         tree.addItem(repair);
-        tree.build(result);
-        verifyResult(result, expectedResult);
+        tree.build();
+        verifyResult(tree.getSimplifiedView(), expectedResult);
 
-        result = Lists.newLinkedList();
         tree = new SubscriptionItemTree(subscriptionId);
         tree.addItem(repair);
         tree.addItem(newItem);
         tree.addItem(initial);
-        tree.build(result);
-        verifyResult(result, expectedResult);
+        tree.build();
+        verifyResult(tree.getSimplifiedView(), expectedResult);
 
-        result = Lists.newLinkedList();
         tree = new SubscriptionItemTree(subscriptionId);
         tree.addItem(repair);
         tree.addItem(initial);
         tree.addItem(newItem);
-        tree.build(result);
-        verifyResult(result, expectedResult);
+        tree.build();
+        verifyResult(tree.getSimplifiedView(), expectedResult);
     }
 
     @Test(groups = "fast")
@@ -104,50 +116,43 @@ public class TestSubscriptionItemTree /* extends InvoiceTestSuiteNoDB  */ {
         final InvoiceItem newItem2 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, repairDate2, endDate, amount3, rate3, currency);
         final InvoiceItem repair2 = new RepairAdjInvoiceItem(invoiceId, accountId, repairDate2, endDate, amount2.negate(), currency, initial.getId());
 
-
         final List<InvoiceItem> expectedResult = Lists.newLinkedList();
-        final InvoiceItem expected1 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, repairDate1, BigDecimal.ONE, rate1, currency);
+        final InvoiceItem expected1 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, repairDate1, new BigDecimal("8.52"), rate1, currency);
         expectedResult.add(expected1);
-        final InvoiceItem expected2 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, repairDate1, repairDate2, BigDecimal.ONE, rate2, currency);
+        final InvoiceItem expected2 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, repairDate1, repairDate2, new BigDecimal("4.95"), rate2, currency);
         expectedResult.add(expected2);
         final InvoiceItem expected3 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, repairDate2, endDate, amount3, rate3, currency);
         expectedResult.add(expected3);
 
-
         // First test with items in order
-        List<InvoiceItem> result = Lists.newLinkedList();
-
         SubscriptionItemTree tree = new SubscriptionItemTree(subscriptionId);
         tree.addItem(initial);
         tree.addItem(newItem1);
         tree.addItem(repair1);
         tree.addItem(newItem2);
         tree.addItem(repair2);
-        tree.build(result);
-        verifyResult(result, expectedResult);
+        tree.build();
+        verifyResult(tree.getSimplifiedView(), expectedResult);
 
-        result = Lists.newLinkedList();
         tree = new SubscriptionItemTree(subscriptionId);
         tree.addItem(repair2);
         tree.addItem(newItem1);
         tree.addItem(newItem2);
         tree.addItem(repair1);
         tree.addItem(initial);
-        tree.build(result);
-        verifyResult(result, expectedResult);
+        tree.build();
+        verifyResult(tree.getSimplifiedView(), expectedResult);
 
-        result = Lists.newLinkedList();
         tree = new SubscriptionItemTree(subscriptionId);
         tree.addItem(repair1);
         tree.addItem(newItem1);
         tree.addItem(initial);
         tree.addItem(repair2);
         tree.addItem(newItem2);
-        tree.build(result);
-        verifyResult(result, expectedResult);
+        tree.build();
+        verifyResult(tree.getSimplifiedView(), expectedResult);
     }
 
-
     @Test(groups = "fast")
     public void testMultipleBlockedBillings() {
 
@@ -163,11 +168,45 @@ public class TestSubscriptionItemTree /* extends InvoiceTestSuiteNoDB  */ {
         final BigDecimal rate1 = new BigDecimal("12.00");
         final BigDecimal amount1 = rate1;
 
-
         final InvoiceItem initial = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, endDate, amount1, rate1, currency);
         final InvoiceItem block1 = new RepairAdjInvoiceItem(invoiceId, accountId, blockStart1, unblockStart1, amount1.negate(), currency, initial.getId());
         final InvoiceItem block2 = new RepairAdjInvoiceItem(invoiceId, accountId, blockStart2, unblockStart2, amount1.negate(), currency, initial.getId());
 
+        final List<InvoiceItem> expectedResult = Lists.newLinkedList();
+        final InvoiceItem expected1 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, blockStart1, new BigDecimal("2.71"), rate1, currency);
+        expectedResult.add(expected1);
+        final InvoiceItem expected2 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, unblockStart1, blockStart2, new BigDecimal("2.71"), rate1, currency);
+        expectedResult.add(expected2);
+        final InvoiceItem expected3 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, unblockStart2, endDate, new BigDecimal("3.48"), rate1, currency);
+        expectedResult.add(expected3);
+
+        // First test with items in order
+        SubscriptionItemTree tree = new SubscriptionItemTree(subscriptionId);
+        tree.addItem(initial);
+        tree.addItem(block1);
+        tree.addItem(block2);
+        tree.build();
+        verifyResult(tree.getSimplifiedView(), expectedResult);
+    }
+
+    @Test(groups = "fast", enabled = false)
+    public void testRepairAndInvoiceItemAdj() {
+
+        final LocalDate startDate = new LocalDate(2014, 1, 1);
+        final LocalDate endDate = new LocalDate(2014, 2, 1);
+
+        final LocalDate blockStart1 = new LocalDate(2014, 1, 8);
+        final LocalDate unblockStart1 = new LocalDate(2014, 1, 10);
+
+        final LocalDate blockStart2 = new LocalDate(2014, 1, 17);
+        final LocalDate unblockStart2 = new LocalDate(2014, 1, 23);
+
+        final BigDecimal rate1 = new BigDecimal("12.00");
+        final BigDecimal amount1 = rate1;
+
+        final InvoiceItem initial = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, endDate, amount1, rate1, currency);
+        final InvoiceItem block1 = new RepairAdjInvoiceItem(invoiceId, accountId, blockStart1, unblockStart1, amount1.negate(), currency, initial.getId());
+        final InvoiceItem block2 = new RepairAdjInvoiceItem(invoiceId, accountId, blockStart2, unblockStart2, amount1.negate(), currency, initial.getId());
 
         final List<InvoiceItem> expectedResult = Lists.newLinkedList();
         final InvoiceItem expected1 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, startDate, blockStart1, BigDecimal.ONE, rate1, currency);
@@ -179,19 +218,15 @@ public class TestSubscriptionItemTree /* extends InvoiceTestSuiteNoDB  */ {
         final InvoiceItem expected3 = new RecurringInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, unblockStart2, endDate, BigDecimal.ONE, rate1, currency);
         expectedResult.add(expected3);
 
-
         // First test with items in order
-        List<InvoiceItem> result = Lists.newLinkedList();
-
         SubscriptionItemTree tree = new SubscriptionItemTree(subscriptionId);
         tree.addItem(initial);
         tree.addItem(block1);
         tree.addItem(block2);
-        tree.build(result);
-        verifyResult(result, expectedResult);
+        tree.build();
+        verifyResult(tree.getSimplifiedView(), expectedResult);
     }
 
-
     private void verifyResult(final List<InvoiceItem> result, final List<InvoiceItem> expectedResult) {
         assertEquals(result.size(), expectedResult.size());
         for (int i = 0; i < expectedResult.size(); i++) {