|
20 | 20 | from simcore_postgres_database.models.users_details import ( |
21 | 21 | users_pre_registration_details, |
22 | 22 | ) |
| 23 | +from simcore_postgres_database.utils import as_postgres_sql_query_str |
23 | 24 | from simcore_postgres_database.utils_groups_extra_properties import ( |
24 | 25 | GroupExtraPropertiesNotFoundError, |
25 | 26 | GroupExtraPropertiesRepo, |
@@ -376,6 +377,132 @@ async def search_users_and_get_profile( |
376 | 377 | return [row async for row in result] |
377 | 378 |
|
378 | 379 |
|
| 380 | +async def list_users_for_admin( |
| 381 | + engine: AsyncEngine, |
| 382 | + connection: AsyncConnection | None = None, |
| 383 | + *, |
| 384 | + filter_approved: bool | None = None, |
| 385 | + limit: int = 50, |
| 386 | + offset: int = 0, |
| 387 | + include_deleted: bool = False, |
| 388 | +) -> tuple[list[dict[str, Any]], int]: |
| 389 | + """ |
| 390 | + Gets users data for admin with pagination support using SQLAlchemy expressions |
| 391 | +
|
| 392 | + Args: |
| 393 | + engine: The database engine |
| 394 | + connection: Optional existing connection to reuse |
| 395 | + filter_approved: If set, filters users by their approval status |
| 396 | + limit: Maximum number of users to return |
| 397 | + offset: Number of users to skip for pagination |
| 398 | + include_deleted: Whether to include users marked as deleted |
| 399 | +
|
| 400 | + Returns: |
| 401 | + Tuple of (list of user data, total count) |
| 402 | + """ |
| 403 | + joined_user_tables = users.outerjoin( |
| 404 | + users_pre_registration_details, |
| 405 | + users.c.id == users_pre_registration_details.c.user_id, |
| 406 | + ) |
| 407 | + |
| 408 | + where_conditions = [] |
| 409 | + if not include_deleted: |
| 410 | + where_conditions.append(users.c.status != UserStatus.DELETED) |
| 411 | + |
| 412 | + if filter_approved is not None: |
| 413 | + if filter_approved: |
| 414 | + where_conditions.append( |
| 415 | + users_pre_registration_details.c.account_request_status |
| 416 | + == AccountRequestStatus.APPROVED |
| 417 | + ) |
| 418 | + else: |
| 419 | + where_conditions.append( |
| 420 | + users_pre_registration_details.c.account_request_status |
| 421 | + != AccountRequestStatus.APPROVED |
| 422 | + ) |
| 423 | + |
| 424 | + where_clause = sa.and_(*where_conditions) if where_conditions else sa.true() |
| 425 | + |
| 426 | + # Count query |
| 427 | + count_query = ( |
| 428 | + sa.select(sa.func.count().label("total")) |
| 429 | + .select_from(joined_user_tables) |
| 430 | + .where(where_clause) |
| 431 | + ) |
| 432 | + |
| 433 | + # Create an alias for the users table to use in the subquery |
| 434 | + users_alias = sa.alias(users, name="creators") |
| 435 | + invited_by = ( |
| 436 | + sa.select( |
| 437 | + users_alias.c.name, |
| 438 | + ) |
| 439 | + .where( |
| 440 | + users_pre_registration_details.c.created_by.isnot(None) |
| 441 | + & (users_pre_registration_details.c.created_by == users_alias.c.id) |
| 442 | + ) |
| 443 | + .correlate(None) |
| 444 | + .scalar_subquery() |
| 445 | + .label("invited_by") |
| 446 | + ) |
| 447 | + |
| 448 | + # Main query to get user data |
| 449 | + main_query = ( |
| 450 | + sa.select( |
| 451 | + users_pre_registration_details.c.pre_email, # unique |
| 452 | + users_pre_registration_details.c.pre_first_name, |
| 453 | + users_pre_registration_details.c.pre_last_name, |
| 454 | + users_pre_registration_details.c.institution, |
| 455 | + users_pre_registration_details.c.pre_phone, |
| 456 | + users_pre_registration_details.c.address, |
| 457 | + users_pre_registration_details.c.city, |
| 458 | + users_pre_registration_details.c.state, |
| 459 | + users_pre_registration_details.c.postal_code, |
| 460 | + users_pre_registration_details.c.country, |
| 461 | + users_pre_registration_details.c.user_id, |
| 462 | + users_pre_registration_details.c.extras, |
| 463 | + users_pre_registration_details.c.created, |
| 464 | + users_pre_registration_details.c.account_request_status, |
| 465 | + users.c.id.label("user_id"), |
| 466 | + users.c.name.label("user_name"), |
| 467 | + users.c.first_name, |
| 468 | + users.c.last_name, |
| 469 | + users.c.email, |
| 470 | + users.c.phone, |
| 471 | + users.c.created_at, |
| 472 | + users.c.status, |
| 473 | + invited_by, |
| 474 | + ) |
| 475 | + .select_from(joined_user_tables) |
| 476 | + .where(where_clause) |
| 477 | + .order_by( |
| 478 | + users_pre_registration_details.c.created.desc(), # newest pre-registered first |
| 479 | + users_pre_registration_details.c.pre_email, |
| 480 | + ) |
| 481 | + .limit(limit) |
| 482 | + .offset(offset) |
| 483 | + ) |
| 484 | + |
| 485 | + print( |
| 486 | + "-" * 100, |
| 487 | + "\n", |
| 488 | + as_postgres_sql_query_str(main_query), |
| 489 | + "-" * 100, |
| 490 | + "\n", |
| 491 | + as_postgres_sql_query_str(count_query), |
| 492 | + ) # DEBUG |
| 493 | + |
| 494 | + async with pass_or_acquire_connection(engine, connection) as conn: |
| 495 | + # Get total count |
| 496 | + count_result = await conn.execute(count_query) |
| 497 | + total_count = count_result.scalar() |
| 498 | + |
| 499 | + # Get user records |
| 500 | + result = await conn.execute(main_query) |
| 501 | + records = result.mappings().all() |
| 502 | + |
| 503 | + return list(records), total_count |
| 504 | + |
| 505 | + |
379 | 506 | async def get_user_products( |
380 | 507 | engine: AsyncEngine, |
381 | 508 | connection: AsyncConnection | None = None, |
@@ -487,133 +614,6 @@ async def is_user_in_product_name( |
487 | 614 | return value is not None |
488 | 615 |
|
489 | 616 |
|
490 | | -async def list_users_for_admin( |
491 | | - engine: AsyncEngine, |
492 | | - connection: AsyncConnection | None = None, |
493 | | - *, |
494 | | - filter_approved: bool | None = None, |
495 | | - limit: int = 50, |
496 | | - offset: int = 0, |
497 | | - include_deleted: bool = False, |
498 | | -) -> tuple[list[dict[str, Any]], int]: |
499 | | - """ |
500 | | - Gets users data for admin with pagination support using SQLAlchemy expressions |
501 | | -
|
502 | | - Args: |
503 | | - engine: The database engine |
504 | | - connection: Optional existing connection to reuse |
505 | | - filter_approved: If set, filters users by their approval status |
506 | | - limit: Maximum number of users to return |
507 | | - offset: Number of users to skip for pagination |
508 | | - include_deleted: Whether to include users marked as deleted |
509 | | -
|
510 | | - Returns: |
511 | | - Tuple of (list of user data, total count) |
512 | | - """ |
513 | | - |
514 | | - # Define the join between users and users_pre_registration_details |
515 | | - joined_tables = users.outerjoin( |
516 | | - users_pre_registration_details, |
517 | | - users.c.id == users_pre_registration_details.c.user_id, |
518 | | - ) |
519 | | - |
520 | | - # Basic where clause - exclude deleted by default |
521 | | - where_conditions = [] |
522 | | - if not include_deleted: |
523 | | - where_conditions.append(users.c.status != UserStatus.DELETED) |
524 | | - |
525 | | - # Add filtering by approval status if requested |
526 | | - if filter_approved is not None: |
527 | | - if filter_approved: |
528 | | - where_conditions.append( |
529 | | - users_pre_registration_details.c.account_request_status |
530 | | - == AccountRequestStatus.APPROVED |
531 | | - ) |
532 | | - else: |
533 | | - where_conditions.append( |
534 | | - users_pre_registration_details.c.account_request_status |
535 | | - != AccountRequestStatus.APPROVED |
536 | | - ) |
537 | | - |
538 | | - # Combine all conditions with AND |
539 | | - where_clause = sa.and_(*where_conditions) if where_conditions else sa.true() |
540 | | - |
541 | | - # Count query to get total number of users |
542 | | - count_query = ( |
543 | | - sa.select(sa.func.count().label("total")) |
544 | | - .select_from(joined_tables) |
545 | | - .where(where_clause) |
546 | | - ) |
547 | | - |
548 | | - # Main query to get user data |
549 | | - invited_by = ( |
550 | | - sa.select( |
551 | | - users.c.name, |
552 | | - ) |
553 | | - .where(users_pre_registration_details.c.created_by == users.c.id) |
554 | | - .label("invited_by") |
555 | | - ) |
556 | | - |
557 | | - main_query = ( |
558 | | - sa.select( |
559 | | - users.c.id.label("user_id"), |
560 | | - users.c.name, |
561 | | - sa.case( |
562 | | - (users.c.email.is_(None), users_pre_registration_details.c.pre_email), |
563 | | - else_=users.c.email, |
564 | | - ).label("email"), |
565 | | - sa.case( |
566 | | - ( |
567 | | - users.c.first_name.is_(None), |
568 | | - users_pre_registration_details.c.pre_first_name, |
569 | | - ), |
570 | | - else_=users.c.first_name, |
571 | | - ).label("first_name"), |
572 | | - sa.case( |
573 | | - ( |
574 | | - users.c.last_name.is_(None), |
575 | | - users_pre_registration_details.c.pre_last_name, |
576 | | - ), |
577 | | - else_=users.c.last_name, |
578 | | - ).label("last_name"), |
579 | | - users.c.status, |
580 | | - users.c.created, |
581 | | - users_pre_registration_details.c.institution, |
582 | | - sa.case( |
583 | | - ( |
584 | | - users.c.phone.is_(None), |
585 | | - users_pre_registration_details.c.pre_phone, |
586 | | - ), |
587 | | - else_=users.c.phone, |
588 | | - ).label("phone"), |
589 | | - users_pre_registration_details.c.address, |
590 | | - users_pre_registration_details.c.city, |
591 | | - users_pre_registration_details.c.state, |
592 | | - users_pre_registration_details.c.postal_code, |
593 | | - users_pre_registration_details.c.country, |
594 | | - users_pre_registration_details.c.extras, |
595 | | - users_pre_registration_details.c.account_request_status, |
596 | | - invited_by, |
597 | | - ) |
598 | | - .select_from(joined_tables) |
599 | | - .where(where_clause) |
600 | | - .order_by(users.c.created.desc()) # newest first |
601 | | - .limit(limit) |
602 | | - .offset(offset) |
603 | | - ) |
604 | | - |
605 | | - async with pass_or_acquire_connection(engine, connection) as conn: |
606 | | - # Get total count |
607 | | - count_result = await conn.execute(count_query) |
608 | | - total_count = count_result.scalar() |
609 | | - |
610 | | - # Get user records |
611 | | - result = await conn.execute(main_query) |
612 | | - records = result.mappings().all() |
613 | | - |
614 | | - return list(records), total_count |
615 | | - |
616 | | - |
617 | 617 | # |
618 | 618 | # USER PROFILE |
619 | 619 | # |
|
0 commit comments