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();
+ }
+
}