feat: Transform to web architecture with FastAPI backend

This major update transforms leggen from CLI-only to a web-ready
architecture while maintaining full CLI compatibility.

New Features:
- FastAPI backend service (leggend) with comprehensive REST API
- Background job scheduler with configurable cron (replaces Ofelia)
- All CLI commands refactored to use API endpoints
- Docker configuration updated for new services
- API client with health checks and error handling

API Endpoints:
- /api/v1/banks/* - Bank connections and institutions
- /api/v1/accounts/* - Account management and balances
- /api/v1/transactions/* - Transaction retrieval with filtering
- /api/v1/sync/* - Manual sync and scheduler configuration
- /api/v1/notifications/* - Notification settings management

CLI Enhancements:
- New --api-url option and LEGGEND_API_URL environment variable
- Enhanced sync command with --wait and --force options
- Improved transactions command with --full and --limit options
- Automatic fallback and health checking

Breaking Changes:
- compose.yml structure updated (leggend service added)
- Ofelia scheduler removed (internal scheduler used instead)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Elisiário Couto
2025-09-02 00:01:35 +01:00
committed by Elisiário Couto
parent 73d6bd32db
commit 91f53b35b1
39 changed files with 2810 additions and 347 deletions

View File

@@ -0,0 +1,47 @@
from typing import Dict, Any, Optional, List
from pydantic import BaseModel
class DiscordConfig(BaseModel):
"""Discord notification configuration"""
webhook: str
enabled: bool = True
class TelegramConfig(BaseModel):
"""Telegram notification configuration"""
token: str
chat_id: int
enabled: bool = True
class NotificationFilters(BaseModel):
"""Notification filters configuration"""
case_insensitive: Dict[str, str] = {}
case_sensitive: Optional[Dict[str, str]] = None
amount_threshold: Optional[float] = None
keywords: List[str] = []
class NotificationSettings(BaseModel):
"""Complete notification settings"""
discord: Optional[DiscordConfig] = None
telegram: Optional[TelegramConfig] = None
filters: NotificationFilters = NotificationFilters()
class NotificationTest(BaseModel):
"""Test notification request"""
service: str # "discord" or "telegram"
message: str = "Test notification from Leggen"
class NotificationHistory(BaseModel):
"""Notification history entry"""
id: str
service: str
message: str
status: str # "sent", "failed"
sent_at: str
error: Optional[str] = None