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)
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)