Use Case 022: Advanced Cross-Entity Search and Saved Searches
Overview
| Property | Value |
|---|---|
| Use Case ID | UC-022 |
| Use Case Name | Advanced Cross-Entity Search and Saved Searches |
| Module | Administration — Advanced Search |
| Priority | Medium |
| Status | Implemented |
| Version | 1.0 |
| Last Updated | April 3, 2026 |
Description
This use case describes how administrators use the Advanced Search module to perform multi-criteria searches across trial users and admin users, save frequently-used search configurations for quick reuse, and export search results to CSV. The module provides a rich search interface with filters for name, email, company, status, date ranges, and more — all combined with AND logic. Users can save and load named search criteria, enabling quick access to common queries like "expired trials needing follow-up" or "inactive admin accounts."
Actors
| Actor | Description | Role |
|---|---|---|
| Administrator | Authenticated admin user performing searches | Primary |
| System | Application Manager search engine | Supporting |
Preconditions
- Application Manager is running and accessible
- User authenticated with valid session
- Trial users and/or admin users exist in the system
- SavedSearches table exists in Identity database
Postconditions
Success Postconditions
- Search results displayed with pagination and sorting
- Saved search persisted with name, description, and criteria JSON
- CSV export downloaded with timestamped filename
- Search criteria available for future reuse
Failure Postconditions
- Invalid search criteria returns validation error
- Failed search logged with error details
- Duplicate saved search name returns descriptive error
- Export failure returns 500 with error message
Triggers
- Administrator navigates to Advanced Search module
- Administrator needs to find users matching specific criteria
- Administrator wants to export user data for reporting
- Administrator saves a complex search for recurring use
- Administrator loads a previously saved search
Basic Flow (Happy Path — Trial User Search)
sequenceDiagram
actor Admin as Administrator
participant UI as Search Interface
participant Ctrl as AdvancedSearchController
participant Med as MediatR
participant Handler as SearchTrialUsersQueryHandler
participant DB as Identity DB
Note over Admin,DB: Advanced Trial User Search Flow
Admin->>UI: Navigate to /advanced-search/trial-users
UI->>Admin: Display search form with criteria fields
Admin->>UI: Enter criteria (name, email, company, status, dates)
Admin->>UI: Click "Search"
UI->>Ctrl: POST /advanced-search/trial-users/search (JSON body)
Ctrl->>Med: Send(SearchTrialUsersQuery)
Med->>Handler: Handle(query)
Handler->>DB: Build LINQ query with EF.Functions.Like filters
Handler->>DB: Count total matches
Handler->>DB: Apply sorting and pagination
DB->>Handler: Paginated TrialUser results
Handler->>Med: TrialUserSearchResultDto
Med->>Ctrl: Result with users, totalCount, pagination
Ctrl->>UI: JSON { success: true, data: results }
UI->>Admin: Display results table with pagination controls
Admin->>UI: Click "Export to CSV"
UI->>Ctrl: POST /advanced-search/trial-users/export
Ctrl->>Med: Send(SearchTrialUsersQuery) with PageSize=10000
Med->>Handler: Handle(query)
Handler->>DB: Execute full result query
DB->>Handler: All matching users (up to 10,000)
Handler->>Ctrl: SearchResultDto
Ctrl->>Ctrl: CsvExportService.ExportSearchResultsToCsvAsync()
Ctrl->>UI: File download (trial_users_search_YYYYMMDD_HHMMSS.csv)
UI->>Admin: CSV file downloaded
Alternative Flows
Alt-1: Save Search Criteria
Trigger: Administrator wants to save current search for reuse
Flow:
- Administrator performs a search with specific criteria
- Administrator clicks "Save Search" button
- UI displays save dialog with Name (required) and Description (optional) fields
- Administrator enters name (e.g., "Expired Trials — Q1 2026") and description
- UI sends POST
/advanced-search/savewith name, description, searchType, criteria - Controller extracts UserId from authentication claims
- Handler validates name uniqueness for user
- Handler serializes criteria to JSON and creates SavedSearch entity
- Handler persists to database with CreatedAt timestamp and UseCount=0
- UI shows success: "Search 'Expired Trials — Q1 2026' saved successfully"
Alt-2: Load Saved Search
Trigger: Administrator wants to apply a previously saved search
Flow:
- Administrator clicks "Load Saved Search" button
- UI sends GET
/advanced-search/saved?searchType=TrialUsers - Controller retrieves user's saved searches filtered by type
- Handler queries SavedSearches ordered by: favorites first, then most recently used
- UI displays saved search list with name, description, and usage stats
- Administrator clicks a saved search
- UI populates search form with the saved criteria
- Administrator clicks "Search" to execute (or modifies criteria first)
Alt-3: Admin User Search
Trigger: Administrator needs to search admin/application users
Flow:
- Administrator navigates to
/advanced-search/users - UI shows admin user search form with fields: Full Name, Email, Username, Status, Role, Email Verified, date ranges
- Administrator enters criteria and searches
- POST
/advanced-search/users/searchwith SearchAdminUsersQuery - Handler joins with roles for role-based filtering
- Results displayed with Name, Email, Username, Status, Verified, Roles columns
- Export available via POST
/advanced-search/users/export
Alt-4: Duplicate Saved Search Name
Trigger: Administrator saves search with name that already exists
Flow:
- Administrator enters a search name that duplicates an existing one
- Handler finds existing SavedSearch with same name for this user
- Handler throws InvalidOperationException: "A saved search with the name 'X' already exists"
- Controller returns BadRequest with error message
- UI displays error, administrator can choose a different name
Alt-5: Empty Search Results
Trigger: No users match the given criteria
Flow:
- Administrator enters restrictive criteria
- Search executes and returns TotalCount = 0
- UI displays "Found 0 trial user(s) matching your criteria"
- Results table shows empty state
- Administrator adjusts criteria and searches again
Business Rules
Search Rules
- BR-022-01: All search criteria combined with AND logic
- BR-022-02: Text fields use case-insensitive partial matching (LIKE %value%)
- BR-022-03: Date range filters use inclusive boundaries
- BR-022-04: Default sort: newest first (CreatedAt descending)
- BR-022-05: Pagination defaults: PageNumber=1, configurable PageSize
Saved Search Rules
- BR-022-06: Saved search names must be unique per user (not globally)
- BR-022-07: Each saved search belongs to exactly one user (no sharing)
- BR-022-08: Search types supported: "TrialUsers", "AdminUsers"
- BR-022-09: Criteria stored as JSON dictionary (key-value pairs)
- BR-022-10: RecordUsage() updates LastUsedAt and increments UseCount on execution
- BR-022-11: Saved searches ordered by: IsFavorite (desc), LastUsedAt (desc), CreatedAt (desc)
- BR-022-12: Users can toggle IsFavorite for quick access
Export Rules
- BR-022-13: Maximum export size: 10,000 records per CSV
- BR-022-14: CSV filenames include UTC timestamp:
trial_users_search_YYYYMMDD_HHMMSS.csv - BR-022-15: Export uses same search criteria as interactive search
- BR-022-16: Export endpoints protected with anti-forgery tokens
Authorization Rules
- BR-022-17: All search endpoints require authentication (
[Authorize]) - BR-022-18: UserId for saved searches determined from ClaimTypes.NameIdentifier
Data Model
SavedSearch Entity
| Field | Type | Description |
|---|---|---|
| Id | Guid (PK) | Unique identifier |
| UserId | Guid | Owner user ID |
| Name | string (200) | Display name, unique per user |
| Description | string? (500) | Optional description |
| SearchType | string (50) | "TrialUsers" or "AdminUsers" |
| CriteriaJson | text | Serialized search criteria JSON |
| CreatedAt | DateTime | Creation timestamp |
| LastUsedAt | DateTime? | Most recent execution timestamp |
| UseCount | int | Total execution count |
| IsFavorite | bool | Quick-access flag |
Search Criteria Fields — Trial Users
| Field | Type | Description |
|---|---|---|
| FullName | string? | Partial match on full name |
| string? | Partial match on email | |
| CompanyName | string? | Partial match on company |
| JobTitle | string? | Partial match on job title |
| IsActive | bool? | Active/inactive filter |
| TrialStartDateFrom/To | DateTime? | Trial start date range |
| TrialEndDateFrom/To | DateTime? | Trial end date range |
| TrialStatus | enum? | Active, ExpiringSoon, Expired |
| EmailVerified | bool? | Verification status |
Search Criteria Fields — Admin Users
| Field | Type | Description |
|---|---|---|
| FullName | string? | Partial match on full name |
| string? | Partial match on email | |
| Username | string? | Partial match on username |
| IsActive | bool? | Active/inactive filter |
| CreatedDateFrom/To | DateTime? | Account creation date range |
| LastLoginFrom/To | DateTime? | Last login date range |
| RoleId | Guid? | Filter by assigned role |
| EmailVerified | bool? | Verification status |
API Endpoints
| Method | Route | Description |
|---|---|---|
| GET | /advanced-search/trial-users |
Trial user search page |
| GET | /advanced-search/users |
Admin user search page |
| POST | /advanced-search/trial-users/search |
Execute trial user search |
| POST | /advanced-search/users/search |
Execute admin user search |
| POST | /advanced-search/trial-users/export |
Export trial user results to CSV |
| POST | /advanced-search/users/export |
Export admin user results to CSV |
| POST | /advanced-search/save |
Save search criteria |
| GET | /advanced-search/saved |
Retrieve saved searches |
Test Scenarios
| ID | Scenario | Expected Result |
|---|---|---|
| TS-022-01 | Search trial users by email partial match | Returns matching users with pagination |
| TS-022-02 | Search with no criteria | Returns all users (paginated) |
| TS-022-03 | Search with multiple criteria (AND logic) | Returns only users matching ALL criteria |
| TS-022-04 | Save search with unique name | SavedSearch created with correct metadata |
| TS-022-05 | Save search with duplicate name | InvalidOperationException thrown |
| TS-022-06 | Get saved searches for user | Returns only user's searches, ordered correctly |
| TS-022-07 | Get saved searches filtered by type | Returns only matching search type |
| TS-022-08 | Export trial users to CSV | File returned with correct content type |
| TS-022-09 | Search admin users by role | Returns users with specified role |
| TS-022-10 | SavedSearch.RecordUsage() | LastUsedAt updated, UseCount incremented |
| TS-022-11 | SavedSearch.ToggleFavorite() | IsFavorite toggled |
| TS-022-12 | Search with invalid model state | Returns BadRequest with ModelState errors |
Dependencies
- MediatR (CQRS command/query handling)
- Entity Framework Core with IdentityDbContext
- CsvExportService (CSV generation via CsvHelper)
- ASP.NET Core Authentication (ClaimTypes.NameIdentifier for user identity)