From 0bc502e468fa95581f1d3952bf21fffce9fa05a2 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Thu, 9 May 2019 14:11:56 +0200 Subject: [PATCH] Improve deletion system and add deletion for bankroll --- .../android/model/interfaces/Manageable.kt | 32 +++-- .../android/model/realm/Bankroll.kt | 118 ++++++++++-------- .../android/model/realm/Transaction.kt | 9 +- .../android/model/realm/TransactionType.kt | 9 +- .../android/ui/activity/BankrollActivity.kt | 6 +- .../ui/fragment/BankrollEditDataFragment.kt | 7 -- .../android/ui/fragment/BankrollFragment.kt | 15 ++- .../ui/fragment/EditableDataFragment.kt | 3 +- 8 files changed, 116 insertions(+), 83 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Manageable.kt b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Manageable.kt index 6ea3ecca..2620928c 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/interfaces/Manageable.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/interfaces/Manageable.kt @@ -12,12 +12,19 @@ enum class SaveValidityStatus { DATA_INVALID; } +enum class DeleteValidityStatus { + VALID, + INVALID, + SESSIONS_LINKED, + TRANSACTIONS_LINKED; +} + /** * An interface to grouped object which are managed by the database */ interface Manageable : Savable, Deletable, Editable -interface NameManageable: Manageable { +interface NameManageable : Manageable { var name: String override fun isValidForSave(): Boolean { @@ -25,16 +32,16 @@ interface NameManageable: Manageable { } override fun alreadyExists(realm: Realm): Boolean { - return realm.where(this::class.java).equalTo("name", this.name).and().notEqualTo("id", this.id).findAll().isNotEmpty() + return realm.where(this::class.java).equalTo("name", this.name).and().notEqualTo("id", this.id).findAll().isNotEmpty() } override fun getFailedSaveMessage(status: SaveValidityStatus): Int { - throw ModelException("${this::class.java} getFailedSaveMessage for $status not handled") + throw ModelException("${this::class.java} getFailedSaveMessage for $status not handled") } - override fun getFailedDeleteMessage(): Int { - return R.string.relationship_error - } + override fun getFailedDeleteMessage(status: DeleteValidityStatus): Int { + return R.string.relationship_error + } } @@ -87,7 +94,7 @@ interface Savable : Identifiable { /** * A method to get the reason why the object can't be saved */ - fun getFailedSaveMessage(status:SaveValidityStatus): Int + fun getFailedSaveMessage(status: SaveValidityStatus): Int } @@ -101,8 +108,17 @@ interface Deletable : Identifiable { */ fun isValidForDelete(realm: Realm): Boolean + + fun getDeleteStatus(realm: Realm): DeleteValidityStatus { + if (!isValidForDelete(realm)) { + return DeleteValidityStatus.INVALID + } + return DeleteValidityStatus.VALID + } + /** * A method to get the reason why the object can't be deleted */ - fun getFailedDeleteMessage(): Int + fun getFailedDeleteMessage(status: DeleteValidityStatus): Int + } \ No newline at end of file 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 f4d6dd88..7d69c508 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 @@ -7,6 +7,7 @@ import io.realm.annotations.LinkingObjects import io.realm.annotations.PrimaryKey import io.realm.kotlin.where import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.interfaces.DeleteValidityStatus import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.model.interfaces.SaveValidityStatus import net.pokeranalytics.android.ui.view.RowRepresentable @@ -16,69 +17,82 @@ import java.util.* open class Bankroll : RealmObject(), NameManageable, RowRepresentable { - @PrimaryKey - override var id = UUID.randomUUID().toString() + @PrimaryKey + override var id = UUID.randomUUID().toString() - override var name: String = "" + override var name: String = "" - // Indicates whether the bankroll is live or online - var live: Boolean = true + // Indicates whether the bankroll is live or online + var live: Boolean = true - /** - * The list of transactions of the bankroll - */ - @LinkingObjects("bankroll") - val transactions: RealmResults? = null + /** + * The list of transactions of the bankroll + */ + @LinkingObjects("bankroll") + val transactions: RealmResults? = null - // The currency of the bankroll - var currency: Currency? = null + // The currency of the bankroll + var currency: Currency? = null - // The initial value of the bankroll - var initialValue: Double = 0.0 + // The initial value of the bankroll + var initialValue: Double = 0.0 - val rate: Double - get() { - return this.currency?.rate ?: 1.0 - } + val rate: Double + get() { + return this.currency?.rate ?: 1.0 + } - override fun getDisplayName(): String { - return this.name - } + override fun getDisplayName(): String { + return this.name + } - override fun updateValue(value: Any?, row: RowRepresentable) { - when (row) { - SimpleRow.NAME -> this.name = value as String? ?: "" - BankrollRow.LIVE -> { - this.live = if (value is Boolean) !value else false - } - BankrollRow.INITIAL_VALUE -> { - this.initialValue = value as Double? ?: 0.0 - } - BankrollRow.CURRENCY -> { - //TODO handle a use default currency option - this.currency?.code = value as String? - } - BankrollRow.RATE -> { - this.currency?.rate = value as Double? - } - } - } + override fun updateValue(value: Any?, row: RowRepresentable) { + when (row) { + SimpleRow.NAME -> this.name = value as String? ?: "" + BankrollRow.LIVE -> { + this.live = if (value is Boolean) !value else false + } + BankrollRow.INITIAL_VALUE -> { + this.initialValue = value as Double? ?: 0.0 + } + BankrollRow.CURRENCY -> { + //TODO handle a use default currency option + this.currency?.code = value as String? + } + BankrollRow.RATE -> { + this.currency?.rate = value as Double? + } + } + } - override fun isValidForDelete(realm: Realm): Boolean { + override fun isValidForDelete(realm: Realm): Boolean { return realm.where().equalTo("bankroll.id", id).findAll().isEmpty() - //TODO: Check transactions - //&& realm.where().equalTo("bankroll.id", id).findAll().isEmpty() + && realm.where().equalTo("bankroll.id", id).findAll().isEmpty() + } + + override fun getDeleteStatus(realm: Realm): DeleteValidityStatus { + return if (!realm.where().equalTo("bankroll.id", id).findAll().isEmpty()) { + DeleteValidityStatus.SESSIONS_LINKED + } else if (!realm.where().equalTo("bankroll.id", id).findAll().isEmpty()) { + DeleteValidityStatus.TRANSACTIONS_LINKED + } else { + DeleteValidityStatus.VALID + } } - override fun getFailedDeleteMessage(): Int { - return R.string.bankroll_relationship_error - } + override fun getFailedDeleteMessage(status: DeleteValidityStatus): Int { + return when (status) { + DeleteValidityStatus.SESSIONS_LINKED -> R.string.bankroll_relationship_error + DeleteValidityStatus.TRANSACTIONS_LINKED -> R.string.bankroll_relationship_error_transactions + else -> super.getFailedDeleteMessage(status) + } + } - override fun getFailedSaveMessage(status: SaveValidityStatus): Int { - return when (status) { - SaveValidityStatus.DATA_INVALID -> R.string.empty_name_for_br_error - SaveValidityStatus.ALREADY_EXISTS -> R.string.duplicate_bankroll_name_error - else -> super.getFailedSaveMessage(status) - } - } + override fun getFailedSaveMessage(status: SaveValidityStatus): Int { + return when (status) { + SaveValidityStatus.DATA_INVALID -> R.string.empty_name_for_br_error + SaveValidityStatus.ALREADY_EXISTS -> R.string.duplicate_bankroll_name_error + else -> super.getFailedSaveMessage(status) + } + } } \ No newline at end of file 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 c6c3f4f9..d45b3b51 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 @@ -10,10 +10,7 @@ import net.pokeranalytics.android.calculus.Stat import net.pokeranalytics.android.calculus.TextFormat import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.filter.QueryCondition -import net.pokeranalytics.android.model.interfaces.DatedValue -import net.pokeranalytics.android.model.interfaces.Manageable -import net.pokeranalytics.android.model.interfaces.SaveValidityStatus -import net.pokeranalytics.android.model.interfaces.TimeFilterable +import net.pokeranalytics.android.model.interfaces.* import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.graph.GraphUnderlyingEntry import net.pokeranalytics.android.ui.view.RowRepresentable @@ -115,8 +112,8 @@ open class Transaction : RealmObject(), Manageable, StaticRowRepresentableDataSo return true } - override fun getFailedDeleteMessage(): Int { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + override fun getFailedDeleteMessage(status: DeleteValidityStatus): Int { + return R.string.relationship_error } override fun getSaveValidityStatus(realm: Realm): SaveValidityStatus { 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 756bc899..8705eb16 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 @@ -3,6 +3,8 @@ package net.pokeranalytics.android.model.realm import io.realm.Realm import io.realm.RealmObject import io.realm.annotations.PrimaryKey +import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.interfaces.DeleteValidityStatus import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.view.RowRepresentable @@ -88,11 +90,12 @@ open class TransactionType : RealmObject(), NameManageable, StaticRowRepresentab } override fun isValidForDelete(realm: Realm): Boolean { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + return true } - override fun getFailedDeleteMessage(): Int { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + override fun getFailedDeleteMessage(status: DeleteValidityStatus): Int { + return R.string.relationship_error } + } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/BankrollActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/BankrollActivity.kt index 5fb6250d..d114029c 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/BankrollActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/BankrollActivity.kt @@ -69,8 +69,10 @@ class BankrollActivity : PokerAnalyticsActivity() { indexes.addAll(changeSet.insertions.toList()) indexes.addAll(changeSet.deletions.toList()) indexes.forEach { index -> - t[index]?.bankroll?.let { br -> - bankrolls.add(br) + if (t.isNotEmpty()) { + t[index]?.bankroll?.let { br -> + bankrolls.add(br) + } } } this.computeBankrollReports(bankrolls) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollEditDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollEditDataFragment.kt index 67947540..bdecaa46 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollEditDataFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollEditDataFragment.kt @@ -3,8 +3,6 @@ package net.pokeranalytics.android.ui.fragment import android.app.Activity.RESULT_OK import android.content.Intent import android.os.Bundle -import android.view.Menu -import android.view.MenuInflater import android.view.View import net.pokeranalytics.android.R import net.pokeranalytics.android.api.CurrencyConverterApi @@ -56,11 +54,6 @@ class BankrollEditDataFragment : EditableDataFragment(), StaticRowRepresentableD } ?: false } - override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { - super.onCreateOptionsMenu(menu, inflater) - menu?.findItem(R.id.delete)?.isVisible = false - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt index 459e3123..3e0eed9f 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/BankrollFragment.kt @@ -9,6 +9,7 @@ import android.view.ViewGroup import androidx.appcompat.app.AlertDialog import androidx.recyclerview.widget.LinearLayoutManager import com.github.mikephil.charting.data.LineDataSet +import io.realm.Realm import io.realm.RealmObject import io.realm.RealmResults import kotlinx.android.synthetic.main.fragment_bankroll.* @@ -34,7 +35,6 @@ import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource -import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable @@ -43,7 +43,7 @@ import timber.log.Timber import java.util.* import kotlin.collections.ArrayList -class BankrollFragment : RealmFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { +class BankrollFragment : DeletableItemFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { companion object { @@ -153,6 +153,9 @@ class BankrollFragment : RealmFragment(), StaticRowRepresentableDataSource, RowR val bankrolls = LiveData.BANKROLL.items(getRealm()) as RealmResults bankrolls.forEach { + + Timber.d("Bankroll: ${it.name} => isValidForDelete: ${it.isValidForDelete(Realm.getDefaultInstance())}") + val bankrollReportSetup = BankrollReportSetup(it) val bankrollReport = BankrollCalculator.computeReport(getRealm(), bankrollReportSetup) val computedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.total) @@ -217,8 +220,10 @@ class BankrollFragment : RealmFragment(), StaticRowRepresentableDataSource, RowR if (mRecentlyDeletedItem is Bankroll) { + val deletableItem = (mRecentlyDeletedItem as Deletable) + // Check if the object is valid for the deletion - if ((mRecentlyDeletedItem as Deletable).isValidForDelete(this.getRealm())) { + if (deletableItem.isValidForDelete(this.getRealm())) { deletedItem = getRealm().copyFromRealm(mRecentlyDeletedItem) getRealm().executeTransaction { mRecentlyDeletedItem.deleteFromRealm() @@ -231,8 +236,10 @@ class BankrollFragment : RealmFragment(), StaticRowRepresentableDataSource, RowR } else { bankrollAdapter.notifyItemChanged(position) + val status = deletableItem.getDeleteStatus(this.getRealm()) + val errorMessage = deletableItem.getFailedDeleteMessage(status) val builder = AlertDialog.Builder(requireContext()) - .setMessage((mRecentlyDeletedItem as Deletable).getFailedDeleteMessage()) + .setMessage(errorMessage) .setNegativeButton(R.string.ok, null) builder.show() } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/EditableDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/EditableDataFragment.kt index 0460b9d8..11fef313 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/EditableDataFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/EditableDataFragment.kt @@ -192,7 +192,8 @@ open class EditableDataFragment : RealmFragment(), RowRepresentableDelegate { activity?.setResult(RESULT_OK, intent) activity?.finish() } else { - val message = deletable.getFailedDeleteMessage() + val status = deletable.getDeleteStatus(realm) + val message = deletable.getFailedDeleteMessage(status) val builder = AlertDialog.Builder(requireContext()) .setMessage(message) .setNegativeButton(R.string.ok, null)