Allow filtering by category to also filter by child categories.
Build and Deploy API / build-and-deploy (push) Successful in 1m44s
Details
Build and Deploy API / build-and-deploy (push) Successful in 1m44s
Details
This commit is contained in:
parent
6415311925
commit
3368cfa96c
|
|
@ -223,9 +223,8 @@ class SqliteTransactionRepository : TransactionRepository {
|
|||
|
||||
// 1. Get the total count of transactions that match the search filters.
|
||||
qb.select("COUNT (DISTINCT txn.id)");
|
||||
applyFilters(qb, request);
|
||||
applyFilters(qb, request, new SqliteTransactionCategoryRepository(db));
|
||||
string countQuery = qb.build();
|
||||
// writeln(countQuery);
|
||||
Statement countStmt = db.prepare(countQuery);
|
||||
qb.applyArgBindings(countStmt);
|
||||
auto countResult = countStmt.execute();
|
||||
|
|
|
|||
|
|
@ -14,17 +14,23 @@ import std.uri;
|
|||
import std.uni;
|
||||
|
||||
import util.sqlite;
|
||||
import transaction.data;
|
||||
|
||||
/**
|
||||
* Applies a set of filters to a query builder for searching over transactions.
|
||||
* Params:
|
||||
* qb = The query builder to add WHERE clauses and argument bindings to.
|
||||
* request = The request to get filter options from.
|
||||
* categoryRepo = Repository for fetching category data, which might be
|
||||
* needed if the user is filtering by a parent category.
|
||||
*/
|
||||
void applyFilters(ref QueryBuilder qb, in ServerHttpRequest request) {
|
||||
void applyFilters(
|
||||
ref QueryBuilder qb,
|
||||
in ServerHttpRequest request,
|
||||
TransactionCategoryRepository categoryRepo
|
||||
) {
|
||||
applyPropertyInFilter!string(qb, request, "tags.tag", "tag");
|
||||
applyPropertyInFilter!ulong(qb, request, "vendor.id", "vendor");
|
||||
applyPropertyInFilter!ulong(qb, request, "category.id", "category");
|
||||
applyPropertyInFilter!string(qb, request, "txn.currency", "currency");
|
||||
applyPropertyInFilter!ulong(qb, request, "account_credit.id", "credited-account");
|
||||
applyPropertyInFilter!ulong(qb, request, "account_debit.id", "debited-account");
|
||||
|
|
@ -45,6 +51,25 @@ void applyFilters(ref QueryBuilder qb, in ServerHttpRequest request) {
|
|||
});
|
||||
}
|
||||
|
||||
// Separate filter that handles the hierarchical category relationship, so
|
||||
// if a parent category is filtered, all children are also included.
|
||||
if (request.hasParam("category")) {
|
||||
ulong[] categoryIds = request.getParamValues!ulong("category");
|
||||
auto app = appender!(ulong[]);
|
||||
foreach (id; categoryIds) {
|
||||
app ~= getAllPossibleCategoryIds(id, categoryRepo);
|
||||
}
|
||||
ulong[] allPossibleIds = app[];
|
||||
if (allPossibleIds.length > 0) {
|
||||
qb.where("(" ~ "txn.category_id = ?".repeat(allPossibleIds.length).join(" OR ") ~ ")");
|
||||
qb.withArgBinding((ref stmt, ref idx) {
|
||||
foreach (value; allPossibleIds) {
|
||||
stmt.bind(idx++, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (request.hasParam("min-amount")) {
|
||||
ulong[] values = request.getParamValues!ulong("min-amount");
|
||||
if (values.length > 0) {
|
||||
|
|
@ -140,3 +165,13 @@ private T[] getParamValues(T = string)(in ServerHttpRequest request, string key)
|
|||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
private ulong[] getAllPossibleCategoryIds(ulong parentId, TransactionCategoryRepository categoryRepo) {
|
||||
auto app = appender!(ulong[]);
|
||||
app ~= parentId;
|
||||
foreach (child; categoryRepo.findAllByParentId(Optional!ulong.of(parentId))) {
|
||||
app ~= child.id;
|
||||
app ~= getAllPossibleCategoryIds(child.id, categoryRepo);
|
||||
}
|
||||
return app[];
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue