mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2026-11-13 12:23:44 +01:00
feat(transactions): allow filtering the transaction picker search
TransactionSelect takes a filters dict sent as query params; the search endpoint applies allowlisted ones (currency, account).
This commit is contained in:
1 parent
eafaf0027c
commit
706f8fea2b
4 files changed
+31
-2
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import json
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from django.forms import SelectMultiple, widgets
|
||||
from django.urls import reverse
|
||||
@@ -141,6 +142,9 @@ class TransactionSelect(TomSelect):
|
||||
self.load_income = income
|
||||
self.load_expense = expense
|
||||
self.create = False
|
||||
# Extra search filters sent as query params, e.g. {"currency": 1};
|
||||
# keys must be in SEARCH_FILTERS of the transactions_search view
|
||||
self.filters = {}
|
||||
|
||||
def build_attrs(self, base_attrs, extra_attrs=None):
|
||||
attrs = super().build_attrs(base_attrs, extra_attrs)
|
||||
@@ -156,6 +160,8 @@ class TransactionSelect(TomSelect):
|
||||
attrs["data-load"] = reverse(
|
||||
"transactions_search", kwargs={"filter_type": "expenses"}
|
||||
)
|
||||
if self.filters:
|
||||
attrs["data-load"] += "?" + urlencode(self.filters)
|
||||
|
||||
return attrs
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ class TransactionSearchTests(TestCase):
|
||||
|
||||
def make(self, days, description="", amount="10", **kwargs):
|
||||
return Transaction.objects.create(
|
||||
account=self.account,
|
||||
account=kwargs.pop("account", self.account),
|
||||
type=Transaction.Type.EXPENSE,
|
||||
date=self.today + timedelta(days=days),
|
||||
reference_date=(self.today + timedelta(days=days)).replace(day=1),
|
||||
@@ -72,3 +72,13 @@ class TransactionSearchTests(TestCase):
|
||||
|
||||
self.assertEqual(self.search("wallet"), ["Groceries", "Other"])
|
||||
self.assertEqual(self.search("groceries nomatch"), [])
|
||||
|
||||
def test_filters_by_currency(self):
|
||||
usd = Currency.objects.create(code="USD", name="Dollar", decimal_places=2)
|
||||
other = Account.objects.create(name="Bank", currency=usd)
|
||||
self.make(0, "brl")
|
||||
self.make(0, "usd", account=other)
|
||||
response = self.client.get(
|
||||
reverse("transactions_search"), {"q": "", "currency": usd.id}
|
||||
)
|
||||
self.assertEqual([r["description"] for r in response.json()], ["usd"])
|
||||
@@ -985,6 +985,13 @@ def transactions_trash_can_list(request):
|
||||
)
|
||||
|
||||
|
||||
# Query params the transaction picker may filter by (TransactionSelect.filters)
|
||||
SEARCH_FILTERS = {
|
||||
"currency": "account__currency_id",
|
||||
"account": "account_id",
|
||||
}
|
||||
|
||||
|
||||
@login_required
|
||||
@require_http_methods(["GET"])
|
||||
def get_recent_transactions(request, filter_type=None):
|
||||
@@ -1002,6 +1009,11 @@ def get_recent_transactions(request, filter_type=None):
|
||||
elif filter_type == "income":
|
||||
queryset = queryset.filter(type=Transaction.Type.INCOME)
|
||||
|
||||
for param, lookup in SEARCH_FILTERS.items():
|
||||
value = request.GET.get(param, "")
|
||||
if value.isdigit():
|
||||
queryset = queryset.filter(**{lookup: value})
|
||||
|
||||
if search_term:
|
||||
queryset = search_transactions(queryset, search_term)
|
||||
|
||||
|
||||
@@ -136,7 +136,8 @@ window.TomSelect = function createDynamicTomSelect(element) {
|
||||
config.preload = 'focus';
|
||||
config.shouldLoad = () => true;
|
||||
config.load = function (query, callback) {
|
||||
let url = element.dataset.load + '?q=' + encodeURIComponent(query);
|
||||
const url = new URL(element.dataset.load, window.location.origin);
|
||||
url.searchParams.set('q', query);
|
||||
fetch(url)
|
||||
.then(response => response.json())
|
||||
.then(json => {
|
||||
|
||||
Reference in new issue
Block a user