diff --git a/app/src/main/java/com/ivy/wallet/logic/csv/CSVImporter.kt b/app/src/main/java/com/ivy/wallet/logic/csv/CSVImporter.kt index 31d4c04792..96fd4e540d 100644 --- a/app/src/main/java/com/ivy/wallet/logic/csv/CSVImporter.kt +++ b/app/src/main/java/com/ivy/wallet/logic/csv/CSVImporter.kt @@ -171,14 +171,18 @@ class CSVImporter( val dateTime = mapDate( - if (rowMapping.timeOnly != null) { + rowMapping = rowMapping, + dateString = if (rowMapping.timeOnly != null) { // date and time are separated in csv, join them with space row.extract(rowMapping.date) + " " + row.extract(rowMapping.timeOnly) } else { row.extract(rowMapping.date) } ) - val dueDate = mapDate(row.extract(rowMapping.dueDate)) + val dueDate = mapDate( + rowMapping = rowMapping, + dateString = row.extract(rowMapping.dueDate) + ) if (dateTime == null && dueDate == null) { //Cannot save transactions without any date return null @@ -241,9 +245,11 @@ class CSVImporter( normalizedType.contains("income") -> TransactionType.INCOME normalizedType.contains("expense") -> TransactionType.EXPENSE normalizedType.contains("transfer") -> TransactionType.TRANSFER - // Default to Expense because Financisto messed up its CSV Export - // and mixes it with another (ignored) column - else -> TransactionType.EXPENSE + else -> { + // Default to Expense because Financisto messed up its CSV Export + // and mixes it with another (ignored) column + if (rowMapping.defaultTypeToExpense) TransactionType.EXPENSE else null + } } } @@ -255,9 +261,28 @@ class CSVImporter( .toDoubleOrNull() } - private fun mapDate(dateString: String?): LocalDateTime? { + private fun mapDate( + rowMapping: RowMapping, + dateString: String? + ): LocalDateTime? { if (dateString == null || dateString.isBlank()) return null + if (rowMapping.dateOnlyFormat != null) { + try { + return dateString.parseDateOnly(rowMapping.dateOnlyFormat) + } catch (e: Exception) { + e.printStackTrace() + } + } + + if (rowMapping.dateTimeFormat != null) { + try { + return dateString.parseDateTime(rowMapping.dateTimeFormat) + } catch (e: Exception) { + e.printStackTrace() + } + } + val supportedPatterns = listOf( "dd/MM/yyyy HH:mm", "dd/MM/yyyy HH:mm:ss", @@ -316,10 +341,7 @@ class CSVImporter( for (pattern in supportedPatterns) { try { - return LocalDateTime.parse( - dateString, - DateTimeFormatter.ofPattern(pattern) - ).convertLocalToUTC() + return dateString.parseDateTime(dateTimeFormat = pattern) } catch (e: Exception) { } } @@ -333,11 +355,7 @@ class CSVImporter( for (pattern in supportedDateOnlyPatterns) { try { - return LocalDate.parse( - dateString, - DateTimeFormatter.ofPattern(pattern) - ).atTime(12, 0) - .convertLocalToUTC() + return dateString.parseDateOnly(dateFormat = pattern) } catch (e: Exception) { } } @@ -367,6 +385,24 @@ class CSVImporter( .minusYears(1) } + private fun String.parseDateOnly( + dateFormat: String + ): LocalDateTime { + return LocalDate.parse( + this, + DateTimeFormatter.ofPattern(dateFormat) + ).atTime(12, 0).convertLocalToUTC() + } + + private fun String.parseDateTime( + dateTimeFormat: String + ): LocalDateTime { + return LocalDateTime.parse( + this, + DateTimeFormatter.ofPattern(dateTimeFormat) + ).convertLocalToUTC() + } + private fun mapAccount( baseCurrency: String, accountNameString: String?, diff --git a/app/src/main/java/com/ivy/wallet/logic/csv/CSVMapper.kt b/app/src/main/java/com/ivy/wallet/logic/csv/CSVMapper.kt index 5a145a9c12..13b66caa67 100644 --- a/app/src/main/java/com/ivy/wallet/logic/csv/CSVMapper.kt +++ b/app/src/main/java/com/ivy/wallet/logic/csv/CSVMapper.kt @@ -21,7 +21,7 @@ class CSVMapper { ImportType.MONEY_MANAGER -> moneyManager() ImportType.WALLET_BY_BUDGET_BAKERS -> walletByBudgetBakers() ImportType.SPENDEE -> spendee() - ImportType.MONEFY -> TODO() + ImportType.MONEFY -> monefy() ImportType.ONE_MONEY -> oneMoney() ImportType.BLUE_COINS -> blueCoins() ImportType.KTW_MONEY_MANAGER -> ktwMoneyManager() @@ -124,6 +124,26 @@ class CSVMapper { title = 6 ) + private fun monefy() = RowMapping( + date = 0, + dateOnlyFormat = "dd/MM/yyyy", + account = 1, + category = 2, + amount = 3, + accountCurrency = 4, + //converted amount = 5 + //currency = 6 + title = 7, + defaultTypeToExpense = true, //Monefy doesn't have transaction type, it uses amount +/- sign, + + transformTransaction = { transaction, _, csvAmount -> + //Monefy doesn't have transaction type, it uses amount +/- sign + transaction.copy( + type = if (csvAmount > 0) TransactionType.INCOME else TransactionType.EXPENSE + ) + } + ) + private fun oneMoney() = RowMapping( date = 0, type = 1, @@ -189,6 +209,7 @@ class CSVMapper { // parent transaction = 8 title = 9, type = 10, + defaultTypeToExpense = true, // project = 11 description = 12, diff --git a/app/src/main/java/com/ivy/wallet/logic/csv/model/RowMapping.kt b/app/src/main/java/com/ivy/wallet/logic/csv/model/RowMapping.kt index 17a15c70ab..9fdd0bf250 100644 --- a/app/src/main/java/com/ivy/wallet/logic/csv/model/RowMapping.kt +++ b/app/src/main/java/com/ivy/wallet/logic/csv/model/RowMapping.kt @@ -5,6 +5,7 @@ import com.ivy.wallet.model.entity.Transaction data class RowMapping( val type: Int? = null, + val defaultTypeToExpense: Boolean = false, val amount: Int, val account: Int, @@ -14,6 +15,8 @@ data class RowMapping( val accountIcon: Int? = null, val date: Int, + val dateOnlyFormat: String? = null, + val dateTimeFormat: String? = null, val timeOnly: Int? = null, val dueDate: Int? = null,