Spaces:
Running
Running
Mitesh Koshiya
commited on
Commit
·
a7b441f
1
Parent(s):
9b76f9e
add new get visualize endpoint
Browse files
main.py
CHANGED
@@ -686,6 +686,106 @@ async def not_found_handler(request: Request, exc):
|
|
686 |
async def internal_error_handler(request: Request, exc):
|
687 |
return ORJSONResponse(status_code=500, content={"error": "Internal server error: " + str(exc)})
|
688 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
689 |
@app.post("/analyze", response_class=ORJSONResponse)
|
690 |
async def analyze(input: TextInput):
|
691 |
start_time = time.time() # ⏱️ start
|
|
|
686 |
async def internal_error_handler(request: Request, exc):
|
687 |
return ORJSONResponse(status_code=500, content={"error": "Internal server error: " + str(exc)})
|
688 |
|
689 |
+
@app.get("/visualyse/{user_id}", response_class=ORJSONResponse)
|
690 |
+
async def visualyse_dashboard(user_id: str):
|
691 |
+
try:
|
692 |
+
conn = psycopg2.connect(DATABASE_URL)
|
693 |
+
cur = conn.cursor()
|
694 |
+
# Fetch all entries for the user
|
695 |
+
cur.execute("SELECT * FROM user_entries WHERE user_id = %s", (user_id,))
|
696 |
+
rows = cur.fetchall()
|
697 |
+
columns = [desc[0] for desc in cur.description]
|
698 |
+
entries = [dict(zip(columns, row)) for row in rows]
|
699 |
+
cur.close()
|
700 |
+
conn.close()
|
701 |
+
except Exception as e:
|
702 |
+
return ORJSONResponse(status_code=500, content={"error": str(e)})
|
703 |
+
|
704 |
+
# Section 1: Expense Overview
|
705 |
+
expenses = [e for e in entries if e["type"] == "expense"]
|
706 |
+
total_expense = sum(a["value"] for e in expenses for a in (e["amounts"] or []))
|
707 |
+
expense_count = len(expenses)
|
708 |
+
expense_by_category = {}
|
709 |
+
for e in expenses:
|
710 |
+
cat = e.get("expense_type", "miscellaneous")
|
711 |
+
amt = sum(a["value"] for a in (e["amounts"] or []))
|
712 |
+
expense_by_category[cat] = expense_by_category.get(cat, 0) + amt
|
713 |
+
|
714 |
+
# Monthly/Weekly Trends
|
715 |
+
monthly_trends = {}
|
716 |
+
for e in expenses:
|
717 |
+
key = f"{e['month']}-{e['year']}"
|
718 |
+
amt = sum(a["value"] for a in (e["amounts"] or []))
|
719 |
+
monthly_trends[key] = monthly_trends.get(key, 0) + amt
|
720 |
+
|
721 |
+
# Section 2: Top Stores & Categories
|
722 |
+
store_stats = {}
|
723 |
+
for e in expenses:
|
724 |
+
for s in (e["stores"] or []):
|
725 |
+
store = s.get("store", "unknown")
|
726 |
+
amt = sum(a["value"] for a in (e["amounts"] or []))
|
727 |
+
if store not in store_stats:
|
728 |
+
store_stats[store] = {"count": 0, "total": 0}
|
729 |
+
store_stats[store]["count"] += 1
|
730 |
+
store_stats[store]["total"] += amt
|
731 |
+
top_categories = sorted(expense_by_category.items(), key=lambda x: x[1], reverse=True)
|
732 |
+
|
733 |
+
# Section 3: Recent Expenses
|
734 |
+
recent_expenses = sorted(expenses, key=lambda e: e.get("created_at", ""), reverse=True)[:10]
|
735 |
+
|
736 |
+
# Section 4: Mood Trends
|
737 |
+
mood_dist = {}
|
738 |
+
for e in entries:
|
739 |
+
mood = e.get("mood", "neutral")
|
740 |
+
mood_dist[mood] = mood_dist.get(mood, 0) + 1
|
741 |
+
|
742 |
+
# Section 5: Tags & Keywords
|
743 |
+
tag_freq = {}
|
744 |
+
for e in entries:
|
745 |
+
for tag in (e["tags"] or []):
|
746 |
+
tag_freq[tag] = tag_freq.get(tag, 0) + 1
|
747 |
+
top_tags = sorted(tag_freq.items(), key=lambda x: x[1], reverse=True)[:10]
|
748 |
+
|
749 |
+
# Section 6: Time Analysis
|
750 |
+
day_stats = {}
|
751 |
+
hour_stats = {}
|
752 |
+
for e in expenses:
|
753 |
+
day = e.get("day_of_week", "unknown")
|
754 |
+
hour = e.get("hour_of_day", 0)
|
755 |
+
amt = sum(a["value"] for a in (e["amounts"] or []))
|
756 |
+
day_stats[day] = day_stats.get(day, 0) + amt
|
757 |
+
hour_stats[hour] = hour_stats.get(hour, 0) + amt
|
758 |
+
|
759 |
+
# Section 7: Meta Info
|
760 |
+
entry_count = len(entries)
|
761 |
+
type_dist = {}
|
762 |
+
for e in entries:
|
763 |
+
t = e.get("type", "other")
|
764 |
+
type_dist[t] = type_dist.get(t, 0) + 1
|
765 |
+
|
766 |
+
dashboard = {
|
767 |
+
"expense_overview": {
|
768 |
+
"total_expense": total_expense,
|
769 |
+
"expense_count": expense_count,
|
770 |
+
"expense_by_category": expense_by_category,
|
771 |
+
"monthly_trends": monthly_trends
|
772 |
+
},
|
773 |
+
"top_stores": store_stats,
|
774 |
+
"top_categories": top_categories,
|
775 |
+
"recent_expenses": recent_expenses,
|
776 |
+
"mood_distribution": mood_dist,
|
777 |
+
"top_tags": top_tags,
|
778 |
+
"time_analysis": {
|
779 |
+
"by_day": day_stats,
|
780 |
+
"by_hour": hour_stats
|
781 |
+
},
|
782 |
+
"meta_info": {
|
783 |
+
"entry_count": entry_count,
|
784 |
+
"type_distribution": type_dist
|
785 |
+
}
|
786 |
+
}
|
787 |
+
return ORJSONResponse(content=dashboard)
|
788 |
+
|
789 |
@app.post("/analyze", response_class=ORJSONResponse)
|
790 |
async def analyze(input: TextInput):
|
791 |
start_time = time.time() # ⏱️ start
|