Skip to content
Closed
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
9 changes: 6 additions & 3 deletions backend/app/api/v1/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import Dict, Any
from app.services.cache import get_revenue_summary
from app.core.auth import authenticate_request as get_current_user
from decimal import Decimal ## I added this import to solve the floating point error

router = APIRouter()

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

revenue_data = await get_revenue_summary(property_id, tenant_id)

total_revenue_float = float(revenue_data['total'])

# total_revenue_float = float(revenue_data['total']) - this causes accuracy loss

# Convert to Decimal for precise financial math
total_revenue = Decimal(revenue_data['total'])
return {
"property_id": revenue_data['property_id'],
"total_revenue": total_revenue_float,
"total_revenue": total_revenue,
Comment on lines +19 to +25

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Returning a Decimal for total_revenue causes FastAPI under Pydantic v2 to serialize it as a string, violating the frontend numeric contract.
Severity: LOW

Suggested Fix

Cast total_revenue to float before returning it in the API response, or define an explicit Pydantic response model configuring decimal serialization as a float.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: backend/app/api/v1/dashboard.py#L19-L25

Potential issue: Returning a `Decimal` instance for `total_revenue` in an endpoint
returning `Dict[str, Any]` causes FastAPI under Pydantic v2 to serialize the value as a
JSON string instead of a number. The frontend TypeScript types define `total_revenue` as
a `number`, breaking the API contract and causing numeric values to be displayed as
quoted strings in raw data views.

Did we get this right? 👍 / 👎 to inform future reviews.

"currency": revenue_data['currency'],
"reservations_count": revenue_data['count']
}
8 changes: 7 additions & 1 deletion backend/app/services/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@ 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}"

# multiple tenants can use similar proprty ids, making client B to see client A's cached data,
# so I included tenant_id

# 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)
if cached:
Expand Down
19 changes: 14 additions & 5 deletions backend/app/services/reservations.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from datetime import datetime
from datetime import datetime, timezone
from decimal import Decimal
from typing import Dict, Any, List

Expand All @@ -7,12 +7,21 @@ async def calculate_monthly_revenue(property_id: str, month: int, year: int, db_
Calculates revenue for a specific month.
"""

start_date = datetime(year, month, 1)
# start_date = datetime(year, month, 1)
# if month < 12:
# end_date = datetime(year, month + 1, 1)
# else:
# end_date = datetime(year + 1, 1, 1)



# I made the datetimes timezone-aware (specifically UTC) , that is why i added timezone to the import
# so the database performs an absolute time comparison.
start_date = datetime(year, month, 1, tzinfo=timezone.utc)
if month < 12:
end_date = datetime(year, month + 1, 1)
end_date = datetime(year, month + 1, 1, tzinfo=timezone.utc)
else:
end_date = datetime(year + 1, 1, 1)

end_date = datetime(year + 1, 1, 1, tzinfo=timezone.utc)
print(f"DEBUG: Querying revenue for {property_id} from {start_date} to {end_date}")

# SQL Simulation (This would be executed against the actual DB)
Expand Down