Skip to content
This repository has been archived by the owner on Nov 5, 2024. It is now read-only.

Import csv monefy #219

Merged
merged 6 commits into from
Dec 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 27 additions & 35 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
## Pull Request (PR) Checklist

Please check if your pull request fulfills the following requirements:

- [ ] The PR is submitted to the `develop` branch.
- [ ] I've read the **[Contribution Guidelines](https://github.com/ILIYANGERMANOV/ivy-wallet/blob/main/CONTRIBUTING.md)**.
- [ ] The code builds and is tested on an actual Android device.
Expand All @@ -12,41 +10,16 @@ Please check if your pull request fulfills the following requirements:
_Important: Don't worry if you experience flaky UI tests. Just re-run the failed ones again and if they pass => it's all good!_

_Put an `x` in the boxes that apply._

- [x] Demo: Checking checkbox using `[x]`

### How to run Ivy Wallet's UI tests (`androidTest`)

**Connect Android Emulator**
- Pixel 5 API 29+ AVD emulator _(recommended)_
- Pixel 3XL API 29+ AVD emulator _(recommended)_
- Large screen physical device _(might also work)_

**Method 1: Android Studio UI**
- Find `com (androidTest)` package
- Right click
- `Run 'Tests in 'com''`

_Note: If you've checked "Compact Middle Packages" the option will appear as `com.ivy.wallet (androidTest)`._

**Method 2: Gradle Wrapper**
- `chmod +x gradlew` (Linux)
- `./gradlew connectedDebugAndroidTest`

**Method 3: Fastlane**
- Install Ruby 2.7
- `bundle install`
- `bundle exec fastlane ui_tests`

## Pull Request Type

Please check the type of change your PR introduces:

- [ ] Bugfix
- [ ] Feature
- [ ] Code style update (formatting, renaming)
- [ ] Refactoring (no functional changes)
- [ ] Small update (fix typo, UI fine-tune, change color or something small)
- [ ] Small improvement (fix typo, UI fine-tune, change color or something small)
- [ ] Gradle Build related changes
- [ ] Dependencies update (updating libraries)
- [ ] Documentation
Expand All @@ -55,18 +28,37 @@ Please check the type of change your PR introduces:

_Put an `x` in the boxes that apply._

## Does this PR closes any GitHub Issues?

## Does this PR closes any GitHub Issues?
Check **[Ivy Wallet Issues](https://github.com/ILIYANGERMANOV/ivy-wallet/issues)**.

- Closes #N/A (type issue number here)

## What's changed?

## What's changed?
Describe with a few bullets **what's new:**
- a
- b
- c
- d

## How to run Ivy Wallet's UI tests (`androidTest`)
**Connect Android Emulator**
- Pixel 5 API 29+ AVD emulator _(recommended)_
- Pixel 3XL API 29+ AVD emulator _(recommended)_
- Large screen physical device _(might also work)_

**Method 1: Android Studio UI**
- Find `com (androidTest)` package
- Right click
- `Run 'Tests in 'com''`

_Note: If you've checked "Compact Middle Packages" the option will appear as `com.ivy.wallet (androidTest)`._

-
-
-
**Method 2: Gradle Wrapper**
- `chmod +x gradlew` (Linux)
- `./gradlew connectedDebugAndroidTest`

_This PR template style was inspired by [ionic-framework](https://github.com/ionic-team/ionic-framework/blob/main/.github/PULL_REQUEST_TEMPLATE.md)._
**Method 3: Fastlane**
- Install Ruby 2.7
- `bundle install`
- `bundle exec fastlane ui_tests`
66 changes: 51 additions & 15 deletions app/src/main/java/com/ivy/wallet/logic/csv/CSVImporter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
}
}

Expand All @@ -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",
Expand Down Expand Up @@ -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) {
}
}
Expand All @@ -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) {
}
}
Expand Down Expand Up @@ -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?,
Expand Down
26 changes: 24 additions & 2 deletions app/src/main/java/com/ivy/wallet/logic/csv/CSVMapper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ class CSVMapper {
ivyMappingV1()
}
}
ImportType.MONEY_MANAGER_PRASE -> moneyManagerPrase()
ImportType.MONEY_MANAGER -> moneyManager()
ImportType.WALLET_BY_BUDGET_BAKERS -> walletByBudgetBakers()
ImportType.SPENDEE -> spendee()
ImportType.MONEFY -> monefy()
ImportType.ONE_MONEY -> oneMoney()
ImportType.BLUE_COINS -> blueCoins()
ImportType.KTW_MONEY_MANAGER -> ktwMoneyManager()
Expand Down Expand Up @@ -74,7 +75,7 @@ class CSVMapper {
)

