killbill-uncached
Changes
Details
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/factory/BusinessInvoiceFactory.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/factory/BusinessInvoiceFactory.java
index ed19754..6347161 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/factory/BusinessInvoiceFactory.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/factory/BusinessInvoiceFactory.java
@@ -19,9 +19,11 @@ package com.ning.billing.osgi.bundles.analytics.dao.factory;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
@@ -319,7 +321,8 @@ public class BusinessInvoiceFactory extends BusinessFactoryBase {
* @param allInvoiceItems all invoice items, across all invoices
* @return a mapping reparee invoice item id to REPAIR_ADJ item
*/
- private Map<InvoiceItem, InvoiceItem> findRepareeInvoiceItems(final Collection<InvoiceItem> allInvoiceItems) {
+ @VisibleForTesting
+ Map<InvoiceItem, InvoiceItem> findRepareeInvoiceItems(final Collection<InvoiceItem> allInvoiceItems) {
// Build a convenience mapping between items -> repair_adj items (inverse of linkedItemId)
final Map<UUID, InvoiceItem> repairedInvoiceItemIdToRepairInvoiceItemMappings = new HashMap<UUID, InvoiceItem>();
for (final InvoiceItem invoiceItem : allInvoiceItems) {
@@ -358,30 +361,52 @@ public class BusinessInvoiceFactory extends BusinessFactoryBase {
return repareeInvoiceItemToRepairItemMappings;
}
- private Collection<AdjustedCBAInvoiceItem> buildMergedCBAItems(final Multimap<UUID, InvoiceItem> allInvoiceItems,
- final Map<InvoiceItem, InvoiceItem> repareeInvoiceItemToRepairItemMappings) {
- final Map<UUID, BigDecimal> cbaPerInvoice = new HashMap<UUID, BigDecimal>();
+ @VisibleForTesting
+ Collection<AdjustedCBAInvoiceItem> buildMergedCBAItems(final Multimap<UUID, InvoiceItem> allInvoiceItems,
+ final Map<InvoiceItem, InvoiceItem> repareeInvoiceItemToRepairItemMappings) {
+ // Build a black list of invoices for which we should not adjust the CBA when rebalancing the reparee item.
+ final Set<UUID> repairInvoiceBlackList = new HashSet<UUID>();
+ for (final InvoiceItem repairInvoiceItem : repareeInvoiceItemToRepairItemMappings.values()) {
+ boolean shouldBlackList = true;
+ // Only adjust CBA items on invoices having CBA already. Otherwise, don't do anything (e.g. for unpaid repaired invoices).
+ for (final InvoiceItem invoiceItem : allInvoiceItems.get(repairInvoiceItem.getInvoiceId())) {
+ if (invoiceItem.getInvoiceItemType().equals(InvoiceItemType.CBA_ADJ) &&
+ invoiceItem.getAmount().compareTo(repairInvoiceItem.getAmount().negate()) == 0) {
+ shouldBlackList = false;
+ }
+ }
+ if (shouldBlackList) {
+ // We can't blacklist the reparee invoice because it might have been repaired...
+ repairInvoiceBlackList.add(repairInvoiceItem.getInvoiceId());
+ }
+ }
+
+ final Map<UUID, BigDecimal> cbaAdjustmentPerInvoice = new HashMap<UUID, BigDecimal>();
// Adjust the CBAs in case of repair.
- // On the new invoice (with the reparee item), we need to add the amount of the reparee to the CBA amount.
// On the original invoice (with the repair item), we need to substract the amount of the reparee to the CBA amount.
+ // On the new invoice (with the reparee item), we need to add the amount of the reparee to the CBA amount.
for (final InvoiceItem repareeInvoiceItem : repareeInvoiceItemToRepairItemMappings.keySet()) {
- // The reparee item was on a new invoice
- if (cbaPerInvoice.get(repareeInvoiceItem.getInvoiceId()) == null) {
- cbaPerInvoice.put(repareeInvoiceItem.getInvoiceId(), BigDecimal.ZERO);
- }
- final BigDecimal currentCBAForNewInvoice = cbaPerInvoice.get(repareeInvoiceItem.getInvoiceId());
- final BigDecimal adjustedCBAForNewInvoice = currentCBAForNewInvoice.add(repareeInvoiceItem.getAmount());
- cbaPerInvoice.put(repareeInvoiceItem.getInvoiceId(), adjustedCBAForNewInvoice);
-
// The repair item was on the original invoice
final InvoiceItem repairInvoiceItem = repareeInvoiceItemToRepairItemMappings.get(repareeInvoiceItem);
- if (cbaPerInvoice.get(repairInvoiceItem.getInvoiceId()) == null) {
- cbaPerInvoice.put(repairInvoiceItem.getInvoiceId(), BigDecimal.ZERO);
+ if (repairInvoiceBlackList.contains(repairInvoiceItem.getInvoiceId())) {
+ continue;
+ }
+
+ if (cbaAdjustmentPerInvoice.get(repairInvoiceItem.getInvoiceId()) == null) {
+ cbaAdjustmentPerInvoice.put(repairInvoiceItem.getInvoiceId(), BigDecimal.ZERO);
}
- final BigDecimal currentCBAForOriginalInvoice = cbaPerInvoice.get(repairInvoiceItem.getInvoiceId());
+ final BigDecimal currentCBAForOriginalInvoice = cbaAdjustmentPerInvoice.get(repairInvoiceItem.getInvoiceId());
final BigDecimal adjustedCBAForOriginalInvoice = currentCBAForOriginalInvoice.add(repareeInvoiceItem.getAmount().negate());
- cbaPerInvoice.put(repairInvoiceItem.getInvoiceId(), adjustedCBAForOriginalInvoice);
+ cbaAdjustmentPerInvoice.put(repairInvoiceItem.getInvoiceId(), adjustedCBAForOriginalInvoice);
+
+ // The reparee item was on a new invoice
+ if (cbaAdjustmentPerInvoice.get(repareeInvoiceItem.getInvoiceId()) == null) {
+ cbaAdjustmentPerInvoice.put(repareeInvoiceItem.getInvoiceId(), BigDecimal.ZERO);
+ }
+ final BigDecimal currentCBAForNewInvoice = cbaAdjustmentPerInvoice.get(repareeInvoiceItem.getInvoiceId());
+ final BigDecimal adjustedCBAForNewInvoice = currentCBAForNewInvoice.add(repareeInvoiceItem.getAmount());
+ cbaAdjustmentPerInvoice.put(repareeInvoiceItem.getInvoiceId(), adjustedCBAForNewInvoice);
}
// Now, we just combine the other CBA items
@@ -391,7 +416,6 @@ public class BusinessInvoiceFactory extends BusinessFactoryBase {
continue;
}
- // Only adjust CBA items on invoices having CBA already. Otherwise, don't do anything (e.g. for unpaid repaired invoices).
final Collection<InvoiceItem> cbaItemsForInvoice = Collections2.filter(allInvoiceItems.get(invoiceId), new Predicate<InvoiceItem>() {
@Override
public boolean apply(final InvoiceItem invoiceItem) {
@@ -402,7 +426,7 @@ public class BusinessInvoiceFactory extends BusinessFactoryBase {
continue;
}
- BigDecimal revenueRecognizableCBA = cbaPerInvoice.get(invoiceId);
+ BigDecimal revenueRecognizableCBA = cbaAdjustmentPerInvoice.get(invoiceId);
if (revenueRecognizableCBA == null) {
revenueRecognizableCBA = BigDecimal.ZERO;
}
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/factory/TestBusinessInvoiceFactory.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/factory/TestBusinessInvoiceFactory.java
index fa41527..b1621aa 100644
--- a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/factory/TestBusinessInvoiceFactory.java
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/factory/TestBusinessInvoiceFactory.java
@@ -41,10 +41,12 @@ import com.ning.killbill.osgi.libs.killbill.OSGIKillbillLogService;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Multimap;
public class TestBusinessInvoiceFactory extends AnalyticsTestSuiteNoDB {
- private BusinessInvoiceFactory invoiceDao;
+ private BusinessInvoiceFactory invoiceFactory;
@Override
@BeforeMethod(groups = "fast")
@@ -65,7 +67,7 @@ public class TestBusinessInvoiceFactory extends AnalyticsTestSuiteNoDB {
}
}).when(osgiKillbillLogService).log(Mockito.anyInt(), Mockito.anyString());
- invoiceDao = new BusinessInvoiceFactory(logService, null);
+ invoiceFactory = new BusinessInvoiceFactory(osgiKillbillLogService, null);
}
@Test(groups = "fast")
@@ -73,114 +75,114 @@ public class TestBusinessInvoiceFactory extends AnalyticsTestSuiteNoDB {
final UUID invoiceId = UUID.randomUUID();
// Classic account credit ($10), from the perspective of the CREDIT_ADJ item
- final BusinessInvoiceItemBaseModelDao businessCreditAdjItem = invoiceDao.createBusinessInvoiceItem(account,
- invoice,
- createInvoiceItem(invoiceId, InvoiceItemType.CREDIT_ADJ, new BigDecimal("-10")),
- ImmutableList.<InvoiceItem>of(createInvoiceItem(invoiceId, InvoiceItemType.CBA_ADJ, new BigDecimal("10"))),
- null,
- null,
- null,
- invoiceItemRecordId,
- auditLog,
- accountRecordId,
- tenantRecordId,
- reportGroup,
- callContext);
+ final BusinessInvoiceItemBaseModelDao businessCreditAdjItem = invoiceFactory.createBusinessInvoiceItem(account,
+ invoice,
+ createInvoiceItem(invoiceId, InvoiceItemType.CREDIT_ADJ, new BigDecimal("-10")),
+ ImmutableList.<InvoiceItem>of(createInvoiceItem(invoiceId, InvoiceItemType.CBA_ADJ, new BigDecimal("10"))),
+ null,
+ null,
+ null,
+ invoiceItemRecordId,
+ auditLog,
+ accountRecordId,
+ tenantRecordId,
+ reportGroup,
+ callContext);
// We ignore these
Assert.assertNull(businessCreditAdjItem);
// Classic account credit ($10), from the perspective of the CBA_ADJ item
- final BusinessInvoiceItemBaseModelDao businessCreditItem = invoiceDao.createBusinessInvoiceItem(account,
- invoice,
- createInvoiceItem(invoiceId, InvoiceItemType.CBA_ADJ, new BigDecimal("10")),
- ImmutableList.<InvoiceItem>of(createInvoiceItem(invoiceId, InvoiceItemType.CREDIT_ADJ, new BigDecimal("-10"))),
- null,
- null,
- null,
- invoiceItemRecordId,
- auditLog,
- accountRecordId,
- tenantRecordId,
- reportGroup,
- callContext);
+ final BusinessInvoiceItemBaseModelDao businessCreditItem = invoiceFactory.createBusinessInvoiceItem(account,
+ invoice,
+ createInvoiceItem(invoiceId, InvoiceItemType.CBA_ADJ, new BigDecimal("10")),
+ ImmutableList.<InvoiceItem>of(createInvoiceItem(invoiceId, InvoiceItemType.CREDIT_ADJ, new BigDecimal("-10"))),
+ null,
+ null,
+ null,
+ invoiceItemRecordId,
+ auditLog,
+ accountRecordId,
+ tenantRecordId,
+ reportGroup,
+ callContext);
// We treat these as NOT recognizable account credits
Assert.assertEquals(businessCreditItem.getAmount().compareTo(new BigDecimal("10")), 0);
Assert.assertEquals(businessCreditItem.getItemType(), InvoiceItemType.CBA_ADJ.toString());
Assert.assertFalse(businessCreditItem.getRevenueRecognizable());
// Invoice adjustment, not to be mixed with credits!
- final BusinessInvoiceItemBaseModelDao businessInvoiceAdjustmentItem = invoiceDao.createBusinessInvoiceItem(account,
- invoice,
- createInvoiceItem(invoiceId, InvoiceItemType.CREDIT_ADJ, new BigDecimal("-10")),
- ImmutableList.<InvoiceItem>of(createInvoiceItem(invoiceId, InvoiceItemType.RECURRING, new BigDecimal("10"))),
- null,
- null,
- null,
- invoiceItemRecordId,
- auditLog,
- accountRecordId,
- tenantRecordId,
- reportGroup,
- callContext);
+ final BusinessInvoiceItemBaseModelDao businessInvoiceAdjustmentItem = invoiceFactory.createBusinessInvoiceItem(account,
+ invoice,
+ createInvoiceItem(invoiceId, InvoiceItemType.CREDIT_ADJ, new BigDecimal("-10")),
+ ImmutableList.<InvoiceItem>of(createInvoiceItem(invoiceId, InvoiceItemType.RECURRING, new BigDecimal("10"))),
+ null,
+ null,
+ null,
+ invoiceItemRecordId,
+ auditLog,
+ accountRecordId,
+ tenantRecordId,
+ reportGroup,
+ callContext);
Assert.assertEquals(businessInvoiceAdjustmentItem.getAmount().compareTo(new BigDecimal("-10")), 0);
Assert.assertEquals(businessInvoiceAdjustmentItem.getItemType(), InvoiceItemType.CREDIT_ADJ.toString());
// Recognizable by default
Assert.assertTrue(businessInvoiceAdjustmentItem.getRevenueRecognizable());
// Invoice adjustment via refund
- final BusinessInvoiceItemBaseModelDao businessRefundInvoiceAdjustmentItem = invoiceDao.createBusinessInvoiceItem(account,
- invoice,
- createInvoiceItem(invoiceId, InvoiceItemType.REFUND_ADJ, new BigDecimal("-10")),
- ImmutableList.<InvoiceItem>of(createInvoiceItem(invoiceId, InvoiceItemType.RECURRING, new BigDecimal("10"))),
- null,
- null,
- null,
- invoiceItemRecordId,
- auditLog,
- accountRecordId,
- tenantRecordId,
- reportGroup,
- callContext);
+ final BusinessInvoiceItemBaseModelDao businessRefundInvoiceAdjustmentItem = invoiceFactory.createBusinessInvoiceItem(account,
+ invoice,
+ createInvoiceItem(invoiceId, InvoiceItemType.REFUND_ADJ, new BigDecimal("-10")),
+ ImmutableList.<InvoiceItem>of(createInvoiceItem(invoiceId, InvoiceItemType.RECURRING, new BigDecimal("10"))),
+ null,
+ null,
+ null,
+ invoiceItemRecordId,
+ auditLog,
+ accountRecordId,
+ tenantRecordId,
+ reportGroup,
+ callContext);
Assert.assertEquals(businessRefundInvoiceAdjustmentItem.getAmount().compareTo(new BigDecimal("-10")), 0);
Assert.assertEquals(businessRefundInvoiceAdjustmentItem.getItemType(), InvoiceItemType.REFUND_ADJ.toString());
// Recognizable by default
Assert.assertTrue(businessRefundInvoiceAdjustmentItem.getRevenueRecognizable());
// Item adjustment
- final BusinessInvoiceItemBaseModelDao businessInvoiceItemAdjustmentItem = invoiceDao.createBusinessInvoiceItem(account,
- invoice,
- createInvoiceItem(invoiceId, InvoiceItemType.ITEM_ADJ, new BigDecimal("-10")),
- ImmutableList.<InvoiceItem>of(createInvoiceItem(invoiceId, InvoiceItemType.RECURRING, new BigDecimal("10"))),
- null,
- null,
- null,
- invoiceItemRecordId,
- auditLog,
- accountRecordId,
- tenantRecordId,
- reportGroup,
- callContext);
+ final BusinessInvoiceItemBaseModelDao businessInvoiceItemAdjustmentItem = invoiceFactory.createBusinessInvoiceItem(account,
+ invoice,
+ createInvoiceItem(invoiceId, InvoiceItemType.ITEM_ADJ, new BigDecimal("-10")),
+ ImmutableList.<InvoiceItem>of(createInvoiceItem(invoiceId, InvoiceItemType.RECURRING, new BigDecimal("10"))),
+ null,
+ null,
+ null,
+ invoiceItemRecordId,
+ auditLog,
+ accountRecordId,
+ tenantRecordId,
+ reportGroup,
+ callContext);
Assert.assertEquals(businessInvoiceItemAdjustmentItem.getAmount().compareTo(new BigDecimal("-10")), 0);
Assert.assertEquals(businessInvoiceItemAdjustmentItem.getItemType(), InvoiceItemType.ITEM_ADJ.toString());
// Recognizable by default
Assert.assertTrue(businessInvoiceItemAdjustmentItem.getRevenueRecognizable());
// System generated account credit
- final BusinessInvoiceItemBaseModelDao businessCBAItem = invoiceDao.createBusinessInvoiceItem(account,
- invoice,
- createInvoiceItem(invoiceId, InvoiceItemType.CBA_ADJ, new BigDecimal("10")),
- ImmutableList.<InvoiceItem>of(createInvoiceItem(invoiceId, InvoiceItemType.RECURRING, new BigDecimal("30")),
- createInvoiceItem(invoiceId, InvoiceItemType.REPAIR_ADJ, new BigDecimal("-30")),
- createInvoiceItem(invoiceId, InvoiceItemType.RECURRING, new BigDecimal("20"))),
- null,
- null,
- null,
- invoiceItemRecordId,
- auditLog,
- accountRecordId,
- tenantRecordId,
- reportGroup,
- callContext);
+ final BusinessInvoiceItemBaseModelDao businessCBAItem = invoiceFactory.createBusinessInvoiceItem(account,
+ invoice,
+ createInvoiceItem(invoiceId, InvoiceItemType.CBA_ADJ, new BigDecimal("10")),
+ ImmutableList.<InvoiceItem>of(createInvoiceItem(invoiceId, InvoiceItemType.RECURRING, new BigDecimal("30")),
+ createInvoiceItem(invoiceId, InvoiceItemType.REPAIR_ADJ, new BigDecimal("-30")),
+ createInvoiceItem(invoiceId, InvoiceItemType.RECURRING, new BigDecimal("20"))),
+ null,
+ null,
+ null,
+ invoiceItemRecordId,
+ auditLog,
+ accountRecordId,
+ tenantRecordId,
+ reportGroup,
+ callContext);
Assert.assertEquals(businessCBAItem.getAmount().compareTo(new BigDecimal("10")), 0);
Assert.assertEquals(businessCBAItem.getItemType(), InvoiceItemType.CBA_ADJ.toString());
// Recognizable by default
@@ -246,7 +248,7 @@ public class TestBusinessInvoiceFactory extends AnalyticsTestSuiteNoDB {
allInvoiceItems.putAll(originalInvoice1, ImmutableList.<InvoiceItem>of(recurring1, repair1, reparation1));
allInvoiceItems.putAll(originalInvoice2, ImmutableList.<InvoiceItem>of(recurring2, repair2, reparation2));
allInvoiceItems.put(otherInvoice3, externalCharge);
- final Collection<InvoiceItem> sanitizedInvoiceItems = invoiceDao.sanitizeInvoiceItems(allInvoiceItems);
+ final Collection<InvoiceItem> sanitizedInvoiceItems = invoiceFactory.sanitizeInvoiceItems(allInvoiceItems);
Assert.assertEquals(sanitizedInvoiceItems.size(), 2 + 2 + 1);
for (final InvoiceItem invoiceItem : sanitizedInvoiceItems) {
if (invoiceItem.getId().equals(recurring1.getId())) {
@@ -276,4 +278,192 @@ public class TestBusinessInvoiceFactory extends AnalyticsTestSuiteNoDB {
}
}
}
+
+ @Test(groups = "fast")
+ public void testFindReparee() throws Exception {
+ final UUID subscriptionId1 = UUID.randomUUID();
+ final LocalDate startDate1 = new LocalDate(2013, 4, 1);
+ final LocalDate endDate1 = new LocalDate(2013, 4, 30);
+ final BigDecimal amount1 = new BigDecimal("30");
+ final UUID originalInvoice1 = UUID.randomUUID();
+ final InvoiceItem recurring1 = createInvoiceItem(originalInvoice1, InvoiceItemType.RECURRING, subscriptionId1, startDate1, endDate1, amount1, null);
+ final InvoiceItem repair1 = createInvoiceItem(originalInvoice1, InvoiceItemType.REPAIR_ADJ, subscriptionId1, startDate1, endDate1, amount1.negate(), recurring1.getId());
+
+ final UUID repareeInvoice1 = UUID.randomUUID();
+ final LocalDate repareeEndDate1 = new LocalDate(2013, 4, 10);
+ final BigDecimal repareeAmount1 = new BigDecimal("10");
+ final InvoiceItem reparee1 = createInvoiceItem(repareeInvoice1, InvoiceItemType.RECURRING, subscriptionId1, startDate1, repareeEndDate1, repareeAmount1, null);
+
+ Assert.assertEquals(invoiceFactory.findRepareeInvoiceItems(ImmutableList.<InvoiceItem>of(recurring1, repair1, reparee1)).size(), 1);
+ Assert.assertEquals(invoiceFactory.findRepareeInvoiceItems(ImmutableList.<InvoiceItem>of(recurring1, repair1, reparee1)).get(reparee1), repair1);
+ }
+
+ @Test(groups = "fast")
+ public void testCantFindRepareeWrongSubscription() throws Exception {
+ final UUID subscriptionId1 = UUID.randomUUID();
+ final LocalDate startDate1 = new LocalDate(2013, 4, 1);
+ final LocalDate endDate1 = new LocalDate(2013, 4, 30);
+ final BigDecimal amount1 = new BigDecimal("30");
+ final UUID originalInvoice1 = UUID.randomUUID();
+ final InvoiceItem recurring1 = createInvoiceItem(originalInvoice1, InvoiceItemType.RECURRING, subscriptionId1, startDate1, endDate1, amount1, null);
+ final InvoiceItem repair1 = createInvoiceItem(originalInvoice1, InvoiceItemType.REPAIR_ADJ, subscriptionId1, startDate1, endDate1, amount1.negate(), recurring1.getId());
+
+ final UUID repareeInvoice1 = UUID.randomUUID();
+ final LocalDate repareeEndDate1 = new LocalDate(2013, 4, 10);
+ final BigDecimal repareeAmount1 = new BigDecimal("10");
+ final InvoiceItem reparee1 = createInvoiceItem(repareeInvoice1, InvoiceItemType.RECURRING, UUID.randomUUID(), startDate1, repareeEndDate1, repareeAmount1, null);
+
+ Assert.assertEquals(invoiceFactory.findRepareeInvoiceItems(ImmutableList.<InvoiceItem>of(recurring1, repair1, reparee1)).size(), 0);
+ }
+
+ @Test(groups = "fast")
+ public void testCantFindRepareeWrongEndDate() throws Exception {
+ final UUID subscriptionId1 = UUID.randomUUID();
+ final LocalDate startDate1 = new LocalDate(2013, 4, 1);
+ final LocalDate endDate1 = new LocalDate(2013, 4, 30);
+ final BigDecimal amount1 = new BigDecimal("30");
+ final UUID originalInvoice1 = UUID.randomUUID();
+ final InvoiceItem recurring1 = createInvoiceItem(originalInvoice1, InvoiceItemType.RECURRING, subscriptionId1, startDate1, endDate1, amount1, null);
+ final InvoiceItem repair1 = createInvoiceItem(originalInvoice1, InvoiceItemType.REPAIR_ADJ, subscriptionId1, startDate1, endDate1, amount1.negate(), recurring1.getId());
+
+ final UUID repareeInvoice1 = UUID.randomUUID();
+ final LocalDate repareeEndDate1 = new LocalDate(2038, 4, 10);
+ final BigDecimal repareeAmount1 = new BigDecimal("10");
+ final InvoiceItem reparee1 = createInvoiceItem(repareeInvoice1, InvoiceItemType.RECURRING, subscriptionId1, startDate1, repareeEndDate1, repareeAmount1, null);
+
+ Assert.assertEquals(invoiceFactory.findRepareeInvoiceItems(ImmutableList.<InvoiceItem>of(recurring1, repair1, reparee1)).size(), 0);
+ }
+
+ @Test(groups = "fast")
+ public void testMergeCBAsNormal() throws Exception {
+ final UUID invoiceId1 = UUID.randomUUID();
+ final InvoiceItem cba1 = createInvoiceItem(invoiceId1, InvoiceItemType.CBA_ADJ, BigDecimal.ONE);
+ final InvoiceItem cba2 = createInvoiceItem(invoiceId1, InvoiceItemType.CBA_ADJ, BigDecimal.TEN.negate());
+ final InvoiceItem charge = createInvoiceItem(invoiceId1, InvoiceItemType.EXTERNAL_CHARGE, new BigDecimal("9"));
+
+ final UUID invoiceId2 = UUID.randomUUID();
+ final InvoiceItem cba3 = createInvoiceItem(invoiceId2, InvoiceItemType.CBA_ADJ, BigDecimal.ONE);
+
+ final Multimap<UUID, InvoiceItem> allInvoiceItems = ArrayListMultimap.<UUID, InvoiceItem>create();
+ allInvoiceItems.put(invoiceId1, cba1);
+ allInvoiceItems.put(invoiceId1, cba2);
+ allInvoiceItems.put(invoiceId1, charge);
+ allInvoiceItems.put(invoiceId2, cba3);
+
+ final Collection<AdjustedCBAInvoiceItem> adjustedCBAInvoiceItems = invoiceFactory.buildMergedCBAItems(allInvoiceItems, ImmutableMap.<InvoiceItem, InvoiceItem>of());
+ Assert.assertEquals(adjustedCBAInvoiceItems.size(), 2);
+ for (final AdjustedCBAInvoiceItem item : adjustedCBAInvoiceItems) {
+ Assert.assertEquals(item.getAmount(), item.getInvoiceId().equals(invoiceId1) ? new BigDecimal("-9") : BigDecimal.ONE);
+ }
+ }
+
+ @Test(groups = "fast")
+ public void testMergeCBAsWithRepairAndPayment() throws Exception {
+ /*
+ * Scenario:
+ * Recurring1: +30
+ * Repair1: -30
+ * CBA: +30
+ */
+ final UUID subscriptionId1 = UUID.randomUUID();
+ final LocalDate startDate1 = new LocalDate(2013, 4, 1);
+ final LocalDate endDate1 = new LocalDate(2013, 4, 30);
+ final BigDecimal amount1 = new BigDecimal("30");
+ final UUID invoiceId1 = UUID.randomUUID();
+ final InvoiceItem recurring1 = createInvoiceItem(invoiceId1, InvoiceItemType.RECURRING, subscriptionId1, startDate1, endDate1, amount1, null);
+ final InvoiceItem repair1 = createInvoiceItem(invoiceId1, InvoiceItemType.REPAIR_ADJ, subscriptionId1, startDate1, endDate1, amount1.negate(), recurring1.getId());
+ final InvoiceItem cba1 = createInvoiceItem(invoiceId1, InvoiceItemType.CBA_ADJ, amount1);
+
+ /*
+ * Scenario:
+ * Recurring1: +10
+ * CBA use: -10
+ * Charge: +9
+ * CBA use: -9
+ */
+ final UUID invoiceId2 = UUID.randomUUID();
+ final LocalDate repareeEndDate1 = new LocalDate(2013, 4, 10);
+ final BigDecimal repareeAmount1 = new BigDecimal("10");
+ final InvoiceItem reparee1 = createInvoiceItem(invoiceId2, InvoiceItemType.RECURRING, subscriptionId1, startDate1, repareeEndDate1, repareeAmount1, null);
+ final InvoiceItem cba2 = createInvoiceItem(invoiceId2, InvoiceItemType.CBA_ADJ, repareeAmount1.negate());
+ final InvoiceItem charge = createInvoiceItem(invoiceId2, InvoiceItemType.EXTERNAL_CHARGE, new BigDecimal("9"));
+ final InvoiceItem cba3 = createInvoiceItem(invoiceId2, InvoiceItemType.CBA_ADJ, new BigDecimal("-9"));
+
+ final Multimap<UUID, InvoiceItem> allInvoiceItems = ArrayListMultimap.<UUID, InvoiceItem>create();
+ allInvoiceItems.put(invoiceId1, recurring1);
+ allInvoiceItems.put(invoiceId1, repair1);
+ allInvoiceItems.put(invoiceId1, cba1);
+ allInvoiceItems.put(invoiceId2, reparee1);
+ allInvoiceItems.put(invoiceId2, cba2);
+ allInvoiceItems.put(invoiceId2, charge);
+ allInvoiceItems.put(invoiceId2, cba3);
+
+ /*
+ * Expected invoice 1:
+ * Recurring1: +30
+ * Adjustment: -20
+ * Recurring1: +10
+ * CBA: +20
+ *
+ * Expected invoice 2:
+ * Charge: +9
+ * CBA use: -9
+ */
+ final Collection<AdjustedCBAInvoiceItem> adjustedCBAInvoiceItems = invoiceFactory.buildMergedCBAItems(allInvoiceItems, ImmutableMap.<InvoiceItem, InvoiceItem>of(reparee1, repair1));
+ Assert.assertEquals(adjustedCBAInvoiceItems.size(), 2);
+ for (final AdjustedCBAInvoiceItem item : adjustedCBAInvoiceItems) {
+ Assert.assertEquals(item.getAmount(), item.getInvoiceId().equals(invoiceId1) ? new BigDecimal("20") : new BigDecimal("-9"));
+ }
+ }
+
+ // TODO Should add the same test, but where the second invoice is repaired to check the blacklist stuff works as expected
+ @Test(groups = "fast")
+ public void testMergeCBAsWithRepairAndNoPayment() throws Exception {
+ /*
+ * Scenario:
+ * Recurring1: +30
+ * Repair1: -30
+ */
+ final UUID subscriptionId1 = UUID.randomUUID();
+ final LocalDate startDate1 = new LocalDate(2013, 4, 1);
+ final LocalDate endDate1 = new LocalDate(2013, 4, 30);
+ final BigDecimal amount1 = new BigDecimal("30");
+ final UUID invoiceId1 = UUID.randomUUID();
+ final InvoiceItem recurring1 = createInvoiceItem(invoiceId1, InvoiceItemType.RECURRING, subscriptionId1, startDate1, endDate1, amount1, null);
+ final InvoiceItem repair1 = createInvoiceItem(invoiceId1, InvoiceItemType.REPAIR_ADJ, subscriptionId1, startDate1, endDate1, amount1.negate(), recurring1.getId());
+
+ /*
+ * Scenario (assume account has 9 credits):
+ * Recurring1: +10
+ * Charge: +9
+ * CBA use: -9
+ */
+ final UUID invoiceId2 = UUID.randomUUID();
+ final LocalDate repareeEndDate1 = new LocalDate(2013, 4, 10);
+ final BigDecimal repareeAmount1 = new BigDecimal("10");
+ final InvoiceItem reparee1 = createInvoiceItem(invoiceId2, InvoiceItemType.RECURRING, subscriptionId1, startDate1, repareeEndDate1, repareeAmount1, null);
+ final InvoiceItem charge = createInvoiceItem(invoiceId2, InvoiceItemType.EXTERNAL_CHARGE, new BigDecimal("9"));
+ final InvoiceItem cba1 = createInvoiceItem(invoiceId2, InvoiceItemType.CBA_ADJ, new BigDecimal("-9"));
+
+ final Multimap<UUID, InvoiceItem> allInvoiceItems = ArrayListMultimap.<UUID, InvoiceItem>create();
+ allInvoiceItems.put(invoiceId1, recurring1);
+ allInvoiceItems.put(invoiceId1, repair1);
+ allInvoiceItems.put(invoiceId2, reparee1);
+ allInvoiceItems.put(invoiceId2, cba1);
+ allInvoiceItems.put(invoiceId2, charge);
+
+ /*
+ * Expected invoice 1:
+ * Recurring1: +30
+ * Adjustment: -20
+ * Recurring1: +10
+ *
+ * Expected invoice 2:
+ * Charge: +9
+ * CBA use: -9
+ */
+ final Collection<AdjustedCBAInvoiceItem> adjustedCBAInvoiceItems = invoiceFactory.buildMergedCBAItems(allInvoiceItems, ImmutableMap.<InvoiceItem, InvoiceItem>of(reparee1, repair1));
+ Assert.assertEquals(adjustedCBAInvoiceItems.size(), 1);
+ Assert.assertEquals(adjustedCBAInvoiceItems.iterator().next().getAmount(), new BigDecimal("-9"));
+ }
}