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:
@@ -1,12 +1,12 @@
|
||||
# import sys # Removed - no longer needed
|
||||
import os
|
||||
from typing import Optional, List, Tuple, Any
|
||||
|
||||
import oracledb
|
||||
from shared.database.oracle_pool import oracle_pool
|
||||
from ..models.treasury import BankCashRegister, RegisterFilter, RegisterListResponse, AccountingPeriod
|
||||
from ..cache.decorators import cached
|
||||
from decimal import Decimal
|
||||
from typing import Optional, List, Tuple, Any
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -15,10 +15,10 @@ class TreasuryService:
|
||||
"""Service pentru trezorerie - registru casă și bancă"""
|
||||
|
||||
@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 PERMANENT)"""
|
||||
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
|
||||
@@ -99,8 +99,8 @@ class TreasuryService:
|
||||
return " UNION ALL ".join(queries)
|
||||
|
||||
@staticmethod
|
||||
@cached(cache_type='treasury', key_params=['filter_params', 'username'])
|
||||
async def get_bank_cash_register(filter_params: RegisterFilter, username: str) -> RegisterListResponse:
|
||||
@cached(cache_type='treasury', key_params=['filter_params', 'username', 'server_id'])
|
||||
async def get_bank_cash_register(filter_params: RegisterFilter, username: str, server_id: Optional[str] = None) -> RegisterListResponse:
|
||||
"""
|
||||
Obține registrul de casă și bancă din vbancasa views (CACHED 10 min)
|
||||
|
||||
@@ -114,9 +114,9 @@ class TreasuryService:
|
||||
Toate în aceeași tranzacție!
|
||||
"""
|
||||
company_id = int(filter_params.company)
|
||||
schema = await TreasuryService._get_schema(company_id)
|
||||
schema = await TreasuryService._get_schema(company_id, server_id)
|
||||
|
||||
async with oracle_pool.get_connection() as connection:
|
||||
async with oracle_pool.get_connection(server_id) as connection:
|
||||
with connection.cursor() as cursor:
|
||||
|
||||
# Construiește query-ul pentru tipul de registru selectat
|
||||
@@ -350,14 +350,14 @@ class TreasuryService:
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@cached(cache_type='treasury', key_params=['company_id', 'register_type'])
|
||||
async def get_bank_cash_accounts(company_id: int, register_type: str) -> List[str]:
|
||||
@cached(cache_type='treasury', key_params=['company_id', 'register_type', 'server_id'])
|
||||
async def get_bank_cash_accounts(company_id: int, register_type: str, server_id: Optional[str] = None) -> List[str]:
|
||||
"""
|
||||
Obține lista distinctă de conturi bancă/casă (bancasa) pentru dropdown.
|
||||
Cached pentru performanță.
|
||||
IMPORTANT: Trebuie să setăm contextul PACK_SESIUNE înainte de a accesa vbancasa views!
|
||||
"""
|
||||
schema = await TreasuryService._get_schema(company_id)
|
||||
schema = await TreasuryService._get_schema(company_id, server_id)
|
||||
|
||||
# Map register_type to view
|
||||
view_map = {
|
||||
@@ -372,7 +372,7 @@ class TreasuryService:
|
||||
|
||||
view_name = view_map[register_type]
|
||||
|
||||
async with oracle_pool.get_connection() as connection:
|
||||
async with oracle_pool.get_connection(server_id) as connection:
|
||||
with connection.cursor() as cursor:
|
||||
# PL/SQL block to set session context and get accounts
|
||||
plsql_block = f"""
|
||||
|
||||
Reference in New Issue
Block a user