feat(staff): action buttons → filtered customer/group list

Adds groups.user_id filter; viewCustomers/viewGroups push owner_account_id query; CustomerList/GroupList read it.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
浅念
2026-08-05 19:06:27 +08:00
parent 02a709ba93
commit dfdd0595d2
6 changed files with 109 additions and 21 deletions
+13 -3
View File
@@ -1,8 +1,9 @@
"""GET /api/groups, /api/groups/{room_id}/members — chat-group browse endpoints.
* ``GET /api/groups`` -> ``Page[GroupOut]`` filtered by ``channel`` /
``owner_account_id``, ordered by ``last_chat_time desc`` (nulls last) so
recently-active groups surface first.
``owner_account_id`` / ``user_id`` (the latter mapping to the
``owner_user_id`` column), ordered by ``last_chat_time desc`` (nulls last)
so recently-active groups surface first.
* ``GET /api/groups/{room_id}/members`` -> ``list[GroupMemberOut]`` — the
members of a single group (small set, no pagination needed).
"""
@@ -33,13 +34,22 @@ async def list_groups(
page_size: PageSizeParam = 20,
channel: Annotated[str | None, Query()] = None,
owner_account_id: Annotated[str | None, Query()] = None,
user_id: Annotated[str | None, Query()] = None,
) -> Page[GroupOut]:
"""List chat groups with optional ``channel`` / ``owner_account_id`` filters."""
"""List chat groups with optional ``channel`` / ``owner_account_id`` /
``user_id`` filters.
``user_id`` maps to the ``ChatGroup.owner_user_id`` column (the staff
``userId`` who owns the chatroom account), mirroring the ``user_id``
filter on ``GET /api/customers``.
"""
conditions = []
if channel is not None:
conditions.append(ChatGroup.channel == channel)
if owner_account_id is not None:
conditions.append(ChatGroup.owner_account_id == owner_account_id)
if user_id is not None:
conditions.append(ChatGroup.owner_user_id == user_id)
total_stmt = sa.select(sa.func.count()).select_from(ChatGroup)
if conditions: