Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import Foundation
- struct Transaction: Identifiable, Decodable, Hashable, Sendable {
- let id: Int
- let date: String
- let institution: String
- let account: String
- var merchant: String
- let amount: Double
- let type: TransactionType.RawValue
- var categoryId: Int
- var category: String
- let isPending: Bool
- var isTransfer: Bool
- var isExpense: Bool
- var isEdited: Bool
- var dateParsed: Date {
- date.dateParsed()
- }
- var month: String {
- dateParsed.formatted(.dateTime.year().month(.wide))
- }
- var signedAmount: Double {
- return type == TransactionType.credit.rawValue ? amount : -amount
- }
- }
- enum TransactionType: String {
- case debit = "debit"
- case credit = "credit"
- }
- struct Category {
- let id: Int
- let name: String
- var mainCategoryId: Int?
- }
- import Foundation
- typealias TransactionPrefixSum = [(String, Double)]
- final class TransactionListViewModel: ObservableObject {
- static let transactionsURL = "https://designcode.io/data/transactions.json"
- var transactions: [Transaction] = []
- init() {
- Task {
- transactions = try await getTransactions()
- }
- }
- func getTransactions() async throws -> [Transaction] {
- guard let url = URL(string: TransactionListViewModel.transactionsURL) else {
- print("Invalid URL")
- return []
- }
- do {
- let (data, response) = try await URLSession.shared.data(from: url)
- guard let httpResponse = response as? HTTPURLResponse,
- (200...299).contains(httpResponse.statusCode) else {
- print("Error making request: ", (response as! HTTPURLResponse).statusCode)
- return []
- }
- return try JSONDecoder().decode([Transaction].self, from: data)
- } catch {
- print("Error: ", error)
- return []
- }
- }
- func accumulateTransactions() async -> TransactionPrefixSum {
- if transactions.isEmpty {
- transactions = try! await getTransactions()
- }
- let today = "02/17/2022".dateParsed()
- let dateInterval = Calendar.current.dateInterval(of: .month, for: today)!
- var sum: Double = .zero
- var cumulativeSum = TransactionPrefixSum()
- for date in stride(from: dateInterval.start, to: today, by: 60 * 60 * 24) {
- let dailyExpenses = transactions.filter { $0.dateParsed == date && $0.isExpense }
- let dailyTotal = dailyExpenses.reduce(0) { $0 - $1.signedAmount }
- sum += dailyTotal
- cumulativeSum.append((date.formatted(), sum))
- }
- return cumulativeSum
- }
- }
- extension String {
- func dateParsed() -> Date {
- guard let parsedDate = DateFormatter.allNumericUSA.date(from: self) else { return Date() }
- return parsedDate
- }
- }
- extension DateFormatter {
- static let allNumericUSA: DateFormatter = {
- // print("Initializing DateFormatter")
- let formatter = DateFormatter()
- formatter.dateFormat = "MM/dd/yyyy"
- return formatter
- }()
- }
- let transactionsViewModel = TransactionListViewModel()
- Task {
- let transactions = await transactionsViewModel.accumulateTransactions()
- print(transactions)
- }
Advertisement
Add Comment
Please, Sign In to add comment