Skip to content

Commit

Permalink
codinguser#876 - Correct balance amount computation and factorize int…
Browse files Browse the repository at this point in the history
…o getAmountColor()
  • Loading branch information
JeanGarf committed Mar 6, 2020
1 parent e178e3a commit 2f82436
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 82 deletions.
58 changes: 58 additions & 0 deletions app/src/main/java/org/gnucash/android/model/AccountType.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package org.gnucash.android.model;

import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;

import org.gnucash.android.R;
import org.gnucash.android.app.GnuCashApplication;

/**
* The type of account
* This are the different types specified by the OFX format and
Expand Down Expand Up @@ -37,6 +43,48 @@ public enum AccountType {
//nothing to see here, move along
}

// TODO TW C 2020-03-06 : Enlever le static

/**
* Compute red/green color according to accountType and isCredit
*
* @param isCredit
* @param accountType
*
* @return
*/
@ColorInt
public static int getAmountColor(final boolean isCredit,
final AccountType accountType) {

AccountType tmpAccountType = ((accountType != null)
? accountType
: AccountType.ASSET);

@ColorRes final int colorRes;

// TODO TW C 2020-03-06 : Trouver un meilleur nom
final boolean specialAccountType = tmpAccountType.isEquityAccount() || tmpAccountType.isResultAccount();

if ((!specialAccountType && isCredit) || (specialAccountType && !isCredit)) {
// TODO TW C 2020-03-02 : commenter
// CREDIT

// RED
colorRes = R.color.debit_red;

} else {
// DEBIT

// GREEN
colorRes = R.color.credit_green;
}

return GnuCashApplication.getAppContext()
.getResources()
.getColor(colorRes);
}

