Skip to content

Commit

Permalink
Added Helper function to escape CSV text
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-nirali-s committed Jan 17, 2025
1 parent 33df125 commit 38a5a34
Showing 1 changed file with 24 additions and 10 deletions.
34 changes: 24 additions & 10 deletions Splito/UI/Home/Groups/Group/GroupHomeViewModelExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,20 @@ extension GroupHomeViewModel {
func handleExportOptionSelection(option: ExportOptions) {
let startDate = getStartDate(exportOption: option)
let today = Date()

exportTask?.cancel()
exportTask = Task { [weak self] in
guard let self else { return }
do {
let expenses = try await self.expenseRepository.fetchExpenses(groupId: self.groupId, startDate: startDate, endDate: today)
let transactions = try await self.transactionRepository.fetchTransactions(groupId: self.groupId, startDate: startDate, endDate: today)
LogD("GroupHomeViewModel: \(#function) Expenses/payments fetched successfully.")

if expenses.isEmpty && transactions.isEmpty {
self.showToastFor(toast: ToastPrompt(type: .info, title: "No Data", message: "No data found for selected time period. Try a different time period."))
return
}

if let reportURL = await self.generateCSVReport(expenses: expenses, payments: transactions) {
groupReportUrl = reportURL
showShareReportSheet = true
Expand Down Expand Up @@ -127,11 +127,14 @@ extension GroupHomeViewModel {
for id in allMemberIDs {
let user = await fetchMemberData(for: id)
let name = user?.nameWithLastInitial ?? "Unknown"
memberNames.append(!group.members.contains(id) ? "\(name) (Removed)" : name)
memberNames.append(escapeCSV(!group.members.contains(id) ? "\(name) (Removed)" : name))
}

var csvContent = ""
let header = "Date, Description, Category, Cost, Currency, \(memberNames.joined(separator: ", "))\n\n"
let headers = ["Date", "Description", "Category", "Cost", "Currency"]
.map(escapeCSV)
.joined(separator: ",")
let header = headers + "," + memberNames.joined(separator: ",") + "\n\n"

csvContent += header
csvContent += createExpensesSection(expenses: expenses, allMemberIDs: allMemberIDs)
Expand All @@ -140,6 +143,7 @@ extension GroupHomeViewModel {

do {
let filePath = FileManager.default.temporaryDirectory.appendingPathComponent(GROUP_REPORT_FILE_NAME)
try FileManager.default.createDirectory(at: filePath.deletingLastPathComponent(), withIntermediateDirectories: true)
try csvContent.write(to: filePath, atomically: true, encoding: .utf8)
return filePath
} catch {
Expand All @@ -148,11 +152,20 @@ extension GroupHomeViewModel {
}
}

// Helper function to escape CSV text
private func escapeCSV(_ text: String) -> String {
// If text contains comma, quote, or newline, wrap in quotes and escape existing quotes
if text.contains(",") || text.contains("\"") || text.contains("\n") {
return "\"\(text.replacingOccurrences(of: "\"", with: "\"\""))\""
}
return text
}

private func createExpensesSection(expenses: [Expense], allMemberIDs: Set<String>) -> String {
var section = "Expenses\n"
var section = escapeCSV("Expenses") + "\n"
for expense in expenses {
let date = expense.date.dateValue().numericDate
var row = "\(date), \(expense.name), \(expense.category ?? "General"), \(expense.amount), \(expense.currencyCode ?? "INR")"
var row = "\(escapeCSV(date)), \(escapeCSV(expense.name)), \(escapeCSV(expense.category ?? "General")), \(expense.amount), \(escapeCSV(expense.currencyCode ?? "INR"))"

// Add owe amounts for each member
for member in allMemberIDs {
Expand All @@ -165,12 +178,13 @@ extension GroupHomeViewModel {
}

private func createSettlementsSection(payments: [Transactions], allMemberIDs: Set<String>, group: Groups) -> String {
var section = "Settlements\n"
var section = escapeCSV("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 row = "\(date), \(payer) paid \(receiver), Payment, \(payment.amount), INR"
let description = "\(escapeCSV(payer)) paid \(escapeCSV(receiver))"
var row = "\(escapeCSV(date)), \(description), Payment, \(payment.amount), INR"

// Add paid amount for payer & receiver
for member in allMemberIDs {
Expand All @@ -184,7 +198,7 @@ extension GroupHomeViewModel {

private func createTotalBalanceSection(group: Groups, allMemberIDs: Set<String>) -> String {
let date = Date()
var section = "\(date.numericDate), Total balance, , , INR"
var section = "\(escapeCSV(date.numericDate)), Total balance, , , INR"

for member in allMemberIDs {
if let memberBalance = group.balances.first(where: { $0.id == member }) {
Expand Down

0 comments on commit 38a5a34

Please sign in to comment.