Implemented global quality_filter_level in user profiles for consistent data filtering across all views (Dashboard, History, Charts, KI-Pipeline). Backend changes: - Migration 016: Add quality_filter_level column to profiles table - quality_filter.py: Centralized helper functions for SQL filtering - insights.py: Apply global filter in _get_profile_data() - activity.py: Apply global filter in list_activity() Frontend changes: - SettingsPage.jsx: Add Datenqualität section with 4-level selector - History.jsx: Use global quality filter from profile context Filter levels: all, quality (good+excellent+acceptable), very_good (good+excellent), excellent (only excellent) Closes #31 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
126 lines
3.6 KiB
Python
126 lines
3.6 KiB
Python
"""
|
|
Quality Filter Helper - Data Access Layer
|
|
|
|
Provides consistent quality filtering across all activity queries.
|
|
Issue: #31
|
|
"""
|
|
from typing import Optional, Dict
|
|
|
|
|
|
def get_quality_filter_sql(profile: Dict, table_alias: str = "") -> str:
|
|
"""
|
|
Returns SQL WHERE clause fragment for quality filtering.
|
|
|
|
Args:
|
|
profile: User profile dict with quality_filter_level
|
|
table_alias: Optional table alias (e.g., "a." for "a.quality_label")
|
|
|
|
Returns:
|
|
SQL fragment (e.g., "AND quality_label IN (...)") or empty string
|
|
|
|
Examples:
|
|
>>> get_quality_filter_sql({'quality_filter_level': 'all'})
|
|
''
|
|
>>> get_quality_filter_sql({'quality_filter_level': 'quality'})
|
|
"AND quality_label IN ('excellent', 'good', 'acceptable')"
|
|
>>> get_quality_filter_sql({'quality_filter_level': 'excellent'}, 'a.')
|
|
"AND a.quality_label = 'excellent'"
|
|
"""
|
|
level = profile.get('quality_filter_level', 'all')
|
|
prefix = table_alias if table_alias else ""
|
|
|
|
if level == 'all':
|
|
return '' # No filter
|
|
elif level == 'quality':
|
|
return f"AND {prefix}quality_label IN ('excellent', 'good', 'acceptable')"
|
|
elif level == 'very_good':
|
|
return f"AND {prefix}quality_label IN ('excellent', 'good')"
|
|
elif level == 'excellent':
|
|
return f"AND {prefix}quality_label = 'excellent'"
|
|
else:
|
|
# Unknown level → no filter (safe fallback)
|
|
return ''
|
|
|
|
|
|
def get_quality_filter_tuple(profile: Dict) -> tuple:
|
|
"""
|
|
Returns tuple of allowed quality labels for Python filtering.
|
|
|
|
Args:
|
|
profile: User profile dict with quality_filter_level
|
|
|
|
Returns:
|
|
Tuple of allowed quality labels or None (no filter)
|
|
|
|
Examples:
|
|
>>> get_quality_filter_tuple({'quality_filter_level': 'all'})
|
|
None
|
|
>>> get_quality_filter_tuple({'quality_filter_level': 'quality'})
|
|
('excellent', 'good', 'acceptable')
|
|
"""
|
|
level = profile.get('quality_filter_level', 'all')
|
|
|
|
if level == 'all':
|
|
return None # No filter
|
|
elif level == 'quality':
|
|
return ('excellent', 'good', 'acceptable')
|
|
elif level == 'very_good':
|
|
return ('excellent', 'good')
|
|
elif level == 'excellent':
|
|
return ('excellent',)
|
|
else:
|
|
return None # Unknown level → no filter
|
|
|
|
|
|
def filter_activities_by_quality(activities: list, profile: Dict) -> list:
|
|
"""
|
|
Filters a list of activity dicts by quality_label.
|
|
|
|
Useful for post-query filtering (e.g., when data already loaded).
|
|
|
|
Args:
|
|
activities: List of activity dicts with quality_label field
|
|
profile: User profile dict with quality_filter_level
|
|
|
|
Returns:
|
|
Filtered list of activities
|
|
"""
|
|
allowed_labels = get_quality_filter_tuple(profile)
|
|
|
|
if allowed_labels is None:
|
|
return activities # No filter
|
|
|
|
return [
|
|
act for act in activities
|
|
if act.get('quality_label') in allowed_labels
|
|
]
|
|
|
|
|
|
# Constants for frontend/documentation
|
|
QUALITY_LEVELS = {
|
|
'all': {
|
|
'label': 'Alle',
|
|
'icon': '📊',
|
|
'description': 'Alle Activities (kein Filter)',
|
|
'includes': None
|
|
},
|
|
'quality': {
|
|
'label': 'Hochwertig',
|
|
'icon': '✓',
|
|
'description': 'Hochwertige Activities',
|
|
'includes': ['excellent', 'good', 'acceptable']
|
|
},
|
|
'very_good': {
|
|
'label': 'Sehr gut',
|
|
'icon': '✓✓',
|
|
'description': 'Sehr gute Activities',
|
|
'includes': ['excellent', 'good']
|
|
},
|
|
'excellent': {
|
|
'label': 'Exzellent',
|
|
'icon': '⭐',
|
|
'description': 'Nur exzellente Activities',
|
|
'includes': ['excellent']
|
|
}
|
|
}
|