feat: support multi-value status and priority filters in list_notes
This commit is contained in:
@@ -70,11 +70,14 @@ async def list_notes_route():
|
||||
elif type_param == "note":
|
||||
is_task = False
|
||||
|
||||
status = request.args.getlist("status") or None
|
||||
priority = request.args.getlist("priority") or None
|
||||
|
||||
notes, total = await list_notes(
|
||||
uid, q=q, tags=tag or None, is_task=is_task, sort=sort, order=order,
|
||||
limit=limit, offset=offset,
|
||||
project_id=project_id, milestone_id=milestone_id, parent_id=parent_id,
|
||||
no_project=no_project,
|
||||
no_project=no_project, status=status, priority=priority,
|
||||
)
|
||||
return jsonify({"notes": [n.to_dict() for n in notes], "total": total})
|
||||
|
||||
|
||||
@@ -106,8 +106,8 @@ async def list_notes(
|
||||
q: str | None = None,
|
||||
tags: list[str] | None = None,
|
||||
is_task: bool | None = None,
|
||||
status: str | None = None,
|
||||
priority: str | None = None,
|
||||
status: str | list[str] | None = None,
|
||||
priority: str | list[str] | None = None,
|
||||
due_before: date | None = None,
|
||||
due_after: date | None = None,
|
||||
project_id: int | None = None,
|
||||
@@ -153,12 +153,14 @@ async def list_notes(
|
||||
count_query = count_query.where(tag_filter)
|
||||
|
||||
if status:
|
||||
query = query.where(Note.status == status)
|
||||
count_query = count_query.where(Note.status == status)
|
||||
statuses = [status] if isinstance(status, str) else status
|
||||
query = query.where(Note.status.in_(statuses))
|
||||
count_query = count_query.where(Note.status.in_(statuses))
|
||||
|
||||
if priority:
|
||||
query = query.where(Note.priority == priority)
|
||||
count_query = count_query.where(Note.priority == priority)
|
||||
priorities = [priority] if isinstance(priority, str) else priority
|
||||
query = query.where(Note.priority.in_(priorities))
|
||||
count_query = count_query.where(Note.priority.in_(priorities))
|
||||
|
||||
if due_before is not None:
|
||||
query = query.where(Note.due_date < due_before)
|
||||
|
||||
@@ -271,15 +271,14 @@ async def test_spawn_recurring_tasks_creates_child():
|
||||
# ── Multi-status filtering ────────────────────────────────────────────────────
|
||||
|
||||
async def test_list_notes_multi_status_builds_in_clause():
|
||||
"""list_notes with a list of statuses uses IN rather than equality."""
|
||||
"""list_notes with a list of statuses executes without error."""
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
mock_session = AsyncMock()
|
||||
mock_result = MagicMock()
|
||||
mock_result.scalars.return_value.all.return_value = []
|
||||
mock_count_result = MagicMock()
|
||||
mock_count_result.scalar.return_value = 0
|
||||
mock_session.execute = AsyncMock(side_effect=[mock_result, mock_count_result])
|
||||
mock_session.execute = AsyncMock(return_value=mock_result)
|
||||
mock_session.scalar = AsyncMock(return_value=0)
|
||||
mock_session.__aenter__ = AsyncMock(return_value=mock_session)
|
||||
mock_session.__aexit__ = AsyncMock(return_value=False)
|
||||
|
||||
@@ -288,4 +287,6 @@ async def test_list_notes_multi_status_builds_in_clause():
|
||||
notes, total = await list_notes(1, status=["todo", "in_progress"], is_task=True)
|
||||
|
||||
assert total == 0
|
||||
assert mock_session.execute.call_count == 2
|
||||
assert notes == []
|
||||
mock_session.scalar.assert_called_once()
|
||||
mock_session.execute.assert_called_once()
|
||||
|
||||
Reference in New Issue
Block a user