killbill-aplcache

Details

diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
index 4c63d98..9bd830e 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
@@ -58,12 +58,7 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
 
 	@Override
 	public BigDecimal getAccountBalance(UUID accountId) {
-		List<Invoice> invoices = getInvoicesByAccount(accountId);
-		BigDecimal result = BigDecimal.ZERO;
-		for(Invoice invoice : invoices) {
-			result = result.add(invoice.getAmountOutstanding());
-		}
-		return result;
+		return dao.getAccountBalance(accountId);
 	}
 
 }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
index d5d4ce9..35f03c2 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
@@ -16,6 +16,7 @@
 
 package com.ning.billing.invoice.dao;
 
+import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 import java.util.UUID;
@@ -156,4 +157,9 @@ public class DefaultInvoiceDao implements InvoiceDao {
         return invoiceDao.getInvoicePayment(paymentAttemptId);
     }
 
+	@Override
+	public BigDecimal getAccountBalance(UUID accountId) {
+		return invoiceDao.getAccountBalance(accountId.toString());
+	}
+
 }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
index e90d22c..322c286 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
@@ -16,6 +16,7 @@
 
 package com.ning.billing.invoice.dao;
 
+import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 import java.util.UUID;
@@ -45,4 +46,6 @@ public interface InvoiceDao {
 
     void notifyOfPaymentAttempt(InvoicePayment invoicePayment);
 
+    BigDecimal getAccountBalance(UUID accountId);
+
 }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceSqlDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceSqlDao.java
index bb03e8b..1f37102 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceSqlDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceSqlDao.java
@@ -84,6 +84,28 @@ public interface InvoiceSqlDao extends EntityDao<Invoice>, Transactional<Invoice
 
     @SqlUpdate
     void notifyOfPaymentAttempt(@Bind(binder = InvoicePaymentBinder.class) InvoicePayment invoicePayment);
+    
+    @SqlQuery
+    @RegisterMapper(BalanceMapper.class)
+    BigDecimal getAccountBalance(@Bind("accountId") final String accountId);
+
+    public static class BalanceMapper implements ResultSetMapper<BigDecimal> {
+        @Override
+        public BigDecimal map(final int index, final ResultSet result, final StatementContext context) throws SQLException {
+            BigDecimal amount_invoiced = result.getBigDecimal("amount_invoiced");
+            BigDecimal amount_paid = result.getBigDecimal("amount_paid");
+
+            if (amount_invoiced == null) {
+                amount_invoiced = BigDecimal.ZERO;
+            }
+
+            if (amount_paid == null) {
+                amount_paid = BigDecimal.ZERO;
+            }
+
+            return amount_invoiced.subtract(amount_paid);
+        };
+    }
 
     @BindingAnnotation(InvoiceBinder.InvoiceBinderFactory.class)
     @Retention(RetentionPolicy.RUNTIME)
@@ -164,5 +186,7 @@ public interface InvoiceSqlDao extends EntityDao<Invoice>, Transactional<Invoice
             return new InvoicePayment(invoiceId, amount, currency, paymentAttemptId, paymentAttemptDate);
         }
     }
+
+
 }
 
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceSqlDao.sql.stg b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceSqlDao.sql.stg
index 1657f7e..5d5725d 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceSqlDao.sql.stg
+++ b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceSqlDao.sql.stg
@@ -81,6 +81,15 @@ getInvoicePayment() ::= <<
      WHERE payment_id = :payment_id
 >>
 
+getAccountBalance() ::= <<
+  SELECT SUM(iis.total_amount) AS amount_invoiced, SUM(ips.total_paid) AS amount_paid
+  FROM invoices i
+  LEFT JOIN invoice_payment_summary ips ON i.id = ips.invoice_id
+  LEFT JOIN invoice_item_summary iis ON i.id = iis.invoice_id
+  WHERE i.account_id = :accountId
+  GROUP BY i.account_id;
+>>
+
 test() ::= <<
   SELECT 1
   FROM invoices;
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
index c840928..859e09b 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
@@ -305,5 +305,74 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
         List<Invoice> items4 = invoiceDao.getInvoicesBySubscription(subscriptionId4.toString());
         assertEquals(items4.size(), 1);
     }
+    
+    @Test
+    public void testAccountBalance() {
+        UUID accountId = UUID.randomUUID();
+        DateTime targetDate1 = new DateTime(2011, 10, 6, 0, 0, 0, 0);
+        Invoice invoice1 = new DefaultInvoice(accountId, targetDate1, Currency.USD);
+        invoiceDao.create(invoice1);
+
+        DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
+        DateTime endDate = startDate.plusMonths(1);
+
+        BigDecimal rate1 = new BigDecimal("17.0");
+        BigDecimal rate2 = new BigDecimal("42.0");
+
+        DefaultInvoiceItem item1 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test A", rate1, rate1, Currency.USD);
+        invoiceItemDao.create(item1);
+
+        DefaultInvoiceItem item2 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test B", rate2, rate2, Currency.USD);
+        invoiceItemDao.create(item2);
+
+        BigDecimal payment1 = new BigDecimal("48.0");
+        
+        // TODO - reenable when DefaultInvoicePayement is visible in this branch
+        //InvoicePayment payment = new DefaultInvoicePayment(invoice1.getId(), new DateTime(), payment1, Currency.USD);
+        //invoicePaymentDao.create(payment);
+        //
+        //BigDecimal balance = invoiceDao.getAccountBalance(accountId);
+        //assertEquals(balance.compareTo(rate1.add(rate2).subtract(payment1)), 0);
+
+    }
+    
+    @Test
+    public void testAccountBalanceWithNoPayments() {
+        UUID accountId = UUID.randomUUID();
+        DateTime targetDate1 = new DateTime(2011, 10, 6, 0, 0, 0, 0);
+        Invoice invoice1 = new DefaultInvoice(accountId, targetDate1, Currency.USD);
+        invoiceDao.create(invoice1);
 
+        DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
+        DateTime endDate = startDate.plusMonths(1);
+
+        BigDecimal rate1 = new BigDecimal("17.0");
+        BigDecimal rate2 = new BigDecimal("42.0");
+
+        DefaultInvoiceItem item1 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test A", rate1, rate1, Currency.USD);
+        invoiceItemDao.create(item1);
+
+        DefaultInvoiceItem item2 = new DefaultInvoiceItem(invoice1.getId(), UUID.randomUUID(), startDate, endDate, "test B", rate2, rate2, Currency.USD);
+        invoiceItemDao.create(item2);
+
+        BigDecimal balance = invoiceDao.getAccountBalance(accountId);
+        assertEquals(balance.compareTo(rate1.add(rate2)), 0);
+    }
+
+
+    @Test
+    public void testAccountBalanceWithNoInvoiceItems() {
+        UUID accountId = UUID.randomUUID();
+        DateTime targetDate1 = new DateTime(2011, 10, 6, 0, 0, 0, 0);
+        Invoice invoice1 = new DefaultInvoice(accountId, targetDate1, Currency.USD);
+        invoiceDao.create(invoice1);
+
+        // TODO - reenable when DefaultInvoicePayement is visible in this branch
+        //BigDecimal payment1 = new BigDecimal("48.0");
+        //InvoicePayment payment = new DefaultInvoicePayment(invoice1.getId(), new DateTime(), payment1, Currency.USD);
+        //invoicePaymentDao.create(payment);
+        //
+        //BigDecimal balance = invoiceDao.getAccountBalance(accountId);
+        //assertEquals(balance.compareTo(BigDecimal.ZERO.subtract(payment1)), 0);
+    }
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
index 446cc2b..2ef150c 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/MockInvoiceDao.java
@@ -193,4 +193,14 @@ public class MockInvoiceDao implements InvoiceDao {
           invoicePayments.put(invoicePayment.getPaymentAttemptId(), invoicePayment);
       }
     }
+
+	@Override
+	public BigDecimal getAccountBalance(UUID accountId) {
+		List<Invoice> invoices = getInvoicesByAccount(accountId.toString());
+		BigDecimal result = BigDecimal.ZERO;
+		for(Invoice invoice : invoices) {
+			result = result.add(invoice.getAmountOutstanding());
+		}
+		return result;
+	}
 }