Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions backend/app/api/v1/dashboard.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from fastapi import APIRouter, Depends, HTTPException
from typing import Dict, Any
from decimal import Decimal, ROUND_HALF_UP
from app.services.cache import get_revenue_summary
from app.core.auth import authenticate_request as get_current_user

Expand All @@ -15,11 +16,11 @@ async def get_dashboard_summary(

revenue_data = await get_revenue_summary(property_id, tenant_id)

total_revenue_float = float(revenue_data['total'])
total_revenue = Decimal(revenue_data['total']).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)

return {
"property_id": revenue_data['property_id'],
"total_revenue": total_revenue_float,
"total_revenue": float(total_revenue),
"currency": revenue_data['currency'],
"reservations_count": revenue_data['count']
}
6 changes: 2 additions & 4 deletions backend/app/core/database_pool.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import asyncio
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
from sqlalchemy.pool import QueuePool
import logging
from ..config import settings

Expand All @@ -15,11 +14,10 @@ async def initialize(self):
"""Initialize database connection pool"""
try:
# Create async engine with connection pooling
database_url = f"postgresql+asyncpg://{settings.supabase_db_user}:{settings.supabase_db_password}@{settings.supabase_db_host}:{settings.supabase_db_port}/{settings.supabase_db_name}"
database_url = settings.database_url.replace("postgresql://", "postgresql+asyncpg://", 1)

self.engine = create_async_engine(
database_url,
poolclass=QueuePool,
pool_size=20, # Number of connections to maintain
max_overflow=30, # Additional connections when needed
pool_pre_ping=True, # Validate connections
Expand All @@ -45,7 +43,7 @@ async def close(self):
if self.engine:
await self.engine.dispose()

async def get_session(self) -> AsyncSession:
def get_session(self) -> AsyncSession:
"""Get database session from pool"""
if not self.session_factory:
raise Exception("Database pool not initialized")
Expand Down
2 changes: 1 addition & 1 deletion backend/app/services/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ async def get_revenue_summary(property_id: str, tenant_id: str) -> Dict[str, Any
"""
Fetches revenue summary, utilizing caching to improve performance.
"""
cache_key = f"revenue:{property_id}"
cache_key = f"revenue:{tenant_id}:{property_id}"

# Try to get from cache
cached = await redis_client.get(cache_key)
Expand Down
46 changes: 28 additions & 18 deletions backend/app/services/reservations.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,44 @@
from decimal import Decimal
from typing import Dict, Any, List

async def calculate_monthly_revenue(property_id: str, month: int, year: int, db_session=None) -> Decimal:
async def calculate_monthly_revenue(property_id: str, month: int, year: int, tenant_id: str) -> Decimal:
"""
Calculates revenue for a specific month.
"""

# month window in the property's local time, not UTC
start_date = datetime(year, month, 1)
if month < 12:
end_date = datetime(year, month + 1, 1)
else:
end_date = datetime(year + 1, 1, 1)

print(f"DEBUG: Querying revenue for {property_id} from {start_date} to {end_date}")

# SQL Simulation (This would be executed against the actual DB)
query = """
SELECT SUM(total_amount) as total
FROM reservations
WHERE property_id = $1
AND tenant_id = $2
AND check_in_date >= $3
AND check_in_date < $4
"""

# In production this query executes against a database session.
# result = await db.fetch_val(query, property_id, tenant_id, start_date, end_date)
# return result or Decimal('0')

return Decimal('0') # Placeholder for now until DB connection is finalized
from app.core.database_pool import DatabasePool
from sqlalchemy import text

db_pool = DatabasePool()
await db_pool.initialize()

async with db_pool.get_session() as session:
query = text("""
SELECT COALESCE(SUM(r.total_amount), 0) as total
FROM reservations r
JOIN properties p ON p.id = r.property_id AND p.tenant_id = r.tenant_id
WHERE r.property_id = :property_id
AND r.tenant_id = :tenant_id
AND (r.check_in_date AT TIME ZONE p.timezone) >= :start_date
AND (r.check_in_date AT TIME ZONE p.timezone) < :end_date
""")

result = await session.execute(query, {
"property_id": property_id,
"tenant_id": tenant_id,
"start_date": start_date,
"end_date": end_date,
})
row = result.fetchone()

return Decimal(str(row.total))

async def calculate_total_revenue(property_id: str, tenant_id: str) -> Dict[str, Any]:
"""
Expand Down