//Praseto - https://play.google.com/store/apps/details?id=com.realbyteapps.moneymanagerfree&hl=en&gl=US
private fun moneyManagerPrase() = RowMapping(
private fun moneyManager() = RowMapping(
type = 6,
amount = 8,
account = 1,
Expand Down Expand Up @@ -123,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,
Expand Down Expand Up @@ -188,6 +209,7 @@ class CSVMapper {
// parent transaction = 8
title = 9,
type = 10,
defaultTypeToExpense = true,
// project = 11
description = 12,

Expand Down
33 changes: 17 additions & 16 deletions app/src/main/java/com/ivy/wallet/logic/csv/model/ImportType.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import com.ivy.wallet.ui.theme.*

enum class ImportType {
IVY,
MONEY_MANAGER_PRASE,
MONEY_MANAGER,
WALLET_BY_BUDGET_BAKERS,
SPENDEE,
MONEFY,
ONE_MONEY,
BLUE_COINS,
KTW_MONEY_MANAGER,
Expand All @@ -20,9 +21,10 @@ enum class ImportType {

fun color(): Color = when (this) {
IVY -> Ivy
MONEY_MANAGER_PRASE -> Red
MONEY_MANAGER -> Red
WALLET_BY_BUDGET_BAKERS -> Green
SPENDEE -> RedLight
MONEFY -> Green
ONE_MONEY -> Red3
BLUE_COINS -> Blue
KTW_MONEY_MANAGER -> Yellow
Expand All @@ -32,9 +34,10 @@ enum class ImportType {

fun appId(): String = when (this) {
IVY -> "com.ivy.wallet"
MONEY_MANAGER_PRASE -> "com.realbyteapps.moneymanagerfree"
MONEY_MANAGER -> "com.realbyteapps.moneymanagerfree"
WALLET_BY_BUDGET_BAKERS -> "com.droid4you.application.wallet"
SPENDEE -> "com.cleevio.spendee"
MONEFY -> "com.monefy.app.lite"
ONE_MONEY -> "org.pixelrush.moneyiq"
BLUE_COINS -> "com.rammigsoftware.bluecoins"
KTW_MONEY_MANAGER -> "com.ktwapps.walletmanager"
Expand All @@ -44,10 +47,11 @@ enum class ImportType {

@DrawableRes
fun logo(): Int = when (this) {
IVY -> R.drawable.ivy_wallet_logo_import
MONEY_MANAGER_PRASE -> R.drawable.ic_money_manager_prase
IVY -> R.drawable.ivywallet_logo
MONEY_MANAGER -> R.drawable.moneymanager_logo
WALLET_BY_BUDGET_BAKERS -> R.drawable.wallet_by_budgetbakers_logo
SPENDEE -> R.drawable.speende_logo_png
SPENDEE -> R.drawable.spendee_logo
MONEFY -> R.drawable.monefy_logo
ONE_MONEY -> R.drawable.one_money_logo
BLUE_COINS -> R.drawable.bluecoins
KTW_MONEY_MANAGER -> R.drawable.ktw_money_manager_logo
Expand All @@ -57,9 +61,10 @@ enum class ImportType {

fun listName(): String = when (this) {
IVY -> "Ivy Wallet CSV"
MONEY_MANAGER_PRASE -> "Money Manager"
MONEY_MANAGER -> "Money Manager"
WALLET_BY_BUDGET_BAKERS -> "Wallet by BudgetBakers"
SPENDEE -> "Spendee"
MONEFY -> "Monefy"
ONE_MONEY -> "1Money"
BLUE_COINS -> "Bluecoins Finance"
KTW_MONEY_MANAGER -> "Money Manager (KTW)"
Expand All @@ -69,14 +74,7 @@ enum class ImportType {

fun appName(): String = when (this) {
IVY -> "Ivy Wallet"
MONEY_MANAGER_PRASE -> "Money Manager"
WALLET_BY_BUDGET_BAKERS -> "Wallet by BudgetBakers"
SPENDEE -> "Spendee"
ONE_MONEY -> "1Money"
BLUE_COINS -> "Bluecoins Finance"
KTW_MONEY_MANAGER -> "Money Manager (KTW)"
FORTUNE_CITY -> "Fortune City"
FINANCISTO -> "Financisto"
else -> listName()
}

@Composable
Expand All @@ -89,7 +87,7 @@ enum class ImportType {
onUploadClick = onUploadClick
)
}
MONEY_MANAGER_PRASE -> {
MONEY_MANAGER -> {
MoneyManagerPraseSteps(
onUploadClick = onUploadClick
)
Expand All @@ -102,6 +100,9 @@ enum class ImportType {
SPENDEE -> SpendeeSteps(
onUploadClick = onUploadClick
)
MONEFY -> MonefySteps(
onUploadClick = onUploadClick
)
ONE_MONEY -> OneMoneySteps(
onUploadClick = onUploadClick
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ private fun Preview() {
IvyAppPreview {
ImportInstructions(
hasSkip = true,
importType = ImportType.MONEY_MANAGER_PRASE,
importType = ImportType.MONEY_MANAGER,
onSkip = {}
) {

Expand Down
Loading