Skip to content

Commit 377d265

Browse files
committed
Refactor list_merged_pre_and_registered_users to use MergedUserData type and update ordering logic with OrderDirection
1 parent 8bd3b63 commit 377d265

File tree

1 file changed

+52
-13
lines changed

1 file changed

+52
-13
lines changed

services/web/server/src/simcore_service_webserver/users/_accounts_repository.py

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import logging
2-
from typing import Annotated, Any, Literal, TypeAlias, cast
2+
from datetime import datetime
3+
from typing import Annotated, Any, Literal, TypeAlias, TypedDict, cast
34

45
import sqlalchemy as sa
56
from annotated_types import doc
67
from common_library.exclude import Unset, is_unset
78
from common_library.users_enums import AccountRequestStatus
9+
from models_library.list_operations import OrderDirection
810
from models_library.products import ProductName
911
from models_library.users import (
1012
UserID,
@@ -433,7 +435,43 @@ async def search_merged_pre_and_registered_users(
433435

434436

435437
OrderKeys: TypeAlias = Literal["email", "current_status_created"]
436-
OrderDirs: TypeAlias = Literal["asc", "desc"]
438+
439+
440+
class MergedUserData(TypedDict, total=False):
441+
"""Type definition for merged user data returned by list_merged_pre_and_registered_users."""
442+
443+
# Pre-registration specific fields
444+
id: int | None # pre-registration ID
445+
pre_reg_user_id: int | None # user_id from pre-registration table
446+
institution: str | None
447+
address: str | None
448+
city: str | None
449+
state: str | None
450+
postal_code: str | None
451+
country: str | None
452+
extras: dict[str, Any] | None
453+
account_request_status: AccountRequestStatus | None
454+
account_request_reviewed_by: int | None
455+
account_request_reviewed_at: datetime | None
456+
created_by: int | None
457+
account_request_reviewed_by_username: str | None
458+
459+
# Common fields (from either pre-registration or users table)
460+
email: str
461+
first_name: str | None
462+
last_name: str | None
463+
phone: str | None
464+
created: datetime | None
465+
current_status_created: datetime
466+
467+
# User table specific fields
468+
user_id: int | None # actual user ID from users table
469+
user_name: str | None
470+
user_primary_group_id: int | None
471+
status: str | None # UserStatus
472+
473+
# Computed fields
474+
is_pre_registered: bool
437475

438476

439477
@validate_call(config={"arbitrary_types_allowed": True})
@@ -452,12 +490,13 @@ async def list_merged_pre_and_registered_users(
452490
pagination_limit: int = 50,
453491
pagination_offset: int = 0,
454492
order_by: Annotated[
455-
list[tuple[OrderKeys, OrderDirs]] | None,
493+
list[tuple[OrderKeys, OrderDirection]] | None,
456494
doc(
457-
'Valid fields: "email", "current_status_created". Default: [("email", "asc"), ("is_pre_registered", "desc"), ("current_status_created", "desc")]'
495+
'Valid fields: "email", "current_status_created". '
496+
'Default: [("email", OrderDirection.ASC), ("is_pre_registered", OrderDirection.DESC), ("current_status_created", OrderDirection.DESC)]'
458497
),
459498
] = None,
460-
) -> tuple[list[dict[str, Any]], int]:
499+
) -> tuple[list[MergedUserData], int]:
461500
"""Retrieves and merges users from both users and pre-registration tables.
462501
463502
This returns:
@@ -633,34 +672,34 @@ async def list_merged_pre_and_registered_users(
633672
result = await conn.execute(final_query)
634673
records = result.mappings().all()
635674

636-
return cast(list[dict[str, Any]], records), total_count
675+
return cast(list[MergedUserData], records), total_count
637676

638677

639678
def _build_ordering_clauses_for_filtered_query(
640679
query: sa.sql.Select,
641-
order_by: list[tuple[OrderKeys, OrderDirs]] | None = None,
680+
order_by: list[tuple[OrderKeys, OrderDirection]] | None = None,
642681
) -> list[sa.sql.ColumnElement]:
643682
"""Build ORDER BY clauses for filtered query (no DISTINCT ON constraints)."""
644-
_ordering_criteria: list[tuple[str, OrderDirs]] = []
683+
_ordering_criteria: list[tuple[str, OrderDirection]] = []
645684

646685
if order_by is None:
647686
# Default ordering
648687
_ordering_criteria = [
649-
("email", "asc"),
650-
("is_pre_registered", "desc"),
651-
("current_status_created", "desc"),
688+
("email", OrderDirection.ASC),
689+
("is_pre_registered", OrderDirection.DESC),
690+
("current_status_created", OrderDirection.DESC),
652691
]
653692
else:
654693
_ordering_criteria = list(order_by)
655694
# Always append is_pre_registered prioritization for custom ordering
656695
if not any(field == "is_pre_registered" for field, _ in order_by):
657-
_ordering_criteria.append(("is_pre_registered", "desc"))
696+
_ordering_criteria.append(("is_pre_registered", OrderDirection.DESC))
658697

659698
order_by_clauses = []
660699
for field, direction in _ordering_criteria:
661700
# Get column from the query's selected columns
662701
column = next(col for col in query.selected_columns if col.name == field)
663-
if direction == "asc":
702+
if direction == OrderDirection.ASC:
664703
order_by_clauses.append(column.asc())
665704
else:
666705
order_by_clauses.append(column.desc())

0 commit comments

Comments
 (0)