killbill-aplcache

Details

diff --git a/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java b/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java
index c81c6e8..d49f139 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/api/user/DefaultInvoiceUserApi.java
@@ -20,6 +20,7 @@ package org.killbill.billing.invoice.api.user;
 
 import java.io.IOException;
 import java.math.BigDecimal;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
@@ -481,4 +482,27 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
         }
         return invoice;
     }
+
+    @Override
+    public List<Invoice> getInvoicesByParentAccount(final UUID parentAccountId, final LocalDate startDate, LocalDate endDate,
+                                                    final TenantContext context) throws InvoiceApiException {
+        // date validations
+        if (startDate != null && endDate == null) {
+            endDate = LocalDate.now();
+        }
+
+        if (startDate != null) {
+            if (startDate.isAfter(LocalDate.now()) || startDate.isAfter(endDate)) {
+                throw new InvoiceApiException(ErrorCode.INVOICE_INVALID_DATE_RANGE, startDate, endDate);
+            }
+        }
+
+        final InternalTenantContext tenantContext = internalCallContextFactory.createInternalTenantContext(context);
+        final List<InvoiceModelDao> invoicesByParentAccount = dao.getInvoicesByParentAccount(parentAccountId, startDate, endDate, tenantContext);
+        final List<Invoice> invoices = new ArrayList<Invoice>();
+        for (InvoiceModelDao invoice : invoicesByParentAccount) {
+            invoices.add(new DefaultInvoice(invoice));
+        }
+        return invoices;
+    }
 }
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
index 9f86bc9..abf068f 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
@@ -853,4 +853,27 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
             throw new InvoiceApiException(ErrorCode.INVOICE_ITEM_ADJUSTMENT_ITEM_INVALID, invoiceItemToBeAdjusted.getId());
         }
     }
+
+    @Override
+    public List<InvoiceModelDao> getInvoicesByParentAccount(final UUID parentAccountId, final LocalDate startDate,
+                                                            final LocalDate endDate, final InternalTenantContext context) {
+        return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<InvoiceModelDao>>() {
+            @Override
+            public List<InvoiceModelDao> inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
+                final InvoiceSqlDao invoiceDao = entitySqlDaoWrapperFactory.become(InvoiceSqlDao.class);
+
+                List<InvoiceModelDao> invoices = null;
+                if (startDate != null && endDate != null) {
+                    invoices = invoiceDao.getInvoicesByParentAccountDateRange(parentAccountId, startDate.toDate(),
+                                                                              endDate.toDate(), context);
+                } else {
+                    invoices = invoiceDao.getInvoicesByParentAccount(parentAccountId, context);
+                }
+
+                invoiceDaoHelper.populateChildren(invoices, entitySqlDaoWrapperFactory, context);
+
+                return invoices;
+            }
+        });
+    }
 }
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java
index effce52..4c0535c 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceDao.java
@@ -138,4 +138,6 @@ public interface InvoiceDao extends EntityDao<InvoiceModelDao, Invoice, InvoiceA
      * @param context   the callcontext
      */
     public void consumeExstingCBAOnAccountWithUnpaidInvoices(final UUID accountId, final InternalCallContext context);
+
+    List<InvoiceModelDao> getInvoicesByParentAccount(UUID parentAccountId, LocalDate startDate, LocalDate endDate, InternalTenantContext context);
 }
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceSqlDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceSqlDao.java
index 40551e9..380e5cc 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceSqlDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/InvoiceSqlDao.java
@@ -16,6 +16,7 @@
 
 package org.killbill.billing.invoice.dao;
 
+import java.util.Date;
 import java.util.List;
 import java.util.UUID;
 
@@ -38,5 +39,15 @@ public interface InvoiceSqlDao extends EntitySqlDao<InvoiceModelDao, Invoice> {
     @SqlQuery
     UUID getInvoiceIdByPaymentId(@Bind("paymentId") final String paymentId,
                                  @BindBean final InternalTenantContext context);
+
+    @SqlQuery
+    List<InvoiceModelDao> getInvoicesByParentAccount(@Bind("parentAccountId") final UUID parentAccountId,
+                                                     @BindBean final InternalTenantContext context);
+
+    @SqlQuery
+    List<InvoiceModelDao> getInvoicesByParentAccountDateRange(@Bind("parentAccountId") final UUID parentAccountId,
+                                                              @Bind("startDate") final Date startDate,
+                                                              @Bind("endDate") final Date endDate,
+                                                              @BindBean final InternalTenantContext context);
 }
 