public boolean hasDebitNormalBalance() {

return mNormalBalance == TransactionType.DEBIT;
Expand All @@ -51,6 +99,16 @@ public TransactionType getNormalBalanceType() {
return mNormalBalance;
}

public boolean isAssetAccount() {

return ASSET.equals(this) || BANK.equals(this) || CASH.equals(this);
}

public boolean isEquityAccount() {

return EQUITY.equals(this);
}

// TODO TW C 2020-03-03 : A renommer en anglais
public boolean isResultAccount() {

Expand Down
90 changes: 58 additions & 32 deletions app/src/main/java/org/gnucash/android/model/Split.java
Original file line number Diff line number Diff line change
Expand Up @@ -301,37 +301,6 @@ public Money getFormattedQuantity(){
return getFormattedAmount(mQuantity, mAccountUID, mSplitType);
}

/**
* Splits are saved as absolute values to the database, with no negative numbers.
* The type of movement the split causes to the balance of an account determines
* its sign, and that depends on the split type and the account type
* @param amount Money amount to format
* @param accountUID GUID of the account
* @param splitType Transaction type of the split
* @return -{@code amount} if the amount would reduce the balance of
* {@code account}, otherwise +{@code amount}
*/
private static Money getFormattedAmount(Money amount, String accountUID, TransactionType
splitType){
boolean isDebitAccount = AccountsDbAdapter.getInstance().getAccountType(accountUID).hasDebitNormalBalance();
Money absAmount = amount.abs();

boolean isDebitSplit = splitType == TransactionType.DEBIT;
if (isDebitAccount) {
if (isDebitSplit) {
return absAmount;
} else {
return absAmount.negate();
}
} else {
if (isDebitSplit) {
return absAmount.negate();
} else {
return absAmount;
}
}
}

/**
* Return the reconciled state of this split
* <p>
Expand All @@ -351,6 +320,54 @@ public char getReconcileState() {
return mReconcileState;
}

/**
* Splits are saved as absolute values to the database, with no negative numbers.
* The type of movement the split causes to the balance of an account determines
* its sign, and that depends on the split type and the account type
* @param amount Money amount to format
* @param accountUID GUID of the account
* @param splitType Transaction type of the split
* @return -{@code amount} if the amount would reduce the balance of
* {@code account}, otherwise +{@code amount}
*/
private static Money getFormattedAmount(Money amount,
String accountUID,
TransactionType splitType) {

// boolean isDebitAccount = AccountsDbAdapter.getInstance()
// .getAccountType(accountUID)
// .hasDebitNormalBalance();

Money absAmount = amount.abs();

boolean isDebitSplit = splitType == TransactionType.DEBIT;

// if (isDebitAccount) {
// if (isDebitSplit) {
// return absAmount;
// } else {
// return absAmount.negate();
// }
// } else {
// if (isDebitSplit) {
// return absAmount.negate();
// } else {
// return absAmount;
// }
// }

if (isDebitSplit) {
// It is a Debit Split

return absAmount;

} else {
// It is not a Debit Split

return absAmount.negate();
}
}

/**
* Check if this split is reconciled
* @return {@code true} if the split is reconciled, {@code false} otherwise
Expand Down Expand Up @@ -394,7 +411,16 @@ public void setReconcileDate(Timestamp reconcileDate) {

@Override
public String toString() {
return mSplitType.name() + " of " + mValue.toString() + " in account: " + mAccountUID;

return mSplitType.name()
+ " of "
+ mValue.toString()
+ " in account: "
+ mAccountUID
+ " ("
+ AccountsDbAdapter.getInstance()
.getAccountFullName(mAccountUID)
+ ")";
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,10 @@ protected void displayReport() {
mChart.highlightValues(null);
mChart.invalidate();

TransactionsActivity.displayBalance(mTotalAssets, mAssetsBalance);
TransactionsActivity.displayBalance(mTotalLiabilities, mLiabilitiesBalance);
TransactionsActivity.displayBalance(mNetWorth, mAssetsBalance.subtract(mLiabilitiesBalance));
TransactionsActivity.displayBalance(mTotalAssets, mAssetsBalance, AccountType.ASSET);
TransactionsActivity.displayBalance(mTotalLiabilities, mLiabilitiesBalance, AccountType.LIABILITY);
// #8xx
TransactionsActivity.displayBalance(mNetWorth, mAssetsBalance.add(mLiabilitiesBalance), null);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
import org.gnucash.android.model.ScheduledAction;
import org.gnucash.android.model.Split;
import org.gnucash.android.model.Transaction;
import org.gnucash.android.model.TransactionType;
import org.gnucash.android.ui.common.FormActivity;
import org.gnucash.android.ui.common.UxArgument;
import org.gnucash.android.ui.passcode.PasscodeLockActivity;
import org.gnucash.android.ui.util.AccountUtils;

import java.text.DateFormat;
import java.util.Date;
Expand All @@ -40,14 +42,55 @@
*/
public class TransactionDetailActivity extends PasscodeLockActivity {

@BindView(R.id.trn_description) TextView mTransactionDescription;
@BindView(R.id.trn_time_and_date) TextView mTimeAndDate;
@BindView(R.id.trn_recurrence) TextView mRecurrence;
@BindView(R.id.trn_notes) TextView mNotes;
class SplitAmountViewHolder {
@BindView(R.id.split_account_name) TextView accountName;
@BindView(R.id.split_debit) TextView splitDebitView;
@BindView(R.id.split_credit) TextView splitCreditView;

View itemView;

public SplitAmountViewHolder(View view,
Split split) {

itemView = view;

ButterKnife.bind(this,
view);

AccountsDbAdapter accountsDbAdapter = AccountsDbAdapter.getInstance();

final String accountUID = split.getAccountUID();

accountName.setText(accountsDbAdapter.getAccountFullName(accountUID));

// quantity (positive or negative number)
Money quantity = split.getFormattedQuantity();

// Define debit or credit view
// #8xx
// TextView balanceView = quantity.isNegative()
// ? splitDebitView
// : splitCreditView;
TextView balanceView = TransactionType.CREDIT.equals(split.getType())
? splitCreditView
: splitDebitView;

TransactionsActivity.displayBalance(balanceView,
quantity,
AccountsDbAdapter.getInstance()
.getAccountType(split.getAccountUID()));
}

} // Class SplitAmountViewHolder

@BindView(R.id.toolbar) Toolbar mToolBar;
@BindView(R.id.trn_description) TextView mTransactionDescription;
@BindView(R.id.transaction_account) TextView mTransactionAccount;
@BindView(R.id.balance_debit) TextView mDebitBalance;
@BindView(R.id.balance_credit) TextView mCreditBalance;
@BindView(R.id.trn_time_and_date) TextView mTimeAndDate;
@BindView(R.id.trn_recurrence) TextView mRecurrence;
@BindView(R.id.trn_notes) TextView mNotes;

@BindView(R.id.fragment_transaction_details)
TableLayout mDetailTableLayout;
Expand Down Expand Up @@ -92,61 +135,71 @@ protected void onCreate(Bundle savedInstanceState) {

}

class SplitAmountViewHolder {
@BindView(R.id.split_account_name) TextView accountName;
@BindView(R.id.split_debit) TextView splitDebit;
@BindView(R.id.split_credit) TextView splitCredit;

View itemView;

public SplitAmountViewHolder(View view, Split split){
itemView = view;
ButterKnife.bind(this, view);

AccountsDbAdapter accountsDbAdapter = AccountsDbAdapter.getInstance();
accountName.setText(accountsDbAdapter.getAccountFullName(split.getAccountUID()));
Money quantity = split.getFormattedQuantity();
TextView balanceView = quantity.isNegative() ? splitDebit : splitCredit;
TransactionsActivity.displayBalance(balanceView, quantity);
}
}

/**
* Reads the transaction information from the database and binds it to the views
*/
private void bindViews(){
TransactionsDbAdapter transactionsDbAdapter = TransactionsDbAdapter.getInstance();
Transaction transaction = transactionsDbAdapter.getRecord(mTransactionUID);

// Transaction description
mTransactionDescription.setText(transaction.getDescription());

// Account Full Name
mTransactionAccount.setText(getString(R.string.label_inside_account_with_name, AccountsDbAdapter.getInstance().getAccountFullName(mAccountUID)));

//
// Account balance
//

AccountsDbAdapter accountsDbAdapter = AccountsDbAdapter.getInstance();

// Compute balance at Transaction time
Money accountBalance = accountsDbAdapter.getAccountBalance(mAccountUID, -1, transaction.getTimeMillis());
TextView balanceTextView = accountBalance.isNegative() ? mDebitBalance : mCreditBalance;
TransactionsActivity.displayBalance(balanceTextView, accountBalance);

// #8xx
// Define in which field (Debit or Credit) the balance shall be displayed
TextView balanceTextView = accountBalance.isNegative() ? mCreditBalance : mDebitBalance ;

TransactionsActivity.displayBalance(balanceTextView,
accountBalance,
accountsDbAdapter.getAccountType(mAccountUID));

//
// Détails
//

mDetailTableRows = mDetailTableLayout.getChildCount();

boolean useDoubleEntry = GnuCashApplication.isDoubleEntryEnabled();
LayoutInflater inflater = LayoutInflater.from(this);
int index = 0;

for (Split split : transaction.getSplits()) {

if (!useDoubleEntry && split.getAccountUID().equals(
accountsDbAdapter.getImbalanceAccountUID(split.getValue().getCommodity()))) {
//do now show imbalance accounts for single entry use case
continue;
}

View view = inflater.inflate(R.layout.item_split_amount_info, mDetailTableLayout, false);
SplitAmountViewHolder viewHolder = new SplitAmountViewHolder(view, split);
mDetailTableLayout.addView(viewHolder.itemView, index++);
}

//
// Date
//

Date trnDate = new Date(transaction.getTimeMillis());
String timeAndDate = DateFormat.getDateInstance(DateFormat.FULL).format(trnDate);
mTimeAndDate.setText(timeAndDate);

//
//
//

if (transaction.getScheduledActionUID() != null){
ScheduledAction scheduledAction = ScheduledActionDbAdapter.getInstance().getRecord(transaction.getScheduledActionUID());
mRecurrence.setText(scheduledAction.getRepeatString());
Expand Down
Loading

0 comments on commit 2f82436

Please sign in to comment.