killbill-memoizeit

analytics: redirect right invoice items to the right table Signed-off-by:

4/11/2013 6:17:46 PM

Details

diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceDao.java
index 023ba78..52432dc 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceDao.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/BusinessInvoiceDao.java
@@ -26,8 +26,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
-import javax.annotation.Nullable;
-
 import org.joda.time.DateTime;
 import org.joda.time.LocalDate;
 import org.osgi.service.log.LogService;
@@ -45,6 +43,7 @@ import com.ning.billing.invoice.api.InvoiceItemType;
 import com.ning.billing.osgi.bundles.analytics.AnalyticsRefreshException;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessAccountModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceItemBaseModelDao;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceItemBaseModelDao.BusinessInvoiceItemType;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceModelDao;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessModelDaoBase.ReportGroup;
 import com.ning.billing.util.audit.AuditLog;
@@ -55,6 +54,8 @@ import com.ning.killbill.osgi.libs.killbill.OSGIKillbillDataSource;
 import com.ning.killbill.osgi.libs.killbill.OSGIKillbillLogService;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
 
 public class BusinessInvoiceDao extends BusinessAnalyticsDaoBase {
 
@@ -127,8 +128,13 @@ public class BusinessInvoiceDao extends BusinessAnalyticsDaoBase {
                 final BusinessInvoiceItemBaseModelDao businessInvoiceItem = createBusinessInvoiceItem(account,
                                                                                                       invoice,
                                                                                                       invoiceItem,
-                                                                                                      // TODO Will be used for REPAIR_ADJ
-                                                                                                      null,
+                                                                                                      Collections2.filter(sanitizedInvoiceItems,
+                                                                                                                          new Predicate<InvoiceItem>() {
+                                                                                                                              @Override
+                                                                                                                              public boolean apply(final InvoiceItem input) {
+                                                                                                                                  return !input.getId().equals(invoiceItem.getId());
+                                                                                                                              }
+                                                                                                                          }),
                                                                                                       context);
                 if (businessInvoiceItem != null) {
                     businessInvoiceItems.add(businessInvoiceItem);
@@ -181,7 +187,7 @@ public class BusinessInvoiceDao extends BusinessAnalyticsDaoBase {
     private BusinessInvoiceItemBaseModelDao createBusinessInvoiceItem(final Account account,
                                                                       final Invoice invoice,
                                                                       final InvoiceItem invoiceItem,
-                                                                      @Nullable final Long secondInvoiceItemRecordId,
+                                                                      final Collection<InvoiceItem> otherInvoiceItemsOnInvoice,
                                                                       final TenantContext context) throws AnalyticsRefreshException {
         SubscriptionBundle bundle = null;
         // Subscription and bundle could be null for e.g. credits or adjustments
@@ -205,10 +211,32 @@ public class BusinessInvoiceDao extends BusinessAnalyticsDaoBase {
         final Long tenantRecordId = getTenantRecordId(context);
         final ReportGroup reportGroup = getReportGroup(account.getId(), context);
 
+        final BusinessInvoiceItemType businessInvoiceItemType;
+        if (isCharge(invoiceItem)) {
+            businessInvoiceItemType = BusinessInvoiceItemType.CHARGE;
+        } else if (isAccountCreditItem(invoiceItem, otherInvoiceItemsOnInvoice)) {
+            businessInvoiceItemType = BusinessInvoiceItemType.ACCOUNT_CREDIT;
+        } else if (isInvoiceItemAdjustementItem(invoiceItem)) {
+            businessInvoiceItemType = BusinessInvoiceItemType.INVOICE_ITEM_ADJUSTMENT;
+        } else if (isInvoiceAdjustementItem(invoiceItem, otherInvoiceItemsOnInvoice)) {
+            businessInvoiceItemType = BusinessInvoiceItemType.INVOICE_ADJUSTMENT;
+        } else {
+            // We don't care
+            return null;
+        }
+
+        final Long secondInvoiceItemRecordId;
+        if (invoiceItem instanceof AdjustmentInvoiceItemForRepair) {
+            secondInvoiceItemRecordId = getInvoiceItemRecordId(((AdjustmentInvoiceItemForRepair) invoiceItem).getSecondId(), context);
+        } else {
+            secondInvoiceItemRecordId = null;
+        }
+
         return BusinessInvoiceItemBaseModelDao.create(account,
                                                       accountRecordId,
                                                       invoice,
                                                       invoiceItem,
+                                                      businessInvoiceItemType,
                                                       invoiceItemRecordId,
                                                       secondInvoiceItemRecordId,
                                                       bundle,
@@ -219,6 +247,38 @@ public class BusinessInvoiceDao extends BusinessAnalyticsDaoBase {
                                                       reportGroup);
     }
 
+    // Invoice adjustments
+    private boolean isInvoiceAdjustementItem(final InvoiceItem invoiceItem, final Collection<InvoiceItem> otherInvoiceItemsOnInvoice) {
+        // Either REFUND_ADJ
+        return InvoiceItemType.REFUND_ADJ.equals(invoiceItem.getInvoiceItemType()) ||
+               // Or invoice level credit
+               (InvoiceItemType.CREDIT_ADJ.equals(invoiceItem.getInvoiceItemType()) &&
+                !isAccountCreditItem(invoiceItem, otherInvoiceItemsOnInvoice));
+    }
+
+    // Item adjustments
+    private boolean isInvoiceItemAdjustementItem(final InvoiceItem invoiceItem) {
+        return InvoiceItemType.ITEM_ADJ.equals(invoiceItem.getInvoiceItemType());
+    }
+
+    // Account credits, used or consumed
+    private boolean isAccountCreditItem(final InvoiceItem invoiceItem, final Collection<InvoiceItem> otherInvoiceItemsOnInvoice) {
+        // Either CBA (positive or negative, i.e. given or consumed)
+        return InvoiceItemType.CBA_ADJ.equals(invoiceItem.getInvoiceItemType()) ||
+               // Or credit adj on its on own invoice (credit adj is negative, hence the CBA item)
+               (InvoiceItemType.CREDIT_ADJ.equals(invoiceItem.getInvoiceItemType()) &&
+                otherInvoiceItemsOnInvoice.size() == 1 &&
+                InvoiceItemType.CBA_ADJ.equals(otherInvoiceItemsOnInvoice.iterator().next().getInvoiceItemType()) &&
+                otherInvoiceItemsOnInvoice.iterator().next().getAmount().compareTo(invoiceItem.getAmount().negate()) == 0);
+    }
+
+    // Regular line item (charges)
+    private boolean isCharge(final InvoiceItem invoiceItem) {
+        return InvoiceItemType.EXTERNAL_CHARGE.equals(invoiceItem.getInvoiceItemType()) ||
+               InvoiceItemType.FIXED.equals(invoiceItem.getInvoiceItemType()) ||
+               InvoiceItemType.RECURRING.equals(invoiceItem.getInvoiceItemType());
+    }
+
     @VisibleForTesting
     Collection<InvoiceItem> sanitizeInvoiceItems(final List<InvoiceItem> allInvoiceItems) {
         // Build a convenience mapping between items -> repair_adj items (inverse of linkedItemId)
@@ -365,8 +425,13 @@ public class BusinessInvoiceDao extends BusinessAnalyticsDaoBase {
 
         @Override
         public UUID getId() {
-            // Fake id, doesn't exist in raw tables
-            return UUID.randomUUID();
+            // We pretend to be the repair, the reparation item record id
+            // will be available as secondId
+            return repairInvoiceItem.getId();
+        }
+
+        public UUID getSecondId() {
+            return reparationInvoiceItem.getId();
         }
 
         @Override
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessInvoiceItemBaseModelDao.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessInvoiceItemBaseModelDao.java
index 4059810..5b29b03 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessInvoiceItemBaseModelDao.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/dao/model/BusinessInvoiceItemBaseModelDao.java
@@ -30,7 +30,6 @@ import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 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.util.audit.AuditLog;
 
 public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBase {
@@ -71,10 +70,18 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
     private String currency;
     private UUID linkedItemId;
 
+    public enum BusinessInvoiceItemType {
+        INVOICE_ADJUSTMENT,
+        INVOICE_ITEM_ADJUSTMENT,
+        ACCOUNT_CREDIT,
+        CHARGE
+    }
+
     public static BusinessInvoiceItemBaseModelDao create(final Account account,
                                                          final Long accountRecordId,
                                                          final Invoice invoice,
                                                          final InvoiceItem invoiceItem,
+                                                         final BusinessInvoiceItemType businessInvoiceItemType,
                                                          final Long invoiceItemRecordId,
                                                          final Long secondInvoiceItemRecordId,
                                                          @Nullable final SubscriptionBundle bundle,
@@ -83,7 +90,7 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
                                                          final AuditLog creationAuditLog,
                                                          final Long tenantRecordId,
                                                          @Nullable final ReportGroup reportGroup) {
-        if (InvoiceItemType.REFUND_ADJ.equals(invoiceItem.getInvoiceItemType())) {
+        if (BusinessInvoiceItemType.INVOICE_ADJUSTMENT.equals(businessInvoiceItemType)) {
             return new BusinessInvoiceAdjustmentModelDao(account,
                                                          accountRecordId,
                                                          invoice,
@@ -96,9 +103,7 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
                                                          creationAuditLog,
                                                          tenantRecordId,
                                                          reportGroup);
-        } else if (InvoiceItemType.EXTERNAL_CHARGE.equals(invoiceItem.getInvoiceItemType()) ||
-                   InvoiceItemType.FIXED.equals(invoiceItem.getInvoiceItemType()) ||
-                   InvoiceItemType.RECURRING.equals(invoiceItem.getInvoiceItemType())) {
+        } else if (BusinessInvoiceItemType.CHARGE.equals(businessInvoiceItemType)) {
             return new BusinessInvoiceItemModelDao(account,
                                                    accountRecordId,
                                                    invoice,
@@ -111,7 +116,7 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
                                                    creationAuditLog,
                                                    tenantRecordId,
                                                    reportGroup);
-        } else if (InvoiceItemType.ITEM_ADJ.equals(invoiceItem.getInvoiceItemType())) {
+        } else if (BusinessInvoiceItemType.INVOICE_ADJUSTMENT.equals(businessInvoiceItemType)) {
             return new BusinessInvoiceItemAdjustmentModelDao(account,
                                                              accountRecordId,
                                                              invoice,
@@ -124,8 +129,7 @@ public abstract class BusinessInvoiceItemBaseModelDao extends BusinessModelDaoBa
                                                              creationAuditLog,
                                                              tenantRecordId,
                                                              reportGroup);
-        } else if (InvoiceItemType.CBA_ADJ.equals(invoiceItem.getInvoiceItemType()) ||
-                   InvoiceItemType.CREDIT_ADJ.equals(invoiceItem.getInvoiceItemType())) {
+        } else if (BusinessInvoiceItemType.ACCOUNT_CREDIT.equals(businessInvoiceItemType)) {
             return new BusinessInvoiceItemCreditModelDao(account,
                                                          accountRecordId,
                                                          invoice,
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteNoDB.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteNoDB.java
index 24423e1..532c579 100644
--- a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteNoDB.java
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/AnalyticsTestSuiteNoDB.java
@@ -51,6 +51,7 @@ import com.ning.billing.junction.api.Blockable.Type;
 import com.ning.billing.junction.api.BlockingState;
 import com.ning.billing.osgi.bundles.analytics.api.BusinessEntityBase;
 import com.ning.billing.osgi.bundles.analytics.dao.TestCallContext;
+import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessInvoiceItemBaseModelDao.BusinessInvoiceItemType;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessModelDaoBase;
 import com.ning.billing.osgi.bundles.analytics.dao.model.BusinessModelDaoBase.ReportGroup;
 import com.ning.billing.payment.api.Payment;
@@ -88,6 +89,7 @@ public abstract class AnalyticsTestSuiteNoDB {
     protected final Long tenantRecordId = 9L;
 
     protected final ReportGroup reportGroup = ReportGroup.partner;
+    protected final BusinessInvoiceItemType invoiceItemType = BusinessInvoiceItemType.INVOICE_ITEM_ADJUSTMENT;
 
     protected Account account;
     protected SubscriptionBundle bundle;
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoice.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoice.java
index f59b325..098b4ca 100644
--- a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoice.java
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoice.java
@@ -40,6 +40,7 @@ public class TestBusinessInvoice extends AnalyticsTestSuiteNoDB {
                                                                                                                accountRecordId,
                                                                                                                invoice,
                                                                                                                invoiceItem,
+                                                                                                               invoiceItemType,
                                                                                                                invoiceItemRecordId,
                                                                                                                secondInvoiceItemRecordId,
                                                                                                                bundle,
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoiceItem.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoiceItem.java
index bd857d5..8008081 100644
--- a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoiceItem.java
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessInvoiceItem.java
@@ -30,6 +30,7 @@ public class TestBusinessInvoiceItem extends AnalyticsTestSuiteNoDB {
                                                                                                                accountRecordId,
                                                                                                                invoice,
                                                                                                                invoiceItem,
+                                                                                                               invoiceItemType,
                                                                                                                invoiceItemRecordId,
                                                                                                                secondInvoiceItemRecordId,
                                                                                                                bundle,
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessSnapshot.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessSnapshot.java
index c6b4773..db2d2d8 100644
--- a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessSnapshot.java
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/api/TestBusinessSnapshot.java
@@ -78,6 +78,7 @@ public class TestBusinessSnapshot extends AnalyticsTestSuiteNoDB {
                                                                                                                accountRecordId,
                                                                                                                invoice,
                                                                                                                invoiceItem,
+                                                                                                               invoiceItemType,
                                                                                                                invoiceItemRecordId,
                                                                                                                secondInvoiceItemRecordId,
                                                                                                                bundle,
diff --git a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceDao.java b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceDao.java
index 7258265..7a17fbe 100644
--- a/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceDao.java
+++ b/osgi-bundles/bundles/analytics/src/test/java/com/ning/billing/osgi/bundles/analytics/dao/TestBusinessInvoiceDao.java
@@ -107,29 +107,27 @@ public class TestBusinessInvoiceDao extends AnalyticsTestSuiteNoDB {
             if (invoiceItem.getId().equals(recurring1.getId())) {
                 Assert.assertEquals(invoiceItem, recurring1);
             } else if (invoiceItem.getId().equals(repair1.getId())) {
-                Assert.fail("Repair item 1 shouldn't be in the sanitized elements");
+                if (InvoiceItemType.ITEM_ADJ.equals(invoiceItem.getInvoiceItemType()) && invoiceItem.getLinkedItemId().equals(recurring1.getId())) {
+                    Assert.assertEquals(invoiceItem.getAmount(), new BigDecimal("20").negate());
+                } else {
+                    Assert.fail("Repair item 1 shouldn't be in the sanitized elements");
+                }
             } else if (invoiceItem.getId().equals(reparation1.getId())) {
                 Assert.fail("Reparation item 1 shouldn't be in the sanitized elements");
             } else if (invoiceItem.getId().equals(recurring2.getId())) {
                 Assert.assertEquals(invoiceItem, recurring2);
             } else if (invoiceItem.getId().equals(repair2.getId())) {
-                Assert.fail("Repair item 2 shouldn't be in the sanitized elements");
+                if (InvoiceItemType.ITEM_ADJ.equals(invoiceItem.getInvoiceItemType()) && invoiceItem.getLinkedItemId().equals(recurring2.getId())) {
+                    Assert.assertEquals(invoiceItem.getAmount(), new BigDecimal("15").negate());
+                } else {
+                    Assert.fail("Repair item 2 shouldn't be in the sanitized elements");
+                }
             } else if (invoiceItem.getId().equals(reparation2.getId())) {
                 Assert.fail("Reparation item 2 shouldn't be in the sanitized elements");
             } else if (invoiceItem.getId().equals(externalCharge.getId())) {
                 Assert.assertEquals(invoiceItem, externalCharge);
             } else {
-                if (InvoiceItemType.ITEM_ADJ.equals(invoiceItem.getInvoiceItemType())) {
-                    if (invoiceItem.getLinkedItemId().equals(recurring1.getId())) {
-                        Assert.assertEquals(invoiceItem.getAmount(), new BigDecimal("20").negate());
-                    } else if (invoiceItem.getLinkedItemId().equals(recurring2.getId())) {
-                        Assert.assertEquals(invoiceItem.getAmount(), new BigDecimal("15").negate());
-                    } else {
-                        Assert.fail("Shouldn't be in the sanitized elements: " + invoiceItem);
-                    }
-                } else {
-                    Assert.fail("Shouldn't be in the sanitized elements: " + invoiceItem);
-                }
+                Assert.fail("Shouldn't be in the sanitized elements: " + invoiceItem);
             }
         }
     }