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

Commit

Permalink
Merge pull request #219 from ILIYANGERMANOV/import-csv-monefy
Browse files Browse the repository at this point in the history
Import csv monefy
  • Loading branch information
ILIYANGERMANOV authored Dec 7, 2021
2 parents cd9fffb + 2147a0d commit b1b30aa
Show file tree
Hide file tree
Showing 16 changed files with 150 additions and 111 deletions.
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

0 comments on commit b1b30aa

Please sign in to comment.