Consolidate 3 separate applications (reports-app, data-entry-app, telegram-bot) into a unified
architecture with single backend and frontend:
Backend Changes:
- Unified FastAPI backend at backend/ with modular structure
- Modules: reports, data_entry, telegram in backend/modules/
- Centralized config.py and main.py with all routers registered
- Single worker mode (--workers 1) for Telegram bot compatibility
- Shared Oracle connection pool and JWT authentication
- Unified requirements.txt and environment configuration
Frontend Changes:
- Single Vue.js SPA with module-based routing
- Unified frontend at src/ with modules in src/modules/{reports,data-entry}/
- Shared components and stores in src/shared/
- Error boundaries for module isolation
- Dual API proxy in Vite for module communication
Infrastructure:
- New unified startup scripts: start-prod.sh, start-test.sh, start-backend.sh
- Environment templates: .env.dev.example, .env.test.example, .env.prod.example
- Updated deployment scripts for Windows IIS
- Simplified SSH tunnel management
Documentation:
- Comprehensive CLAUDE.md with architecture overview
- Module-specific docs in docs/{data-entry,telegram}/
- Architecture decision records in docs/ARCHITECTURE-DECISIONS.md
- Deployment guides consolidated in deployment/windows/docs/
This migration reduces complexity, improves maintainability, and enables easier
deployment while maintaining all existing functionality.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
97 lines
2.5 KiB
Python
97 lines
2.5 KiB
Python
"""Application configuration using pydantic-settings."""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from typing import List
|
|
from pydantic_settings import BaseSettings
|
|
from functools import lru_cache
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
"""Application settings loaded from environment variables."""
|
|
|
|
# App info
|
|
app_name: str = "Data Entry API"
|
|
app_version: str = "1.0.0"
|
|
debug: bool = False
|
|
|
|
# API
|
|
api_host: str = "0.0.0.0"
|
|
api_port: int = 8003
|
|
|
|
# SQLite Database
|
|
sqlite_database_path: str = "data/receipts/receipts.db"
|
|
|
|
# File uploads
|
|
upload_path: str = "data/uploads"
|
|
max_upload_size_mb: int = 10
|
|
allowed_mime_types: List[str] = [
|
|
"image/jpeg",
|
|
"image/png",
|
|
"image/gif",
|
|
"image/webp",
|
|
"application/pdf",
|
|
]
|
|
|
|
# Oracle Database (for nomenclatures)
|
|
oracle_user: str = ""
|
|
oracle_password: str = ""
|
|
oracle_host: str = "localhost"
|
|
oracle_port: int = 1526
|
|
oracle_sid: str = "ROA"
|
|
|
|
# JWT Authentication
|
|
jwt_secret_key: str = "change-me-in-production"
|
|
jwt_algorithm: str = "HS256"
|
|
jwt_expire_minutes: int = 480
|
|
|
|
# CORS
|
|
cors_origins: str = "http://localhost:3010,http://localhost:3000"
|
|
|
|
class Config:
|
|
env_file = ".env"
|
|
env_file_encoding = "utf-8"
|
|
extra = "ignore"
|
|
|
|
@property
|
|
def database_url(self) -> str:
|
|
"""Get SQLite database URL for async."""
|
|
return f"sqlite+aiosqlite:///{self.sqlite_database_path}"
|
|
|
|
@property
|
|
def sync_database_url(self) -> str:
|
|
"""Get SQLite database URL for sync operations (Alembic)."""
|
|
return f"sqlite:///{self.sqlite_database_path}"
|
|
|
|
@property
|
|
def upload_path_resolved(self) -> Path:
|
|
"""Get resolved upload path."""
|
|
path = Path(self.upload_path)
|
|
path.mkdir(parents=True, exist_ok=True)
|
|
return path
|
|
|
|
@property
|
|
def max_upload_size_bytes(self) -> int:
|
|
"""Get max upload size in bytes."""
|
|
return self.max_upload_size_mb * 1024 * 1024
|
|
|
|
@property
|
|
def cors_origins_list(self) -> List[str]:
|
|
"""Get CORS origins as list."""
|
|
return [origin.strip() for origin in self.cors_origins.split(",")]
|
|
|
|
@property
|
|
def oracle_dsn(self) -> str:
|
|
"""Get Oracle DSN string."""
|
|
return f"{self.oracle_host}:{self.oracle_port}/{self.oracle_sid}"
|
|
|
|
|
|
@lru_cache()
|
|
def get_settings() -> Settings:
|
|
"""Get cached settings instance."""
|
|
return Settings()
|
|
|
|
|
|
# Convenience instance
|
|
settings = get_settings()
|