Skip to content

Commit 6f8d5a5

Browse files
committed
list_user_pre_registartion
1 parent d5a45ea commit 6f8d5a5

File tree

2 files changed

+393
-24
lines changed

2 files changed

+393
-24
lines changed

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

Lines changed: 174 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import sqlalchemy as sa
66
from aiohttp import web
7+
from common_library.exclude import UnSet, is_unset
78
from common_library.users_enums import AccountRequestStatus, UserRole
89
from models_library.groups import GroupID
910
from models_library.products import ProductName
@@ -534,30 +535,6 @@ async def get_user_products(
534535
return [row async for row in result]
535536

536537

537-
async def create_user_pre_registration(
538-
engine: AsyncEngine,
539-
connection: AsyncConnection | None = None,
540-
*,
541-
email: str,
542-
created_by: UserID,
543-
product_name: ProductName,
544-
**other_values,
545-
) -> int:
546-
async with transaction_context(engine, connection) as conn:
547-
result = await conn.execute(
548-
sa.insert(users_pre_registration_details)
549-
.values(
550-
created_by=created_by,
551-
pre_email=email,
552-
product_name=product_name,
553-
**other_values,
554-
)
555-
.returning(users_pre_registration_details.c.id)
556-
)
557-
pre_registration_id: int = result.scalar_one()
558-
return pre_registration_id
559-
560-
561538
async def get_user_billing_details(
562539
engine: AsyncEngine, connection: AsyncConnection | None = None, *, user_id: UserID
563540
) -> UserBillingDetails:
@@ -694,3 +671,176 @@ async def update_user_profile(
694671
) from err
695672

696673
raise # not due to name duplication
674+
675+
676+
async def create_user_pre_registration(
677+
engine: AsyncEngine,
678+
connection: AsyncConnection | None = None,
679+
*,
680+
email: str,
681+
created_by: UserID,
682+
product_name: ProductName,
683+
**other_values,
684+
) -> int:
685+
async with transaction_context(engine, connection) as conn:
686+
result = await conn.execute(
687+
sa.insert(users_pre_registration_details)
688+
.values(
689+
created_by=created_by,
690+
pre_email=email,
691+
product_name=product_name,
692+
**other_values,
693+
)
694+
.returning(users_pre_registration_details.c.id)
695+
)
696+
pre_registration_id: int = result.scalar_one()
697+
return pre_registration_id
698+
699+
700+
async def list_user_pre_registrations(
701+
engine: AsyncEngine,
702+
connection: AsyncConnection | None = None,
703+
*,
704+
filter_by_pre_email: str | None = None,
705+
filter_by_product_name: ProductName | UnSet = UnSet.VALUE,
706+
filter_by_account_request_status: AccountRequestStatus | None = None,
707+
pagination_limit: int = 50,
708+
pagination_offset: int = 0,
709+
) -> tuple[list[dict[str, Any]], int]:
710+
"""Lists user pre-registrations with optional filters.
711+
712+
Args:
713+
engine: Database engine
714+
connection: Optional existing connection
715+
filter_by_pre_email: Filter by email pattern (SQL LIKE pattern)
716+
filter_by_product_name: Filter by product name
717+
filter_by_account_request_status: Filter by account request status
718+
pagination_limit: Maximum number of results to return
719+
pagination_offset: Number of results to skip (for pagination)
720+
721+
Returns:
722+
Tuple of (list of pre-registration records, total count)
723+
"""
724+
# Base query conditions
725+
where_conditions = []
726+
727+
# Apply filters if provided
728+
if filter_by_pre_email is not None:
729+
where_conditions.append(
730+
users_pre_registration_details.c.pre_email.ilike(f"%{filter_by_pre_email}%")
731+
)
732+
733+
if not is_unset(filter_by_product_name):
734+
where_conditions.append(
735+
users_pre_registration_details.c.product_name == filter_by_product_name
736+
)
737+
738+
if filter_by_account_request_status is not None:
739+
where_conditions.append(
740+
users_pre_registration_details.c.account_request_status
741+
== filter_by_account_request_status
742+
)
743+
744+
# Combine conditions
745+
where_clause = sa.and_(*where_conditions) if where_conditions else sa.true()
746+
747+
# Create an alias for the users table for the created_by join
748+
creator_users_alias = sa.alias(users, name="creator")
749+
reviewer_users_alias = sa.alias(users, name="reviewer")
750+
751+
# Count query for pagination
752+
count_query = (
753+
sa.select(sa.func.count().label("total"))
754+
.select_from(users_pre_registration_details)
755+
.where(where_clause)
756+
)
757+
758+
# Main query to get pre-registration data
759+
main_query = (
760+
sa.select(
761+
users_pre_registration_details.c.id,
762+
users_pre_registration_details.c.user_id,
763+
users_pre_registration_details.c.pre_email,
764+
users_pre_registration_details.c.pre_first_name,
765+
users_pre_registration_details.c.pre_last_name,
766+
users_pre_registration_details.c.pre_phone,
767+
users_pre_registration_details.c.institution,
768+
users_pre_registration_details.c.address,
769+
users_pre_registration_details.c.city,
770+
users_pre_registration_details.c.state,
771+
users_pre_registration_details.c.postal_code,
772+
users_pre_registration_details.c.country,
773+
users_pre_registration_details.c.product_name,
774+
users_pre_registration_details.c.account_request_status,
775+
users_pre_registration_details.c.extras,
776+
users_pre_registration_details.c.created,
777+
users_pre_registration_details.c.modified,
778+
users_pre_registration_details.c.created_by,
779+
creator_users_alias.c.name.label("created_by_name"),
780+
users_pre_registration_details.c.account_request_reviewed_by,
781+
reviewer_users_alias.c.name.label("reviewed_by_name"),
782+
users_pre_registration_details.c.account_request_reviewed_at,
783+
)
784+
.select_from(
785+
users_pre_registration_details.outerjoin(
786+
creator_users_alias,
787+
users_pre_registration_details.c.created_by == creator_users_alias.c.id,
788+
).outerjoin(
789+
reviewer_users_alias,
790+
users_pre_registration_details.c.account_request_reviewed_by
791+
== reviewer_users_alias.c.id,
792+
)
793+
)
794+
.where(where_clause)
795+
.order_by(
796+
users_pre_registration_details.c.created.desc(),
797+
users_pre_registration_details.c.pre_email,
798+
)
799+
.limit(pagination_limit)
800+
.offset(pagination_offset)
801+
)
802+
803+
async with pass_or_acquire_connection(engine, connection) as conn:
804+
# Get total count
805+
count_result = await conn.execute(count_query)
806+
total_count = count_result.scalar()
807+
808+
# Get pre-registration records
809+
result = await conn.execute(main_query)
810+
records = result.mappings().all()
811+
812+
return list(records), total_count
813+
814+
815+
async def review_user_pre_registration(
816+
engine: AsyncEngine,
817+
connection: AsyncConnection | None = None,
818+
*,
819+
pre_registration_id: int,
820+
reviewed_by: UserID,
821+
new_status: AccountRequestStatus,
822+
) -> None:
823+
"""Updates the account request status of a pre-registered user.
824+
825+
Args:
826+
engine: The database engine
827+
connection: Optional existing connection
828+
pre_registration_id: ID of the pre-registration record
829+
reviewed_by: ID of the user who reviewed the request
830+
new_status: New status (APPROVED or REJECTED)
831+
"""
832+
if new_status not in (AccountRequestStatus.APPROVED, AccountRequestStatus.REJECTED):
833+
raise ValueError(
834+
f"Invalid status for review: {new_status}. Must be APPROVED or REJECTED."
835+
)
836+
837+
async with transaction_context(engine, connection) as conn:
838+
await conn.execute(
839+
users_pre_registration_details.update()
840+
.values(
841+
account_request_status=new_status,
842+
account_request_reviewed_by=reviewed_by,
843+
account_request_reviewed_at=sa.func.now(),
844+
)
845+
.where(users_pre_registration_details.c.id == pre_registration_id)
846+
)

0 commit comments

Comments
 (0)