-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
132 lines (106 loc) · 6.01 KB
/
server.py
File metadata and controls
132 lines (106 loc) · 6.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
from fastapi import FastAPI, HTTPException # Import FastAPI and HTTPException for creating API and error handling
from datetime import date # Import date type to handle date parameters
import db_helper # Import custom module to interact with the database
from typing import List,Literal # Import List type for type hinting multiple objects
from pydantic import BaseModel # Import BaseModel for defining data models for validation
from decimal import Decimal
app = FastAPI() # Create an instance of FastAPI application
class Expense(BaseModel): # Define a Pydantic model for Expense data validation
# expense_date: date # Commented out because date is passed separately, not in body
amount: float # Expense amount, must be a float
category: str # Category of the expense, must be a string
notes: str # Additional notes about the expense, must be a string
class DateRange(BaseModel): # Define a Pydantic model for date range input
start_date: date # Start date for filtering expenses
end_date: date # End date for filtering expenses
class BudgetRequest(BaseModel):
category: str
start_date: str
end_date: str
class BudgetResponse(BaseModel):
category: str
start_date: str
end_date: str
budget_amount: float
total_expense: float
status: Literal["Within Budget", "Approaching Budget Limit", "Budget Exceeded"]
class BudgetSummaryRequest(BaseModel):
start_date: date
end_date: date
class BudgetSummary(BaseModel):
category: str
budget_amount: float
total_expense: float
status: Literal["Within Budget", "Approaching Budget Limit", "Budget Exceeded"]
class MonthlySummary(BaseModel):
expense_month: int
month_name: str
total: float
@app.get("/expenses/{expense_date}", response_model=List[Expense]) # Define GET endpoint with date param and list of Expense response
def get_expenses(expense_date: date): # Function to get expenses for a specific date
expenses = db_helper.fetch_expenses_for_date(expense_date) # Fetch expenses from DB for the given date
if expenses is None: # If no expenses returned (error or empty)
raise HTTPException(status_code=500, detail="Failed to receive Exception Summary from the database") # Raise 500 error
return expenses # Return list of expenses
@app.post("/expenses/{expense_date}") # Define POST endpoint to add or update expenses for a date
def add_or_update_expenses(expense_date: date, expenses: List[Expense]): # Accept date and list of expenses
db_helper.delete_expenses_for_date(expense_date) # Delete existing expenses for that date before inserting new ones
for expense in expenses: # Loop through each expense in the list
db_helper.insert_expense(str(expense_date), expense.amount, expense.category, expense.notes) # Insert each expense, date converted to string
return {"message": "Expenses updated carefully"} # Return success message
@app.post("/analytics/") # Define POST endpoint for analytics summary in a date range
def get_analytics(date_range: DateRange): # Accept a date range for the query
data = db_helper.fetch_expense_summary(date_range.start_date, date_range.end_date) # Fetch summary data from DB between the given dates
if data is None: # If no data returned or error
raise HTTPException(status_code=500, detail="Failed to receive Exception Summary from the database") # Raise 500 error
total = sum([row['Total Amount'] for row in data]) # Calculate total amount spent in the date range
breakdown = {} # Initialize empty dictionary for category-wise breakdown
for row in data: # Loop through each category's data row
percentage = (row['Total Amount'] / total) * 100 if total != 0 else 0 # Calculate percentage of total spent per category
breakdown[row['category']] = { # Store total and percentage in breakdown dict keyed by category
"total": row['Total Amount'], # Total amount spent in category
"percentage": percentage # Percentage contribution of category to total spending
}
return breakdown # Return the breakdown dictionary as response
@app.get("/monthly_summary/", response_model=List[MonthlySummary])
def get_monthly_summary():
summaries = db_helper.fetch_monthly_expense_summary()
if summaries is None or len(summaries) == 0:
raise HTTPException(status_code=404, detail="No monthly summary data found")
result = []
for row in summaries:
result.append(MonthlySummary(
expense_month=row["expense_month"],
month_name=row["month_name"],
total=float(row["total"])
))
return result
@app.post("/budget", response_model=BudgetResponse)
def get_budget(data: BudgetRequest):
budget_amount = db_helper.fetch_budget_for_category(data.category, data.start_date, data.end_date)
total_expense = db_helper.fetch_total_expenses_for_category(data.category, data.start_date, data.end_date)
if budget_amount is None:
raise HTTPException(status_code=404, detail="Budget not found for this category and date range")
# Compare
total_expense = Decimal(total_expense or 0)
budget = Decimal(budget_amount)
if total_expense > budget:
status = "Budget Exceeded"
elif total_expense >= budget * Decimal('0.9'):
status = "Approaching Budget Limit"
else:
status = "Within Budget"
return BudgetResponse(
category=data.category,
start_date=data.start_date,
end_date=data.end_date,
budget_amount=float(budget),
total_expense=float(total_expense),
status=status
)
@app.post("/budget-summary", response_model=List[BudgetSummary])
def budget_summary(date_range: DateRange):
summaries = db_helper.fetch_budget_summary_for_all_categories(date_range.start_date, date_range.end_date)
if summaries is None:
raise HTTPException(status_code=404, detail="No budget summary found")
return summaries