Commit
·
0a1d03f
1
Parent(s):
eb33258
Add API-level validation for budget_amount to catch corrupted data early and provide clear error messages
Browse files- app/models.py +11 -2
- app/smart_recommendation.py +8 -1
app/models.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
from pydantic import BaseModel, Field
|
| 2 |
from typing import Optional, List
|
| 3 |
from datetime import datetime
|
| 4 |
from enum import Enum
|
|
@@ -44,7 +44,16 @@ class CategoryExpense(BaseModel):
|
|
| 44 |
class RecommendationRequest(BaseModel):
|
| 45 |
user_id: str = Field(..., description="User identifier")
|
| 46 |
category_id: str = Field(..., description="Category ID to check for previous data")
|
| 47 |
-
budget_amount: Optional[float] = Field(None, description="Current budget amount for this category (optional)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
class RecommendationResponse(BaseModel):
|
| 50 |
has_previous_data: bool
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field, validator
|
| 2 |
from typing import Optional, List
|
| 3 |
from datetime import datetime
|
| 4 |
from enum import Enum
|
|
|
|
| 44 |
class RecommendationRequest(BaseModel):
|
| 45 |
user_id: str = Field(..., description="User identifier")
|
| 46 |
category_id: str = Field(..., description="Category ID to check for previous data")
|
| 47 |
+
budget_amount: Optional[float] = Field(None, gt=0, le=1e12, description="Current budget amount for this category (optional, max 1 trillion)")
|
| 48 |
+
|
| 49 |
+
@validator('budget_amount')
|
| 50 |
+
def validate_budget_amount(cls, v):
|
| 51 |
+
if v is not None:
|
| 52 |
+
if v <= 0:
|
| 53 |
+
raise ValueError('budget_amount must be greater than 0')
|
| 54 |
+
if v > 1e12: # More than 1 trillion is likely corrupted data
|
| 55 |
+
raise ValueError(f'budget_amount ({v:,.0f}) is unreasonably large. Maximum allowed is 1,000,000,000,000 (1 trillion). Please check your input.')
|
| 56 |
+
return v
|
| 57 |
|
| 58 |
class RecommendationResponse(BaseModel):
|
| 59 |
has_previous_data: bool
|
app/smart_recommendation.py
CHANGED
|
@@ -293,7 +293,14 @@ class SmartBudgetRecommender:
|
|
| 293 |
# If budget_amount is provided, use it
|
| 294 |
using_budget_amount_only = False
|
| 295 |
if budget_amount and budget_amount > 0:
|
| 296 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 297 |
# First, get category name
|
| 298 |
category_name = self._get_category_name(category_id)
|
| 299 |
avg_expense = budget_amount
|
|
|
|
| 293 |
# If budget_amount is provided, use it
|
| 294 |
using_budget_amount_only = False
|
| 295 |
if budget_amount and budget_amount > 0:
|
| 296 |
+
# Check for data corruption in budget_amount
|
| 297 |
+
if budget_amount > 1e15: # Unreasonably large number
|
| 298 |
+
print(f"🚨 DATA CORRUPTION: budget_amount is {budget_amount:,.2e} - too large, using safe fallback")
|
| 299 |
+
# Use a reasonable default based on category or cap at 1 billion
|
| 300 |
+
budget_amount = 1e9 # 1 billion as safe maximum
|
| 301 |
+
print(f" Capped budget_amount to {budget_amount:,.0f}")
|
| 302 |
+
|
| 303 |
+
print(f"🔍 get_recommendation_for_category: Using provided budget_amount: {budget_amount:,.0f}")
|
| 304 |
# First, get category name
|
| 305 |
category_name = self._get_category_name(category_id)
|
| 306 |
avg_expense = budget_amount
|