Vincentran commited on
Commit
978e57b
·
1 Parent(s): 03da54f

Upload E-Commerce Product Intelligence Dashboard

Browse files
Files changed (1) hide show
  1. app.py +38 -11
app.py CHANGED
@@ -18,8 +18,15 @@ def load_data():
18
  if not LOCAL_CSV_PATH.exists():
19
  raise FileNotFoundError(f"CSV not found: {LOCAL_CSV_PATH}")
20
 
21
- logger.info(f"Loading CSV from: {LOCAL_CSV_PATH}")
22
- return pd.read_csv(LOCAL_CSV_PATH)
 
 
 
 
 
 
 
23
 
24
 
25
  @app.get("/")
@@ -36,18 +43,24 @@ def get_data():
36
  @app.get("/stats/categories")
37
  def stats_categories():
38
  df = load_data()
 
 
39
  return df["category"].value_counts().head(10).to_dict()
40
 
41
 
42
  @app.get("/stats/brands")
43
  def stats_brands():
44
  df = load_data()
 
 
45
  return df["brand"].value_counts().head(10).to_dict()
46
 
47
 
48
  @app.get("/stats/price")
49
  def stats_price():
50
  df = load_data()
 
 
51
  return df.groupby("category")["price"].agg(["mean", "median", "min", "max", "count"]).reset_index().to_dict(
52
  "records")
53
 
@@ -55,6 +68,8 @@ def stats_price():
55
  @app.get("/stats/rating")
56
  def stats_rating():
57
  df = load_data()
 
 
58
  return df.groupby("category")["rating"].agg(["mean", "median", "min", "max", "count"]).reset_index().to_dict(
59
  "records")
60
 
@@ -64,10 +79,10 @@ def insights():
64
  df = load_data()
65
  return JSONResponse(content={
66
  "total_products": len(df),
67
- "categories": df["category"].nunique(),
68
- "brands": df["brand"].nunique(),
69
- "avg_price": df["price"].mean(),
70
- "avg_rating": df["rating"].mean(),
71
  })
72
 
73
 
@@ -75,18 +90,30 @@ def insights():
75
  def search(query: str):
76
  df = load_data()
77
  q = query.lower()
78
- mask = (
79
- df["title"].str.contains(q, case=False, na=False) |
80
- df["description"].str.contains(q, case=False, na=False)
81
- )
 
 
 
 
 
 
 
82
  return df[mask].head(100).to_dict("records")
83
 
84
 
85
  @app.get("/recommend")
86
  def recommend(category: str):
87
  df = load_data()
 
 
 
88
  subset = df[df["category"] == category]
89
- return subset.sort_values("rating", ascending=False).head(10).to_dict("records")
 
 
90
 
91
 
92
  @app.post("/run-scraper")
 
18
  if not LOCAL_CSV_PATH.exists():
19
  raise FileNotFoundError(f"CSV not found: {LOCAL_CSV_PATH}")
20
 
21
+ file_size = LOCAL_CSV_PATH.stat().st_size
22
+ logger.info(f"Loading CSV from: {LOCAL_CSV_PATH} (size: {file_size} bytes)")
23
+
24
+ if file_size == 0:
25
+ raise ValueError(f"CSV file is empty: {LOCAL_CSV_PATH}")
26
+
27
+ df = pd.read_csv(LOCAL_CSV_PATH)
28
+ logger.info(f"Loaded {len(df)} rows, columns: {list(df.columns)}")
29
+ return df
30
 
31
 
32
  @app.get("/")
 
43
  @app.get("/stats/categories")
44
  def stats_categories():
45
  df = load_data()
46
+ if "category" not in df.columns:
47
+ raise ValueError("Missing 'category' column")
48
  return df["category"].value_counts().head(10).to_dict()
49
 
50
 
51
  @app.get("/stats/brands")
52
  def stats_brands():
53
  df = load_data()
54
+ if "brand" not in df.columns:
55
+ raise ValueError("Missing 'brand' column")
56
  return df["brand"].value_counts().head(10).to_dict()
57
 
58
 
59
  @app.get("/stats/price")
60
  def stats_price():
61
  df = load_data()
62
+ if "category" not in df.columns or "price" not in df.columns:
63
+ raise ValueError("Missing 'category' or 'price' column")
64
  return df.groupby("category")["price"].agg(["mean", "median", "min", "max", "count"]).reset_index().to_dict(
65
  "records")
66
 
 
68
  @app.get("/stats/rating")
69
  def stats_rating():
70
  df = load_data()
71
+ if "category" not in df.columns or "rating" not in df.columns:
72
+ raise ValueError("Missing 'category' or 'rating' column")
73
  return df.groupby("category")["rating"].agg(["mean", "median", "min", "max", "count"]).reset_index().to_dict(
74
  "records")
75
 
 
79
  df = load_data()
80
  return JSONResponse(content={
81
  "total_products": len(df),
82
+ "categories": df["category"].nunique() if "category" in df.columns else 0,
83
+ "brands": df["brand"].nunique() if "brand" in df.columns else 0,
84
+ "avg_price": df["price"].mean() if "price" in df.columns else 0,
85
+ "avg_rating": df["rating"].mean() if "rating" in df.columns else 0,
86
  })
87
 
88
 
 
90
  def search(query: str):
91
  df = load_data()
92
  q = query.lower()
93
+
94
+ # Find text columns
95
+ text_cols = df.select_dtypes(include=["object"]).columns.tolist()
96
+
97
+ mask = pd.Series([False] * len(df), index=df.index)
98
+ for col in text_cols[:5]: # Check first 5 text columns
99
+ try:
100
+ mask |= df[col].str.contains(q, case=False, na=False)
101
+ except:
102
+ pass
103
+
104
  return df[mask].head(100).to_dict("records")
105
 
106
 
107
  @app.get("/recommend")
108
  def recommend(category: str):
109
  df = load_data()
110
+ if "category" not in df.columns:
111
+ raise ValueError("Missing 'category' column")
112
+
113
  subset = df[df["category"] == category]
114
+ if "rating" in df.columns:
115
+ return subset.sort_values("rating", ascending=False).head(10).to_dict("records")
116
+ return subset.head(10).to_dict("records")
117
 
118
 
119
  @app.post("/run-scraper")