Skip to content

Commit

Permalink
Created csv file and showed payment/expenses proper data
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-nirali-s committed Jan 17, 2025
1 parent f1260f0 commit 71feb02
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 28 deletions.
7 changes: 7 additions & 0 deletions Data/Data/Extension/Date+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ public extension Date {
return dateFormatter.string(from: self)
}

// 13-12-2001
var numericDate: String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy"
return dateFormatter.string(from: self)
}

var millisecondsSince1970: Int {
Int((self.timeIntervalSince1970 * 1000.0).rounded())
}
Expand Down
18 changes: 9 additions & 9 deletions Splito/UI/Home/Groups/Group/GroupExpenseListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ struct GroupExpenseListView: View {
GeometryReader { geometry in
ScrollViewReader { scrollProxy in
VStack(alignment: .leading, spacing: 0) {
GroupOptionsListView(showShareSheet: $viewModel.showShareSheet, showExportOptions: $viewModel.showExportOptions,
isSettleUpEnable: (!viewModel.memberOwingAmount.isEmpty && viewModel.group?.members.count ?? 1 > 1),
onSettleUpTap: viewModel.handleSettleUpBtnTap,
onTransactionsTap: viewModel.handleTransactionsBtnTap,
onBalanceTap: viewModel.handleBalancesBtnTap,
onTotalsTap: viewModel.handleTotalBtnTap,
onExportTap: { exportOption, completion in
viewModel.handleExportTap(exportOption: exportOption, completion: completion)
})
GroupOptionsListView(
showShareSheet: $viewModel.showShareSheet, showExportOptions: $viewModel.showExportOptions,
isSettleUpEnable: (!viewModel.memberOwingAmount.isEmpty && viewModel.group?.members.count ?? 1 > 1),
generatedReportURL: viewModel.generatedReportURL, onSettleUpTap: viewModel.handleSettleUpBtnTap,
onTransactionsTap: viewModel.handleTransactionsBtnTap, onBalanceTap: viewModel.handleBalancesBtnTap,
onTotalsTap: viewModel.handleTotalBtnTap, onExportTap: { exportOption, completion in
viewModel.handleExportTap(exportOption: exportOption, completion: completion)
}
)

if viewModel.showSearchBar {
SearchBar(text: $viewModel.searchedExpense, isFocused: isFocused, placeholder: "Search expenses")
Expand Down
31 changes: 18 additions & 13 deletions Splito/UI/Home/Groups/Group/GroupHomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ struct GroupOptionsListView: View {
@Binding var showExportOptions: Bool

let isSettleUpEnable: Bool
let generatedReportURL: URL?

let onSettleUpTap: () -> Void
let onTransactionsTap: () -> Void
Expand All @@ -152,24 +153,28 @@ struct GroupOptionsListView: View {
GroupOptionsButtonView(text: "Export") {
showExportOptions = true
}
}
.padding([.horizontal, .bottom], 16)
.padding(.top, 24)
}
.confirmationDialog("", isPresented: $showExportOptions, titleVisibility: .hidden) {
ForEach(ExportOptions.allCases, id: \.self) { option in
Button(option.option.localized) {
showExportOptions = false
onExportTap(option) { _ in
showShareSheet = true
.confirmationDialog("", isPresented: $showExportOptions, titleVisibility: .hidden) {
ForEach(ExportOptions.allCases, id: \.self) { option in
Button(option.option.localized) {
showExportOptions = false
onExportTap(option) { isSucceed in
if isSucceed {
showShareSheet = true
}
}
}
}
}
}
.padding([.horizontal, .bottom], 16)
.padding(.top, 24)
}
.sheet(isPresented: $showShareSheet) {
ShareSheetView(activityItems: [""]) { isCompleted in
if isCompleted {
showShareSheet = false
if let fileURL = generatedReportURL {
ShareSheetView(activityItems: [fileURL]) { isCompleted in
if isCompleted {
showShareSheet = false
}
}
}
}
Expand Down
13 changes: 7 additions & 6 deletions Splito/UI/Home/Groups/Group/GroupHomeViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,33 @@ class GroupHomeViewModel: BaseViewModel, ObservableObject {
@Inject var expenseRepository: ExpenseRepository
@Inject var transactionRepository: TransactionRepository

@Published var group: Groups?
@Published var generatedReportURL: URL?
@Published private(set) var groupId: String

@Published var transactionsCount: Int = 0
@Published private(set) var overallOwingAmount: Double = 0.0
@Published private(set) var currentMonthSpending: Double = 0.0

@Published var group: Groups?
@Published var groupState: GroupState = .loading

@Published var expenses: [Expense] = []
@Published var expensesWithUser: [ExpenseWithUser] = []
@Published var transactionsCount: Int = 0
@Published private(set) var memberOwingAmount: [String: Double] = [:]
@Published private(set) var groupExpenses: [String: [ExpenseWithUser]] = [:]


@Published var showSearchBar = false
@Published var showShareSheet = false
@Published var showSettleUpSheet = false
@Published var showBalancesSheet = false
@Published var showExportOptions = false
@Published var showScrollToTopBtn = false
@Published var showGroupTotalSheet = false
@Published var showAddExpenseSheet = false
@Published var showTransactionsSheet = false
@Published var showSimplifyInfoSheet = false
@Published var showInviteMemberSheet = false

@Published var showSearchBar = false
@Published var showScrollToTopBtn = false

@Published var searchedExpense: String = "" {
didSet {
updateGroupExpenses()
Expand Down
76 changes: 76 additions & 0 deletions Splito/UI/Home/Groups/Group/GroupHomeViewModelExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ extension GroupHomeViewModel {
let transactions = try await transactionRepository.fetchTransactions(groupId: groupId, startDate: startDate, endDate: today)
print("xxx \(expenses.count) \(transactions.count)")
LogD("GroupHomeViewModel: \(#function) Expenses/payments fetched successfully.")
if let reportURL = generateCSVReport(expenses: expenses, payments: transactions) {
self.generatedReportURL = reportURL // Store the file URL
completion(true)
} else {
completion(false)
}
completion(true)
} catch {
LogE("GroupHomeViewModel: \(#function) Failed to fetch Expenses/payments: \(error).")
Expand All @@ -93,6 +99,76 @@ extension GroupHomeViewModel {
}
}

func generateCSVReport(expenses: [Expense], payments: [Transactions]) -> URL? {
guard let group else { return nil }

var csvContent = ""

// Add Expenses Section
csvContent += "Expenses\n"

let memberNames = group.members.map { getMemberDataBy(id: $0)?.nameWithLastInitial ?? "Unknown" }
let header = "Date, Description, Category, Cost, Currency, \(memberNames.joined(separator: ", "))\n\n"
csvContent += header

for expense in expenses {
let date = expense.date.dateValue().numericDate
var expenseRow = "\(date), \(expense.name), \(expense.category ?? "General"), \(expense.amount), \(expense.currencyCode ?? "INR")"

// Add owe amounts for each group member
for member in group.members {
let oweAmount = expense.getCalculatedSplitAmountOf(member: member)
expenseRow += ", \(oweAmount)"
}

csvContent += expenseRow + "\n"
}
csvContent += "\n"

// Add Settlements Section
csvContent += "Settlements\n"
for payment in payments {
let date = payment.date.dateValue().numericDate
let payer = getMemberDataBy(id: payment.payerId)?.nameWithLastInitial ?? "Unknown"
let receiver = getMemberDataBy(id: payment.receiverId)?.nameWithLastInitial ?? "Unknown"
var paymentRow = "\(date), \(payer) paid \(receiver), Payment, \(payment.amount), INR"

// Add owe amounts for each group member
for member in group.members {
let amount = member == payment.payerId ? payment.amount : (member == payment.receiverId) ? -payment.amount : 0.00
paymentRow += ", \(amount)"
}

csvContent += paymentRow + "\n"
}
csvContent += "\n"

// Add Total balance Section
let date = Date().numericDate
csvContent += "\(date), Total balance, , , INR"

for member in group.members {
// Find the balance for the current member
if let memberBalance = group.balances.first(where: { $0.id == member }) {
csvContent += ", \(memberBalance.balance)"
} else {
csvContent += ", 0.00" // Default to 0 if no balance is found
}
}

// Save the file to the temporary directory
let fileName = "Group_Report.csv"
let filePath = FileManager.default.temporaryDirectory.appendingPathComponent(fileName)

do {
try csvContent.write(to: filePath, atomically: true, encoding: .utf8)
return filePath
} catch {
LogE("GroupHomeViewModel: \(#function) Failed to write CSV file: \(error)")
return nil
}
}

func handleSimplifyInfoSheet() {
UIApplication.shared.endEditing()
showSimplifyInfoSheet = true
Expand Down

0 comments on commit 71feb02

Please sign in to comment.