diff --git a/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceSqlDao.sql.stg b/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceSqlDao.sql.stg
index 8daa8b1..e8c0d42 100644
--- a/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceSqlDao.sql.stg
+++ b/invoice/src/main/resources/org/killbill/billing/invoice/dao/InvoiceSqlDao.sql.stg
@@ -50,3 +50,25 @@ getInvoiceIdByPaymentId() ::= <<
    <AND_CHECK_TENANT("i.")>
    <AND_CHECK_TENANT("ip.")>
 >>
+
+getInvoicesByParentAccount() ::= <<
+  SELECT <allTableFields("i.")>
+  FROM <tableName()> i
+  JOIN accounts ac ON i.account_id = ac.id
+  WHERE ac.parent_account_id = :parentAccountId
+  <AND_CHECK_TENANT("i.")>
+  <AND_CHECK_TENANT("ac.")>
+  ;
+>>
+
+getInvoicesByParentAccountDateRange() ::= <<
+  SELECT <allTableFields("i.")>
+  FROM <tableName()> i
+  JOIN accounts ac ON i.account_id = ac.id
+  WHERE ac.parent_account_id = :parentAccountId
+  and invoice_date >= :startDate
+  and invoice_date \< :endDate
+  <AND_CHECK_TENANT("i.")>
+  <AND_CHECK_TENANT("ac.")>
+  ;
+>>
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java b/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java
index 6c1c27e..732e65e 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java
@@ -362,4 +362,18 @@ public class MockInvoiceDao extends MockEntityDaoBase<InvoiceModelDao, Invoice, 
     public void deleteCBA(final UUID accountId, final UUID invoiceId, final UUID invoiceItemId, final InternalCallContext context) throws InvoiceApiException {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public List<InvoiceModelDao> getInvoicesByParentAccount(final UUID parentAccountId, final LocalDate startDate, final LocalDate endDate, final InternalTenantContext context) {
+        final List<InvoiceModelDao> result = new ArrayList<InvoiceModelDao>();
+
+        synchronized (monitor) {
+            for (final InvoiceModelDao invoice : invoices.values()) {
+                // TODO filter by parent account id
+                // if (invoice.account.parentAccountId.equals(parentAccountId)) { ... }
+                result.add(invoice);
+            }
+        }
+        return result;
+    }
 }
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java
index d0cbe08..69e303e 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java
@@ -49,6 +49,7 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.core.UriInfo;
 
+import org.joda.time.LocalDate;
 import org.killbill.billing.ErrorCode;
 import org.killbill.billing.ObjectType;
 import org.killbill.billing.account.api.Account;
@@ -1236,4 +1237,37 @@ public class AccountResource extends JaxRsResourceBase {
         return Response.status(Status.OK).entity(accountJson).build();
     }
 
+    @TimedResource
+    @GET
+    @Path("/{parentAccountId:" + UUID_PATTERN + "}/" + CHILDS + "/" + INVOICES)
+    @Produces(APPLICATION_JSON)
+    @ApiOperation(value = "Retrieve child account invoices", response = InvoiceJson.class)
+    @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid account id or date range supplied"),
+                           @ApiResponse(code = 404, message = "Account not found")})
+    public Response getChildInvoices(@PathParam("parentAccountId") final String parentAccountIdString,
+                                     @QueryParam(QUERY_START_DATE) final String startDateString,
+                                     @QueryParam(QUERY_END_DATE) final String endDateString,
+                                     @QueryParam(QUERY_INVOICE_WITH_ITEMS) @DefaultValue("false") final boolean withItems,
+                                     @QueryParam(QUERY_UNPAID_INVOICES_ONLY) @DefaultValue("false") final boolean unpaidInvoicesOnly,
+                                     @QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
+                                     @javax.ws.rs.core.Context final HttpServletRequest request) throws AccountApiException, InvoiceApiException {
+        final TenantContext tenantContext = context.createContext(request);
+
+        // Verify the account exists
+        final UUID parentAccountId = UUID.fromString(parentAccountIdString);
+        accountUserApi.getAccountById(parentAccountId, tenantContext);
+
+        final LocalDate startDate = (startDateString != null) ? LOCAL_DATE_FORMATTER.parseLocalDate(startDateString) : null ;
+        final LocalDate endDate = (endDateString != null) ? LOCAL_DATE_FORMATTER.parseLocalDate(endDateString) : null ;
+        final List<Invoice> invoices = invoiceApi.getInvoicesByParentAccount(parentAccountId, startDate, endDate, tenantContext);
+        final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(parentAccountId, auditMode.getLevel(), tenantContext);
+
+        final List<InvoiceJson> result = new LinkedList<InvoiceJson>();
+        for (final Invoice invoice : invoices) {
+            result.add(new InvoiceJson(invoice, withItems, accountAuditLogs));
+        }
+
+        return Response.status(Status.OK).entity(result).build();
+    }
+
 }