LogicGoInfotechSpaces commited on
Commit
32daeaa
·
1 Parent(s): 26bdcce

Fallback to budgets when no expenses

Browse files
Files changed (1) hide show
  1. app/smart_recommendation.py +69 -12
app/smart_recommendation.py CHANGED
@@ -40,19 +40,29 @@ class SmartBudgetRecommender:
40
  end_date = datetime(year, month, 1) - timedelta(days=1)
41
  start_date = end_date - timedelta(days=180) # ~6 months
42
 
43
- expenses = list(self.db.expenses.find({
44
- "user_id": user_id,
45
- "date": {"$gte": start_date, "$lte": end_date},
46
- "type": "expense"
47
- }))
48
-
49
- if not expenses:
50
- return []
51
-
52
- # Group expenses by category and calculate monthly averages
53
- category_data = self._calculate_category_statistics(expenses, start_date, end_date)
 
 
 
 
 
 
 
 
 
 
 
54
 
55
- recommendations = []
56
  for category, data in category_data.items():
57
  avg_expense = data["average_monthly"]
58
  confidence = self._calculate_confidence(data)
@@ -235,6 +245,53 @@ class SmartBudgetRecommender:
235
  result.sort(key=lambda x: x.average_monthly_expense, reverse=True)
236
  return result
237
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
  def _get_ai_recommendation(self, category: str, data: Dict, avg_expense: float):
239
  """Use OpenAI to refine the budget recommendation."""
240
  if not OPENAI_API_KEY:
 
40
  end_date = datetime(year, month, 1) - timedelta(days=1)
41
  start_date = end_date - timedelta(days=180) # ~6 months
42
 
43
+ expenses = list(
44
+ self.db.expenses.find(
45
+ {
46
+ "user_id": user_id,
47
+ "date": {"$gte": start_date, "$lte": end_date},
48
+ "type": "expense",
49
+ }
50
+ )
51
+ )
52
+
53
+ recommendations: List[BudgetRecommendation] = []
54
+
55
+ if expenses:
56
+ # Group expenses by category and calculate monthly averages
57
+ category_data = self._calculate_category_statistics(
58
+ expenses, start_date, end_date
59
+ )
60
+ else:
61
+ # No expenses found: fallback to existing budgets for this period
62
+ category_data = self._get_category_stats_from_budgets(user_id, month, year)
63
+ if not category_data:
64
+ return []
65
 
 
66
  for category, data in category_data.items():
67
  avg_expense = data["average_monthly"]
68
  confidence = self._calculate_confidence(data)
 
245
  result.sort(key=lambda x: x.average_monthly_expense, reverse=True)
246
  return result
247
 
248
+ def _get_category_stats_from_budgets(
249
+ self, user_id: str, month: int, year: int
250
+ ) -> Dict:
251
+ """
252
+ Fallback source when there are no expenses:
253
+ use existing budgets for the requested month/year as the 'average' spend.
254
+ """
255
+ budgets = list(
256
+ self.db.budgets.find(
257
+ {
258
+ "user_id": user_id,
259
+ "period": {"$in": ["monthly", "MONTHLY"]},
260
+ "start_date": {
261
+ "$lte": datetime(year, month, 28)
262
+ }, # loosely within month
263
+ }
264
+ )
265
+ )
266
+
267
+ if not budgets:
268
+ return {}
269
+
270
+ result: Dict[str, Dict] = {}
271
+ for b in budgets:
272
+ category = b.get("category", "Uncategorized")
273
+ amount = float(b.get("amount", 0))
274
+ if category not in result:
275
+ result[category] = {
276
+ "average_monthly": amount,
277
+ "total": amount,
278
+ "count": 1,
279
+ "months_analyzed": 1,
280
+ "std_dev": 0.0,
281
+ "monthly_values": [amount],
282
+ }
283
+ else:
284
+ # If multiple budgets per category, average them
285
+ result[category]["total"] += amount
286
+ result[category]["count"] += 1
287
+ result[category]["months_analyzed"] = result[category]["count"]
288
+ result[category]["average_monthly"] = (
289
+ result[category]["total"] / result[category]["count"]
290
+ )
291
+ result[category]["monthly_values"].append(amount)
292
+
293
+ return result
294
+
295
  def _get_ai_recommendation(self, category: str, data: Dict, avg_expense: float):
296
  """Use OpenAI to refine the budget recommendation."""
297
  if not OPENAI_API_KEY: