feat: multi-Oracle server support with runtime switching
Complete implementation of multi-server Oracle database support: Backend: - Multi-pool Oracle with lazy loading per server - Email-to-server cache for automatic server discovery - JWT tokens include server_id claim - /auth/check-identity and /auth/check-email endpoints - /auth/my-servers endpoint for listing user's accessible servers - Server switch with password re-authentication Frontend: - New ServerSelector component for header dropdown - Multi-step login flow (identity → server → password) - Server switching from header with password modal - Mobile drawer menu with server selection - Dark mode support for all new components - URL bookmark support with ?server= query param Scripts: - Unified start.sh replacing start-prod.sh/start-test.sh - Unified ssh-tunnel.sh with multi-server support - Updated status.sh for new architecture Tests: - E2E tests for multi-server and single-server login flows - Backend unit tests for all new endpoints - Oracle multi-pool integration tests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,9 +4,9 @@ Refactored to use caching system for optimal performance
|
||||
"""
|
||||
# import sys # Removed - no longer needed
|
||||
import os
|
||||
from typing import Dict, Any, Optional
|
||||
|
||||
from shared.database.oracle_pool import oracle_pool
|
||||
from typing import Dict, Any
|
||||
from ..models.trial_balance import (
|
||||
TrialBalanceItem,
|
||||
TrialBalanceFilters,
|
||||
@@ -25,14 +25,14 @@ class TrialBalanceService:
|
||||
"""Service pentru gestionarea balanței de verificare cu cache"""
|
||||
|
||||
@staticmethod
|
||||
@cached(cache_type='schema', key_params=['company_id'])
|
||||
async def _get_schema(company_id: int) -> str:
|
||||
@cached(cache_type='schema', key_params=['company_id', 'server_id'])
|
||||
async def _get_schema(company_id: int, server_id: Optional[str] = None) -> str:
|
||||
"""
|
||||
Obține schema pentru company_id (CACHED 24h)
|
||||
|
||||
This is cached permanently because company schemas rarely change.
|
||||
"""
|
||||
async with oracle_pool.get_connection() as connection:
|
||||
async with oracle_pool.get_connection(server_id) as connection:
|
||||
with connection.cursor() as cursor:
|
||||
schema_query = """
|
||||
SELECT schema
|
||||
@@ -50,7 +50,7 @@ class TrialBalanceService:
|
||||
@staticmethod
|
||||
@cached(cache_type='trial_balance', key_params=['company_id', 'luna', 'an', 'cont_filter',
|
||||
'denumire_filter', 'sort_by', 'sort_order',
|
||||
'page', 'page_size', 'username'])
|
||||
'page', 'page_size', 'username', 'server_id'])
|
||||
async def get_trial_balance(
|
||||
company_id: int,
|
||||
luna: int,
|
||||
@@ -61,7 +61,8 @@ class TrialBalanceService:
|
||||
sort_order: str,
|
||||
page: int,
|
||||
page_size: int,
|
||||
username: str
|
||||
username: str,
|
||||
server_id: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Obține balanța de verificare sintetică (CACHED 10 min)
|
||||
@@ -80,12 +81,13 @@ class TrialBalanceService:
|
||||
page: Pagina
|
||||
page_size: Mărimea paginii
|
||||
username: Username pentru cache tracking
|
||||
server_id: Optional Oracle server identifier for multi-server support
|
||||
|
||||
Returns:
|
||||
Dictionary cu items, pagination, filters_applied
|
||||
"""
|
||||
# Get schema (cached separately)
|
||||
schema = await TrialBalanceService._get_schema(company_id)
|
||||
schema = await TrialBalanceService._get_schema(company_id, server_id)
|
||||
|
||||
# Validate sort_order
|
||||
if sort_order.lower() not in ['asc', 'desc']:
|
||||
@@ -97,7 +99,7 @@ class TrialBalanceService:
|
||||
if sort_by.upper() not in valid_sort_columns:
|
||||
sort_by = 'CONT'
|
||||
|
||||
async with oracle_pool.get_connection() as connection:
|
||||
async with oracle_pool.get_connection(server_id) as connection:
|
||||
with connection.cursor() as cursor:
|
||||
# Build base query for VBAL VIEW
|
||||
base_query = f"""
|
||||
|
||||
Reference in New Issue
Block a user