From baf755c4c856eed37f61ca072d4aaebcaff4caaa Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 10 Oct 2022 16:54:53 +0200 Subject: [PATCH] Adds bankroll transfer --- .../android/PokerAnalyticsApplication.kt | 4 +- .../calculus/bankroll/BankrollCalculator.kt | 28 ++++++++--- .../calculus/bankroll/BankrollReport.kt | 2 +- .../android/model/migrations/Patcher.kt | 38 ++------------ .../migrations/PokerAnalyticsMigration.kt | 12 +++++ .../android/model/realm/Bankroll.kt | 6 +++ .../android/model/realm/Transaction.kt | 50 +++++++++++++++---- .../android/model/realm/TransactionType.kt | 5 +- .../bottomsheet/BottomSheetFragment.kt | 2 +- .../modules/data/TransactionDataFragment.kt | 38 +++++++++++--- .../android/ui/view/TransactionRowView.kt | 9 +++- .../ui/view/rows/TransactionPropertiesRow.kt | 24 +++++++-- .../android/util/Preferences.kt | 2 +- .../android/util/csv/ProductCSVDescriptors.kt | 7 ++- .../android/util/csv/SessionField.kt | 18 +++++++ .../util/csv/TransactionCSVDescriptor.kt | 27 +++++++++- .../util/extensions/RealmExtensions.kt | 12 +++-- app/src/main/res/values/strings.xml | 2 + 18 files changed, 206 insertions(+), 80 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt b/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt index 5c138a88..e77f8e48 100644 --- a/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt +++ b/app/src/main/java/net/pokeranalytics/android/PokerAnalyticsApplication.kt @@ -12,8 +12,8 @@ import kotlinx.coroutines.launch import net.pokeranalytics.android.model.migrations.Patcher import net.pokeranalytics.android.model.migrations.PokerAnalyticsMigration import net.pokeranalytics.android.model.realm.Session -import net.pokeranalytics.android.util.CrashLogging import net.pokeranalytics.android.model.utils.Seed +import net.pokeranalytics.android.util.CrashLogging import net.pokeranalytics.android.util.FakeDataManager import net.pokeranalytics.android.util.PokerAnalyticsLogs import net.pokeranalytics.android.util.UserDefaults @@ -47,7 +47,7 @@ class PokerAnalyticsApplication : Application() { Realm.init(this) val realmConfiguration = RealmConfiguration.Builder() .name(Realm.DEFAULT_REALM_NAME) - .schemaVersion(12) + .schemaVersion(13) .allowWritesOnUiThread(true) .migration(PokerAnalyticsMigration()) .initialData(Seed(this)) diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollCalculator.kt b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollCalculator.kt index 0d9e92d2..6ff628a0 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollCalculator.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollCalculator.kt @@ -39,10 +39,28 @@ class BankrollCalculator { initialValue += bankroll.initialValue * rate } - bankroll.transactions?.let { transactions -> - val sum = transactions.sum("amount") + if (setup.virtualBankroll) { + val sum = realm.where(Transaction::class.java) + .equalTo("bankroll.id", bankroll.id) + .notEqualTo("type.kind", TransactionType.Value.TRANSFER.uniqueIdentifier) + .sum("amount") // we remove transfer as they don't impact the overall bankroll transactionNet += rate * sum.toDouble() + } else { + + bankroll.transactions?.let { transactions -> + val sum = transactions.sum("amount") + transactionNet += rate * sum.toDouble() + } + + bankroll.destinationTransactions?.let { transactions -> + for (transaction in transactions) { + val transferRate = transaction.transferRate ?: 1.0 + transactionNet += transferRate * transaction.amount * -1 + } + } + } + } report.transactionsNet = transactionNet @@ -71,20 +89,18 @@ class BankrollCalculator { this.computeRiskOfRuin(report, result) } else { - val results = Filter.queryOn(realm, baseQuery) report.netResult = results.sum("net").toDouble() - } val depositType = TransactionType.getByValue(TransactionType.Value.DEPOSIT, realm) report.transactionBuckets[depositType.id]?.let { bucket -> - report.depositTotal = bucket.transactions.sumByDouble { it.amount } + report.depositTotal = bucket.transactions.sumOf { it.amount } } val withdrawalType = TransactionType.getByValue(TransactionType.Value.WITHDRAWAL, realm) report.transactionBuckets[withdrawalType.id]?.let { bucket -> - report.withdrawalTotal = bucket.transactions.sumByDouble { it.amount } + report.withdrawalTotal = bucket.transactions.sumOf { it.amount } } report.generateGraphPointsIfNecessary() diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt index 56f0be1d..6f2e98c7 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt @@ -13,7 +13,6 @@ import net.pokeranalytics.android.model.realm.Transaction import net.pokeranalytics.android.ui.graph.DataSetFactory import net.pokeranalytics.android.util.extensions.findById import java.util.* -import kotlin.collections.HashMap /** * This class holds the results from the BankrollCalculator computations @@ -64,6 +63,7 @@ class BankrollReport(var setup: BankrollReportSetup) { */ private fun computeBankrollTotal() { this.total = this.initial + this.netResult + this.transactionsNet +// Timber.d("init = $initial, net = $netResult, trans = $transactionsNet") } /** diff --git a/app/src/main/java/net/pokeranalytics/android/model/migrations/Patcher.kt b/app/src/main/java/net/pokeranalytics/android/model/migrations/Patcher.kt index 5ec7fffc..6eb4902f 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/migrations/Patcher.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/migrations/Patcher.kt @@ -46,24 +46,7 @@ class Patcher { } Preferences.executeOnce(Preferences.Keys.ADD_NEW_TRANSACTION_TYPES, context) { - - val realm = Realm.getDefaultInstance() - - val lockedTypes = - realm.where(TransactionType::class.java).equalTo("lock", true).findAll() - if (lockedTypes.size == 3) { - Preferences.executeOnce(Preferences.Keys.ADD_NEW_TRANSACTION_TYPES, context) { - val newTypes = arrayOf( - TransactionType.Value.STACKING_INCOMING, - TransactionType.Value.STACKING_OUTGOING - ) - realm.executeTransaction { - Seed.createDefaultTransactionTypes(newTypes, context, realm) - } - } - } - - realm.close() + patchMissingTransactionTypes(context) } } @@ -71,25 +54,10 @@ class Patcher { private fun patchMissingTransactionTypes(context: Context) { val realm = Realm.getDefaultInstance() - val depositType = TransactionType.Value.DEPOSIT - val deposit = realm.where(TransactionType::class.java) - .equalTo("kind", depositType.uniqueIdentifier).findFirst() - if (deposit == null) { - realm.executeTransaction { - Seed.createDefaultTransactionTypes(arrayOf(depositType), context, realm) - } - } + val transactionTypes = TransactionType.Value.values() + Seed.createDefaultTransactionTypes(transactionTypes, context, realm) - val withdrawalType = TransactionType.Value.WITHDRAWAL - val withdrawal = realm.where(TransactionType::class.java) - .equalTo("kind", withdrawalType.uniqueIdentifier).findFirst() - if (withdrawal == null) { - realm.executeTransaction { - Seed.createDefaultTransactionTypes(arrayOf(withdrawalType), context, realm) - } - } realm.close() - } private fun patchBreaks() { diff --git a/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt b/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt index 04e1fba9..3f95f187 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/migrations/PokerAnalyticsMigration.kt @@ -279,6 +279,18 @@ class PokerAnalyticsMigration : RealmMigration { hs.renameField("bigBlind", "oldBigBlind") } + // Migrate to version 13 + if (currentVersion == 12) { + Timber.d("*** Running migration ${currentVersion + 1}") + schema.get("TransactionType")?.let { tts -> + tts.addField("transferRate", Double::class.java).setNullable("transferRate", true) + schema.get("Bankroll")?.let { bs -> + tts.addRealmObjectField("destination", bs) + } ?: throw PAIllegalStateException("Bankroll schema not found") + } + currentVersion++ + } + currentVersion++ } diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt index ec109c60..3b91a491 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Bankroll.kt @@ -60,6 +60,12 @@ open class Bankroll : RealmObject(), NameManageable, RowUpdatable, RowRepresenta @LinkingObjects("bankroll") val transactions: RealmResults? = null + /** + * The list of transactions where the bankroll is the destination + */ + @LinkingObjects("destination") + val destinationTransactions: RealmResults? = null + // The currency of the bankroll var currency: Currency? = null diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt index 32b9a8fd..6f8362a5 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Transaction.kt @@ -18,15 +18,14 @@ import net.pokeranalytics.android.util.TextFormat import net.pokeranalytics.android.util.extensions.findById import java.text.DateFormat import java.util.* -import kotlin.collections.ArrayList - +import kotlin.math.abs open class Transaction : RealmObject(), RowRepresentable, RowUpdatable, Manageable, StaticRowRepresentableDataSource, TimeFilterable, Filterable, DatedBankrollGraphEntry { companion object { - fun newInstance(realm: Realm, bankroll: Bankroll, date: Date? = null, type: TransactionType, amount: Double, comment: String? = null): Transaction { + fun newInstance(realm: Realm, bankroll: Bankroll, date: Date? = null, type: TransactionType, amount: Double, comment: String? = null, destination: Bankroll? = null, transferRate: Double? = null): Transaction { val transaction = realm.copyToRealm(Transaction()) transaction.date = date ?: Date() @@ -34,14 +33,14 @@ open class Transaction : RealmObject(), RowRepresentable, RowUpdatable, Manageab transaction.type = type transaction.bankroll = bankroll transaction.comment = comment ?: "" + transaction.destination = destination + transaction.transferRate = transferRate - return transaction - } + if (destination != null) { // we make sure transfers are negative + transaction.amount = abs(amount) * -1 + } - val rowRepresentation: List by lazy { - val rows = ArrayList() - rows.addAll(TransactionPropertiesRow.values()) - rows + return transaction } fun fieldNameForQueryType(queryCondition: Class): String? { @@ -88,6 +87,12 @@ open class Transaction : RealmObject(), RowRepresentable, RowUpdatable, Manageab // A user comment var comment: String = "" + // The destination Bankroll of a transfer + var destination: Bankroll? = null + + // The rate of the transfer when bankrolls are in different currencies + var transferRate: Double? = null + // Timed interface override var dayOfWeek: Int? = null override var month: Int? = null @@ -97,6 +102,11 @@ open class Transaction : RealmObject(), RowRepresentable, RowUpdatable, Manageab @Ignore override val viewType: Int = RowViewType.ROW_TRANSACTION.ordinal + val displayAmount: Double + get() { // for transfers we want to show a positive value (in the feed for instance) + return if (this.destination == null) { this.amount } else { abs(this.amount) } + } + override fun updateValue(value: Any?, row: RowRepresentable) { when (row) { TransactionPropertiesRow.BANKROLL -> bankroll = value as Bankroll? @@ -104,11 +114,13 @@ open class Transaction : RealmObject(), RowRepresentable, RowUpdatable, Manageab TransactionPropertiesRow.AMOUNT -> amount = if (value == null) 0.0 else (value as String).toDouble() TransactionPropertiesRow.COMMENT -> comment = value as String? ?: "" TransactionPropertiesRow.DATE -> date = value as Date? ?: Date() + TransactionPropertiesRow.DESTINATION -> destination = value as? Bankroll + TransactionPropertiesRow.RATE -> transferRate = (value as String?)?.toDouble() } } override fun adapterRows(): List? { - return rowRepresentation + return rowRepresentation() } override fun isValidForSave(): Boolean { @@ -144,6 +156,24 @@ open class Transaction : RealmObject(), RowRepresentable, RowUpdatable, Manageab return SaveValidityStatus.VALID } + fun rowRepresentation(): List { + val rows = ArrayList() + when (this.type?.kind) { + TransactionType.Value.TRANSFER.uniqueIdentifier -> { + if (this.bankroll != null && this.bankroll?.currency?.code != this.destination?.currency?.code) { + rows.addAll(TransactionPropertiesRow.transferRateRows) + } else { + rows.addAll(TransactionPropertiesRow.transferRows) + } + } + else -> { + rows.addAll(TransactionPropertiesRow.baseRows) + } + } + + return rows + } + // GraphIdentifiableEntry @Ignore diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt index e4d7ce63..3378b003 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/TransactionType.kt @@ -19,7 +19,6 @@ import net.pokeranalytics.android.ui.view.rows.TransactionTypePropertiesRow import net.pokeranalytics.android.util.enumerations.IntIdentifiable import net.pokeranalytics.android.util.enumerations.IntSearchable import java.util.* -import kotlin.collections.ArrayList open class TransactionType : RealmObject(), RowRepresentable, RowUpdatable, NameManageable, StaticRowRepresentableDataSource, @@ -31,7 +30,8 @@ open class TransactionType : RealmObject(), RowRepresentable, RowUpdatable, Name DEPOSIT(1, true), BONUS(2, true), STACKING_INCOMING(3, true), - STACKING_OUTGOING(4, false); + STACKING_OUTGOING(4, false), + TRANSFER(5, false); companion object : IntSearchable { @@ -48,6 +48,7 @@ open class TransactionType : RealmObject(), RowRepresentable, RowUpdatable, Name BONUS -> R.string.bonus STACKING_INCOMING -> R.string.stacking_incoming STACKING_OUTGOING -> R.string.stacking_outgoing + TRANSFER -> R.string.transfer } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt index 9ea6b621..70dd2c14 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt @@ -216,7 +216,7 @@ open class BottomSheetFragment : BottomSheetDialogFragment() { bottomSheetToolbar.menu.findItem(R.id.actionAdd).setOnMenuItemClickListener { val liveData = when (row) { SessionPropertiesRow.GAME -> LiveData.GAME - SessionPropertiesRow.BANKROLL, TransactionPropertiesRow.BANKROLL -> LiveData.BANKROLL + SessionPropertiesRow.BANKROLL, TransactionPropertiesRow.BANKROLL, TransactionPropertiesRow.DESTINATION -> LiveData.BANKROLL SessionPropertiesRow.LOCATION -> LiveData.LOCATION SessionPropertiesRow.TOURNAMENT_NAME -> LiveData.TOURNAMENT_NAME SessionPropertiesRow.TOURNAMENT_FEATURE -> LiveData.TOURNAMENT_FEATURE diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/data/TransactionDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/data/TransactionDataFragment.kt index b6e23388..a66f67bb 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/data/TransactionDataFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/data/TransactionDataFragment.kt @@ -68,6 +68,8 @@ class TransactionDataFragment : EditableDataFragment(), StaticRowRepresentableDa TransactionPropertiesRow.AMOUNT -> if (this.transaction.amount != 0.0) abs(this.transaction.amount).round() else NULL_TEXT TransactionPropertiesRow.COMMENT -> if (this.transaction.comment.isNotEmpty()) this.transaction.comment else NULL_TEXT TransactionPropertiesRow.DATE -> this.transaction.date.shortDate() + TransactionPropertiesRow.DESTINATION -> this.transaction.destination?.name ?: NULL_TEXT + TransactionPropertiesRow.RATE -> this.transaction.transferRate?.round() ?: NULL_TEXT else -> super.charSequenceForRow(row, context, 0) } } @@ -77,7 +79,7 @@ class TransactionDataFragment : EditableDataFragment(), StaticRowRepresentableDa TransactionPropertiesRow.BANKROLL -> row.editingDescriptors( mapOf( "defaultValue" to this.transaction.bankroll, - "data" to getRealm().sorted() + "data" to getRealm().sorted(omitId = this.transaction.destination?.id) ) ) TransactionPropertiesRow.TYPE -> row.editingDescriptors( @@ -88,6 +90,13 @@ class TransactionDataFragment : EditableDataFragment(), StaticRowRepresentableDa ) TransactionPropertiesRow.AMOUNT -> row.editingDescriptors(mapOf("defaultValue" to (if (this.transaction.amount != 0.0) abs(this.transaction.amount).round() else ""))) TransactionPropertiesRow.COMMENT -> row.editingDescriptors(mapOf("defaultValue" to this.transaction.comment)) + TransactionPropertiesRow.DESTINATION -> row.editingDescriptors( + mapOf( + "defaultValue" to this.transaction.destination, + "data" to getRealm().sorted(omitId = this.transaction.bankroll?.id) + ) + ) + TransactionPropertiesRow.RATE -> row.editingDescriptors(mapOf("defaultValue" to this.transaction.transferRate)) else -> super.editDescriptors(row) } } @@ -108,6 +117,13 @@ class TransactionDataFragment : EditableDataFragment(), StaticRowRepresentableDa override fun onRowValueChanged(value: Any?, row: RowRepresentable) { super.onRowValueChanged(value, row) + + when (row) { + TransactionPropertiesRow.TYPE, TransactionPropertiesRow.DESTINATION -> { + this.rowRepresentableAdapter.notifyDataSetChanged() + } + } + this.rowRepresentableAdapter.refreshRow(row) this.selectNextRow(row) } @@ -118,13 +134,19 @@ class TransactionDataFragment : EditableDataFragment(), StaticRowRepresentableDa private fun selectNextRow(currentRow: RowRepresentable) { if (this.model.primaryKey == null) { // automatically change the row for new data - GlobalScope.launch(Dispatchers.Main) { - delay(200) - when (currentRow) { - TransactionPropertiesRow.BANKROLL -> onRowSelected(0, TransactionPropertiesRow.TYPE) - TransactionPropertiesRow.TYPE -> onRowSelected(0, TransactionPropertiesRow.AMOUNT) -// TransactionRow.AMOUNT -> onRowSelected(0, TransactionRow.DATE) -// TransactionRow.DATE -> onRowSelected(0, TransactionRow.COMMENT) + + this.adapterRows()?.let { rows -> + val index = rows.indexOf(currentRow) + if (index + 1 < rows.size) { + when (val next = rows[index + 1]) { + TransactionPropertiesRow.DATE, TransactionPropertiesRow.COMMENT -> {} + else -> { + GlobalScope.launch(Dispatchers.Main) { + delay(200) + onRowSelected(0, next) + } + } + } } } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/TransactionRowView.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/TransactionRowView.kt index 71167eef..6a6f2f11 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/TransactionRowView.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/TransactionRowView.kt @@ -57,14 +57,19 @@ class TransactionRowView : FrameLayout { // Title / Game type val title = transaction.type?.name ?: "" + " " + transaction.comment - val subtitle = transaction.bankroll?.name + var subtitle = transaction.bankroll?.name ?: "" + + transaction.destination?.let { + val items = listOf(subtitle, "→", it.name) + subtitle = items.joinToString(" ") + } rowTransaction.findViewById(R.id.transactionTitle).text = title rowTransaction.findViewById(R.id.transactionSubtitle).text = subtitle // Amount val computedStat = ComputedStat(Stat.NET_RESULT, - transaction.amount, + transaction.displayAmount, currency = transaction.bankroll?.utilCurrency) rowTransaction.findViewById(R.id.transactionAmount).setTextFormat(computedStat.textFormat, context) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/TransactionPropertiesRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/TransactionPropertiesRow.kt index 83bd227f..33eb610d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rows/TransactionPropertiesRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rows/TransactionPropertiesRow.kt @@ -16,7 +16,17 @@ enum class TransactionPropertiesRow : RowRepresentable, DefaultEditDataSource { TYPE, AMOUNT, DATE, - COMMENT; + COMMENT, + DESTINATION, + RATE; + + companion object { + + val baseRows: List = listOf(BANKROLL, TYPE, AMOUNT, DATE, COMMENT) + val transferRows: List = listOf(BANKROLL, TYPE, DESTINATION, AMOUNT, DATE, COMMENT, ) + val transferRateRows: List = listOf(BANKROLL, TYPE, DESTINATION, AMOUNT, RATE, DATE, COMMENT) + + } override val resId: Int? get() { @@ -26,6 +36,8 @@ enum class TransactionPropertiesRow : RowRepresentable, DefaultEditDataSource { AMOUNT -> R.string.amount COMMENT -> R.string.comment DATE -> R.string.date + DESTINATION -> R.string.destination + RATE -> R.string.rate } } @@ -37,15 +49,17 @@ enum class TransactionPropertiesRow : RowRepresentable, DefaultEditDataSource { AMOUNT -> RowViewType.TITLE_VALUE.ordinal COMMENT -> RowViewType.TITLE_VALUE.ordinal DATE -> RowViewType.TITLE_VALUE.ordinal + DESTINATION -> RowViewType.TITLE_VALUE.ordinal + RATE -> RowViewType.TITLE_VALUE.ordinal } } override val bottomSheetType: BottomSheetType get() { return when (this) { - BANKROLL -> BottomSheetType.LIST + BANKROLL, DESTINATION -> BottomSheetType.LIST TYPE -> BottomSheetType.LIST - AMOUNT -> BottomSheetType.EDIT_TEXT + AMOUNT, RATE -> BottomSheetType.EDIT_TEXT COMMENT -> BottomSheetType.EDIT_TEXT_MULTI_LINES DATE -> BottomSheetType.NONE } @@ -53,7 +67,7 @@ enum class TransactionPropertiesRow : RowRepresentable, DefaultEditDataSource { override fun editingDescriptors(map: Map): ArrayList? { return when (this) { - BANKROLL -> { + BANKROLL, DESTINATION -> { val defaultValue : Any? by map val data : RealmResults? by map arrayListOf( @@ -67,7 +81,7 @@ enum class TransactionPropertiesRow : RowRepresentable, DefaultEditDataSource { RowRepresentableEditDescriptor(defaultValue, data = data) ) } - AMOUNT -> { + AMOUNT, RATE -> { val defaultValue: String? by map arrayListOf( RowRepresentableEditDescriptor( diff --git a/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt b/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt index 99578a2a..f4b7ef65 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/Preferences.kt @@ -35,7 +35,7 @@ class Preferences { // PATCH_BLINDS_FORMAT("patchBlindFormat"), PATCH_COMPUTABLE_RESULTS("patchPositiveSessions"), SHOW_STOP_NOTIFICATIONS("showStopNotifications"), - ADD_NEW_TRANSACTION_TYPES("addNewTransactionTypes"), + ADD_NEW_TRANSACTION_TYPES("addNewTransactionTypes_transfer"), SHOW_VILLAIN_CARDS("showVillainCards"), BANKROLL_RESULT_CAPTURE_TYPE("bankrollResultCaptureType_"), LATEST_BLOG_POST_ID_RETRIEVED("latestBlogPostIdRetrieved"), diff --git a/app/src/main/java/net/pokeranalytics/android/util/csv/ProductCSVDescriptors.kt b/app/src/main/java/net/pokeranalytics/android/util/csv/ProductCSVDescriptors.kt index b5d79fe2..29a8cd7b 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/csv/ProductCSVDescriptors.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/csv/ProductCSVDescriptors.kt @@ -236,7 +236,12 @@ class ProductCSVDescriptors { TrField.Live("Live"), TrField.CurrencyCode("Currency Code"), TrField.CurrencyRate("Currency Rate"), - TrField.Comment("Comment") + TrField.Comment("Comment"), + TrField.TransferRate("Transfer Rate"), + TrField.DestinationBankrollName("Destination"), + TrField.DestinationLive("Destination Live"), + TrField.DestinationCurrencyCode("Destination Currency"), + TrField.DestinationCurrencyRate("Destination Currency Rate"), ) } diff --git a/app/src/main/java/net/pokeranalytics/android/util/csv/SessionField.kt b/app/src/main/java/net/pokeranalytics/android/util/csv/SessionField.kt index 611d042d..f92db5c5 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/csv/SessionField.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/csv/SessionField.kt @@ -32,6 +32,24 @@ sealed class TrField { override var callback: ((String) -> Double?)? = null ) : NumberCSVField + data class DestinationBankrollName(override var header: String) : CSVField + data class DestinationCurrencyCode(override var header: String) : CSVField + + data class TransferRate( + override var header: String, + override var callback: ((String) -> Double?)? = null + ) : NumberCSVField + + data class DestinationCurrencyRate( + override var header: String, + override var callback: ((String) -> Double?)? = null + ) : NumberCSVField + + data class DestinationLive( + override var header: String, + override var callback: ((String) -> Boolean?)? = null + ) : BooleanCSVField + data class TransactionType(override var header: String) : CSVField data class Comment(override var header: String) : CSVField diff --git a/app/src/main/java/net/pokeranalytics/android/util/csv/TransactionCSVDescriptor.kt b/app/src/main/java/net/pokeranalytics/android/util/csv/TransactionCSVDescriptor.kt index 3b2db42d..c0de0819 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/csv/TransactionCSVDescriptor.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/csv/TransactionCSVDescriptor.kt @@ -20,10 +20,17 @@ class TransactionCSVDescriptor(source: DataSource, vararg elements: CSVField) : var bankrollName: String? = null var amount: Double? = null var comment: String? = null - var live = false + var live = true var currencyCode: String? = null var currencyRate: Double? = null + // transfers + var destinationName: String? = null + var destinationLive = true + var destinationCurrencyCode: String? = null + var destinationCurrencyRate: Double? = null + var transferRate: Double? = null + for (field in this.fields) { val index = this.fieldMapping[field] @@ -38,6 +45,11 @@ class TransactionCSVDescriptor(source: DataSource, vararg elements: CSVField) : is TrField.CurrencyCode -> currencyCode = value is TrField.CurrencyRate -> currencyRate = field.parse(value) is TrField.Comment -> comment = value + is TrField.DestinationBankrollName -> destinationName = value + is TrField.DestinationCurrencyCode -> destinationCurrencyCode = value + is TrField.DestinationCurrencyRate -> destinationCurrencyRate = field.parse(value) + is TrField.TransferRate -> transferRate = field.parse(value) + is TrField.DestinationLive -> destinationLive = field.parse(value) ?: true } } } @@ -48,7 +60,13 @@ class TransactionCSVDescriptor(source: DataSource, vararg elements: CSVField) : if (DataUtils.transactionUnicityCheck(realm, date, amount, type)) { val bankroll = Bankroll.getOrCreate(realm, bankrollName, live, currencyCode, currencyRate) - return Transaction.newInstance(realm, bankroll, date, type, amount, comment) + + var destination: Bankroll? = null + if (destinationName?.isNotEmpty() == true) { + destination = Bankroll.getOrCreate(realm, destinationName, destinationLive, destinationCurrencyCode, destinationCurrencyRate) + } + + return Transaction.newInstance(realm, bankroll, date, type, amount, comment, destination, transferRate) } else { Timber.d("Transaction already exists") } @@ -70,6 +88,11 @@ class TransactionCSVDescriptor(source: DataSource, vararg elements: CSVField) : is TrField.CurrencyCode -> data.bankroll?.currency?.code is TrField.CurrencyRate -> field.format(data.bankroll?.currency?.rate) is TrField.Comment -> data.comment + is TrField.DestinationBankrollName -> data.destination?.name + is TrField.DestinationCurrencyRate -> field.format(data.destination?.currency?.rate) + is TrField.DestinationCurrencyCode -> data.destination?.currency?.code + is TrField.TransferRate -> field.format(data.transferRate) + is TrField.DestinationLive -> field.format(data.destination?.live) else -> throw PAIllegalStateException("unmanaged field: $field") } diff --git a/app/src/main/java/net/pokeranalytics/android/util/extensions/RealmExtensions.kt b/app/src/main/java/net/pokeranalytics/android/util/extensions/RealmExtensions.kt index 0ebf60fd..85012d46 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/extensions/RealmExtensions.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/extensions/RealmExtensions.kt @@ -3,9 +3,9 @@ package net.pokeranalytics.android.util.extensions import io.realm.* import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.filter.Query -import net.pokeranalytics.android.model.interfaces.UsageCountable import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.NameManageable +import net.pokeranalytics.android.model.interfaces.UsageCountable import net.pokeranalytics.android.model.realm.* fun Realm.count(clazz: Class) : Long { @@ -39,7 +39,7 @@ inline fun Realm.getOrCreate(name: String) : T { * Returns all entities of the [clazz] sorted with their default sorting * Set [editableOnly] to true to only receive entities that can be edited */ -fun < T : RealmModel> Realm.sorted(clazz: Class, editableOnly: Boolean = false, filterableTypeUniqueIdentifier: Int? = null) : RealmResults { +fun Realm.sorted(clazz: Class, editableOnly: Boolean = false, filterableTypeUniqueIdentifier: Int? = null, omitId: String? = null) : RealmResults { val query = this.where(clazz) when (clazz.kotlin) { TransactionType::class -> { @@ -54,6 +54,10 @@ fun < T : RealmModel> Realm.sorted(clazz: Class, editableOnly: Boolean = fals } } + omitId?.let { + query.notEqualTo("id", it) + } + val items = query.findAll() var sortField = arrayOf("name") var resultSort = arrayOf(Sort.ASCENDING) @@ -79,8 +83,8 @@ fun < T : RealmModel> Realm.sorted(clazz: Class, editableOnly: Boolean = fals /** * Returns all entities of the [C] class sorted with their default sorting */ -inline fun Realm.sorted(editableOnly: Boolean = false) : RealmResults { - return this.sorted(C::class.java, editableOnly) +inline fun Realm.sorted(editableOnly: Boolean = false, omitId: String? = null) : RealmResults { + return this.sorted(C::class.java, editableOnly, omitId = omitId) } /** diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 74a9b5db..54486f52 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -822,5 +822,7 @@ The hand you\'ve created has suit wildcards. By convenience - sorry! - we\'re currently removing such cards to determine which hand wins, resulting in potentially wrong chip distribution. proceed error(s) + Transfer + Destination