feat: improve notification filters configuration format

- Change filters config from nested dict to simple arrays
- Update NotificationFilters model to use List[str] instead of Dict[str, str]
- Modify notification service to handle list-based filters
- Update API routes and tests for new format
- Update README with new configuration example

Before: [filters.case-insensitive] salary = 'salary'
After: [filters] case-insensitive = ['salary', 'utility']
This commit is contained in:
Elisiário Couto
2025-09-09 16:51:26 +01:00
committed by Elisiário Couto
parent bc947183e3
commit 2191fe9066
5 changed files with 31 additions and 13 deletions

View File

@@ -114,9 +114,9 @@ chat_id = 12345
enabled = true
# Optional: Transaction filters for notifications
[filters.case-insensitive]
salary = "salary"
bills = "utility"
[filters]
case-insensitive = ["salary", "utility"]
case-sensitive = ["SpecificStore"]
```
## 📖 Usage

View File

@@ -1,4 +1,4 @@
from typing import Dict, Optional, List
from typing import Optional, List
from pydantic import BaseModel
@@ -21,8 +21,8 @@ class TelegramConfig(BaseModel):
class NotificationFilters(BaseModel):
"""Notification filters configuration"""
case_insensitive: Dict[str, str] = {}
case_sensitive: Optional[Dict[str, str]] = None
case_insensitive: List[str] = []
case_sensitive: Optional[List[str]] = None
amount_threshold: Optional[float] = None
keywords: List[str] = []

View File

@@ -46,7 +46,7 @@ async def get_notification_settings() -> APIResponse:
if (telegram_config.get("token") or telegram_config.get("api-key"))
else None,
filters=NotificationFilters(
case_insensitive=filters_config.get("case-insensitive", {}),
case_insensitive=filters_config.get("case-insensitive", []),
case_sensitive=filters_config.get("case-sensitive"),
amount_threshold=filters_config.get("amount_threshold"),
keywords=filters_config.get("keywords", []),

View File

@@ -63,14 +63,29 @@ class NotificationService:
) -> List[Dict[str, Any]]:
"""Filter transactions based on notification criteria"""
matching = []
filters_case_insensitive = self.filters_config.get("case-insensitive", {})
filters_case_insensitive = self.filters_config.get("case-insensitive", [])
filters_case_sensitive = self.filters_config.get("case-sensitive", [])
for transaction in transactions:
description = transaction.get("description", "").lower()
description = transaction.get("description", "")
description_lower = description.lower()
# Check case-insensitive filters
for _filter_name, filter_value in filters_case_insensitive.items():
if filter_value.lower() in description:
for filter_value in filters_case_insensitive:
if filter_value.lower() in description_lower:
matching.append(
{
"name": transaction["description"],
"value": transaction["transactionValue"],
"currency": transaction["transactionCurrency"],
"date": transaction["transactionDate"],
}
)
break
# Check case-sensitive filters
for filter_value in filters_case_sensitive:
if filter_value in description:
matching.append(
{
"name": transaction["description"],

View File

@@ -188,7 +188,8 @@ class TestConfig:
"""Test filters configuration access."""
custom_config = {
"filters": {
"case-insensitive": {"salary": "SALARY", "bills": "BILL"},
"case-insensitive": ["salary", "utility"],
"case-sensitive": ["SpecificStore"],
"amount_threshold": 100.0,
}
}
@@ -197,5 +198,7 @@ class TestConfig:
config._config = custom_config
filters = config.filters_config
assert filters["case-insensitive"]["salary"] == "SALARY"
assert "salary" in filters["case-insensitive"]
assert "utility" in filters["case-insensitive"]
assert "SpecificStore" in filters["case-sensitive"]
assert filters["amount_threshold"] == 100.0