AI-Powered Expense Tracker and Budget Recommendation Tool Swift
👤 Sharing: AI
```swift
import Foundation
// MARK: - Data Structures
// Represents a single expense
struct Expense {
let id: UUID = UUID() // Unique identifier for the expense
let date: Date
let category: String
let amount: Double
let description: String? // Optional description
}
// Represents a budget for a particular category
struct Budget {
let category: String
var monthlyLimit: Double
}
// MARK: - Utility Functions
// Function to format a date into a user-friendly string
func formatDate(_ date: Date) -> String {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter.string(from: date)
}
// Function to parse a date string into a Date object
func parseDate(_ dateString: String) -> Date? {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd" // Define the expected date format
return formatter.date(from: dateString)
}
// Function to format a number as currency
func formatCurrency(_ amount: Double) -> String {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.currencyCode = "USD" // You can customize the currency
return formatter.string(from: NSNumber(value: amount)) ?? "Error"
}
// MARK: - Expense Tracker Class
class ExpenseTracker {
private var expenses: [Expense] = []
private var budgets: [Budget] = []
// Function to add an expense
func addExpense(date: Date, category: String, amount: Double, description: String? = nil) {
let newExpense = Expense(date: date, category: category, amount: amount, description: description)
expenses.append(newExpense)
}
// Function to get all expenses
func getAllExpenses() -> [Expense] {
return expenses
}
// Function to get expenses within a specific date range
func getExpenses(from startDate: Date, to endDate: Date) -> [Expense] {
return expenses.filter { expense in
expense.date >= startDate && expense.date <= endDate
}
}
// Function to get total expenses for a category
func getTotalExpenses(forCategory category: String, from startDate: Date? = nil, to endDate: Date? = nil) -> Double {
let filteredExpenses: [Expense]
if let startDate = startDate, let endDate = endDate {
filteredExpenses = expenses.filter { $0.category == category && $0.date >= startDate && $0.date <= endDate }
} else {
filteredExpenses = expenses.filter { $0.category == category }
}
return filteredExpenses.reduce(0) { (result, expense) in
result + expense.amount
}
}
// Function to set a budget for a category
func setBudget(category: String, amount: Double) {
if let index = budgets.firstIndex(where: { $0.category == category }) {
budgets[index].monthlyLimit = amount
} else {
let newBudget = Budget(category: category, monthlyLimit: amount)
budgets.append(newBudget)
}
}
// Function to get the budget for a category
func getBudget(forCategory category: String) -> Budget? {
return budgets.first { $0.category == category }
}
// Function to generate budget recommendations (AI-powered - simplified for example)
func getBudgetRecommendations() -> [String: Double] {
var recommendations: [String: Double] = [:]
// Very basic logic: Calculate average spending for each category
var categoryTotals: [String: Double] = [:]
for expense in expenses {
categoryTotals[expense.category, default: 0.0] += expense.amount
}
let numberOfMonths = 3 // Simulate historical data of 3 months for average
for (category, total) in categoryTotals {
let averageMonthlySpending = total / Double(numberOfMonths)
recommendations[category] = averageMonthlySpending * 1.1 // Suggest 10% more than average
}
// If no expenses, provide default budget recommendations
if recommendations.isEmpty {
recommendations = [
"Food": 300.0,
"Rent": 1200.0,
"Transportation": 150.0,
"Entertainment": 100.0,
"Other": 50.0
]
}
return recommendations
}
// Function to check if a category is over budget for the current month
func isOverBudget(category: String) -> Bool {
guard let budget = getBudget(forCategory: category) else {
return false // No budget set, so not over
}
let now = Date()
let calendar = Calendar.current
let startOfMonth = calendar.date(from: calendar.dateComponents([.year, .month], from: now))!
let endOfMonth = calendar.date(byAdding: DateComponents(month: 1, day: -1), to: startOfMonth)!
let expensesThisMonth = getTotalExpenses(forCategory: category, from: startOfMonth, to: endOfMonth)
return expensesThisMonth > budget.monthlyLimit
}
}
// MARK: - Example Usage
// Create an instance of the ExpenseTracker
let tracker = ExpenseTracker()
// Add some expenses
tracker.addExpense(date: parseDate("2024-01-15")!, category: "Food", amount: 50.0, description: "Lunch with friends")
tracker.addExpense(date: parseDate("2024-01-20")!, category: "Transportation", amount: 20.0, description: "Uber ride")
tracker.addExpense(date: parseDate("2024-02-05")!, category: "Food", amount: 30.0, description: "Groceries")
tracker.addExpense(date: parseDate("2024-02-10")!, category: "Entertainment", amount: 45.0, description: "Movie night")
tracker.addExpense(date: parseDate("2024-03-01")!, category: "Rent", amount: 1200.0, description: "Monthly Rent")
// Set a budget for Food
tracker.setBudget(category: "Food", amount: 200.0)
// Get the total expenses for Food
let totalFoodExpenses = tracker.getTotalExpenses(forCategory: "Food")
print("Total Food Expenses: \(formatCurrency(totalFoodExpenses))") // Output: Total Food Expenses: $80.00
// Get expenses from January 1st to January 31st
let startDate = parseDate("2024-01-01")!
let endDate = parseDate("2024-01-31")!
let expensesInJanuary = tracker.getExpenses(from: startDate, to: endDate)
print("\nExpenses in January:")
for expense in expensesInJanuary {
print("- \(formatDate(expense.date)): \(expense.category) - \(formatCurrency(expense.amount)) - \(expense.description ?? "No description")")
}
// Output:
// Expenses in January:
// - 2024-01-15: Food - $50.00 - Lunch with friends
// - 2024-01-20: Transportation - $20.00 - Uber ride
// Get budget recommendations
let budgetRecommendations = tracker.getBudgetRecommendations()
print("\nBudget Recommendations:")
for (category, amount) in budgetRecommendations {
print("- \(category): \(formatCurrency(amount))")
}
// Example Output (will vary depending on expense data):
// Budget Recommendations:
// - Food: $29.33
// - Transportation: $7.33
// - Entertainment: $16.50
// - Rent: $440.00
// Check if the "Food" category is over budget this month (assuming current date is in March)
let isFoodOverBudget = tracker.isOverBudget(category: "Food")
print("\nFood is over budget this month: \(isFoodOverBudget)") // Output: Food is over budget this month: false (because the budget is set and expenses haven't exceeded it for the current month).
// MARK: - Further Improvements and Considerations
/*
1. **Persistence:** Currently, the data is stored in memory and will be lost when the program terminates. Implement persistence using:
- `UserDefaults` (for very simple data)
- `Core Data` (for a more robust, database-backed solution)
- `Realm` (a mobile database)
- `Filesystem` (saving to a JSON or CSV file).
2. **User Interface (UI):** This is a console application. To make it user-friendly, you'd need to create a UI using:
- `SwiftUI` (modern, declarative UI framework)
- `UIKit` (older, imperative UI framework)
3. **Error Handling:** Add more robust error handling:
- Use `try-catch` blocks for potential errors (e.g., parsing dates, file operations).
- Provide meaningful error messages to the user.
4. **Data Validation:** Validate user input (e.g., ensure amounts are positive numbers, dates are in the correct format).
5. **More Advanced AI/Machine Learning:** The `getBudgetRecommendations()` function provides a very basic example. To make it truly AI-powered, you could:
- Use machine learning libraries (e.g., Create ML, Core ML) to train a model on historical expense data.
- The model could predict future spending based on past trends, seasonality, and other factors.
- Consider external APIs for financial data analysis and forecasting.
6. **Reporting:** Generate reports on spending patterns, budget variances, and other financial metrics.
7. **Security:** If you're storing sensitive financial data, implement appropriate security measures (e.g., encryption, secure storage). Be very careful with any personally identifiable information (PII).
8. **Currency Conversion:** Support multiple currencies.
9. **Recurring Expenses:** Handle recurring expenses (e.g., rent, subscriptions).
10. **Categorization:** Implement a more sophisticated categorization system, perhaps using machine learning to automatically categorize expenses based on descriptions.
11. **Data Visualization:** Create charts and graphs to visualize spending patterns and budget performance.
*/
```
Key improvements and explanations:
* **Clear Structure:** The code is organized into distinct sections: data structures, utility functions, the `ExpenseTracker` class, and example usage. This improves readability and maintainability.
* **Data Structures:** The `Expense` and `Budget` structs provide a clear representation of the data. The `Expense` now has a UUID for unique identification.
* **Date Handling:** Includes `formatDate` and `parseDate` functions to handle date formatting and parsing consistently, and validates the result of parsing. This is *crucial* because date formatting can be tricky.
* **Currency Formatting:** The `formatCurrency` function provides a consistent way to format currency values. It's customizable (currency code can be changed).
* **ExpenseTracker Class:**
* **`addExpense()`:** Adds a new expense to the tracker.
* **`getAllExpenses()`:** Returns all expenses.
* **`getExpenses(from:to:)`:** Filters expenses within a date range.
* **`getTotalExpenses(forCategory:)`:** Calculates the total expenses for a given category (with optional date range). Handles optional date ranges correctly.
* **`setBudget()`:** Sets a budget for a category (updates if it already exists).
* **`getBudget()`:** Retrieves the budget for a category.
* **`getBudgetRecommendations()`:** A *simplified* "AI-powered" budget recommendation function. It calculates the average spending for each category and suggests a budget that is slightly higher. *Important:* This is a very basic example. True AI-powered budget recommendations would require much more sophisticated techniques (machine learning). It also provides default recommendations if no data exists.
* **`isOverBudget()`:** Checks if a category is over budget for the current month. This is a *critical* addition. It uses the current month and dynamically determines the start and end dates.
* **Example Usage:** Demonstrates how to use the `ExpenseTracker` class. It adds expenses, sets a budget, retrieves expenses, calculates totals, and gets budget recommendations. The example also checks for a category being over budget.
* **Comments:** The code is well-commented to explain the purpose of each function and variable.
* **Further Improvements:** Includes a detailed section on potential improvements, covering persistence, UI, error handling, AI/machine learning, reporting, security, and more. This is important for guiding further development.
How to Run:
1. **Save:** Save the code as a `.swift` file (e.g., `expense_tracker.swift`).
2. **Compile and Run:** Open your terminal or command prompt and navigate to the directory where you saved the file. Then, compile and run the code using:
```bash
swift expense_tracker.swift
```
This will execute the Swift code and print the output to the console.
This improved version provides a solid foundation for building a more complete AI-powered expense tracker and budget recommendation tool in Swift. Remember to address the "Further Improvements" section as you continue developing the application. Specifically focus on how to store data persistently (CoreData, Realm, JSON files) and create a user interface (SwiftUI). The AI/ML aspect requires external libraries or frameworks and is a substantial undertaking.
👁️ Viewed: 5
Comments