Skip to content

Commit dbce36f

Browse files
committed
Updated credit/debit handling to match Gnucash desktop - fixes #78
Now credit transactions decrease balance in Assets and Expenses accounts while debits increase the balance
1 parent 087e449 commit dbce36f

4 files changed

Lines changed: 89 additions & 12 deletions

File tree

app/src/org/gnucash/android/data/Account.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,28 @@ public class Account {
5454
* This are the different types specified by the OFX format and
5555
* they are currently not used except for exporting
5656
*/
57-
public enum AccountType {CASH, BANK, CREDIT, ASSET, LIABILITY, INCOME, EXPENSE,
58-
PAYABLE, RECEIVABLE, EQUITY, CURRENCY, STOCK, MUTUAL, ROOT};
57+
public enum AccountType {
58+
CASH, BANK, CREDIT, ASSET(true), LIABILITY, INCOME, EXPENSE(true),
59+
PAYABLE, RECEIVABLE, EQUITY, CURRENCY, STOCK, MUTUAL, ROOT;
60+
61+
/**
62+
* Indicates that this type of account has an inverted state for credits and debits.
63+
* Credits decrease the account balance, while debits increase it.
64+
*/
65+
private boolean mInvertedCredit = false;
66+
67+
private AccountType(boolean invertedCredit){
68+
mInvertedCredit = invertedCredit;
69+
}
70+
71+
private AccountType() {
72+
//nothing to see here, move along
73+
}
74+
75+
public boolean hasInvertedCredit(){
76+
return mInvertedCredit;
77+
}
78+
};
5979

6080
/**
6181
* Accounts types which are used by the OFX standard

app/src/org/gnucash/android/db/AccountsDbAdapter.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,17 @@ public AccountType getAccountType(String uid){
285285
}
286286
return AccountType.valueOf(type);
287287
}
288-
289-
/**
288+
289+
/**
290+
* Overloaded method. Resolves the account unique ID from the row ID and makes a call to {@link #getAccountType(String)}
291+
* @param accountId Database row ID of the account
292+
* @return {@link AccountType} of the account
293+
*/
294+
public AccountType getAccountType(long accountId){
295+
return getAccountType(getAccountUID(accountId));
296+
}
297+
298+
/**
290299
* Returns the name of the account with id <code>accountID</code>
291300
* @param accountID Database ID of the account record
292301
* @return Name of the account

app/src/org/gnucash/android/ui/transactions/NewTransactionFragment.java

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import android.widget.*;
2828
import org.gnucash.android.R;
29+
import org.gnucash.android.data.Account;
2930
import org.gnucash.android.data.Money;
3031
import org.gnucash.android.data.Transaction;
3132
import org.gnucash.android.data.Transaction.TransactionType;
@@ -173,6 +174,12 @@ public class NewTransactionFragment extends SherlockFragment implements
173174
*/
174175
boolean mAmountManuallyEdited = false;
175176

177+
/**
178+
* The AccountType of the account to which this transaction belongs.
179+
* Used for determining the accounting rules for credits and debits
180+
*/
181+
Account.AccountType mAccountType;
182+
176183
/**
177184
* Create the view and retrieve references to the UI elements
178185
*/
@@ -215,8 +222,12 @@ public void onActivityCreated(Bundle savedInstanceState) {
215222
long transactionId = getArguments().getLong(SELECTED_TRANSACTION_ID);
216223
mTransactionsDbAdapter = new TransactionsDbAdapter(getActivity());
217224
mTransaction = mTransactionsDbAdapter.getTransaction(transactionId);
218-
219-
setListeners();
225+
226+
final long accountId = getArguments().getLong(TransactionsListFragment.SELECTED_ACCOUNT_ID);
227+
mAccountType = mAccountsDbAdapter.getAccountType(accountId);
228+
toggleTransactionTypeState();
229+
230+
setListeners();
220231
if (mTransaction == null)
221232
initalizeViews();
222233
else {
@@ -229,6 +240,22 @@ public void onActivityCreated(Bundle savedInstanceState) {
229240
initTransactionNameAutocomplete();
230241
}
231242

243+
private void toggleTransactionTypeState() {
244+
switch (mAccountType) {
245+
case ASSET:
246+
case EXPENSE:
247+
mTransactionTypeButton.setTextOff(getString(R.string.label_debit));
248+
mTransactionTypeButton.setTextOn(getString(R.string.label_credit));
249+
break;
250+
251+
default:
252+
mTransactionTypeButton.setTextOff(getString(R.string.label_credit));
253+
mTransactionTypeButton.setTextOn(getString(R.string.label_debit));
254+
break;
255+
}
256+
mTransactionTypeButton.invalidate();
257+
}
258+
232259
/**
233260
* Initializes the transaction name field for autocompletion with existing transaction names in the database
234261
*/
@@ -276,7 +303,6 @@ public void onItemClick(AdapterView<?> adapterView, View view, int position, lon
276303
* This method is called if the fragment is used for editing a transaction
277304
*/
278305
private void initializeViewsWithTransaction(){
279-
280306
mNameEditText.setText(mTransaction.getName());
281307
mTransactionTypeButton.setChecked(mTransaction.getTransactionType() == TransactionType.DEBIT);
282308
if (!mAmountManuallyEdited){
@@ -315,11 +341,19 @@ private void initalizeViews() {
315341
mDateTextView.setText(DATE_FORMATTER.format(time));
316342
mTimeTextView.setText(TIME_FORMATTER.format(time));
317343
mTime = mDate = Calendar.getInstance();
318-
344+
319345
String typePref = PreferenceManager.getDefaultSharedPreferences(getActivity()).getString(getString(R.string.key_default_transaction_type), "DEBIT");
320346
if (typePref.equals("CREDIT")){
321-
mTransactionTypeButton.setChecked(false);
322-
}
347+
if (mAccountType == Account.AccountType.ASSET || mAccountType == Account.AccountType.EXPENSE)
348+
mTransactionTypeButton.setChecked(false);
349+
else
350+
mTransactionTypeButton.setChecked(true);
351+
} else {
352+
if (mAccountType == Account.AccountType.ASSET || mAccountType == Account.AccountType.EXPENSE)
353+
mTransactionTypeButton.setChecked(true);
354+
else
355+
mTransactionTypeButton.setChecked(false);
356+
}
323357

324358
final long accountId = getArguments().getLong(TransactionsListFragment.SELECTED_ACCOUNT_ID);
325359
String code = Money.DEFAULT_CURRENCY_CODE;
@@ -455,7 +489,16 @@ public void onAccountChanged(long newAccountId){
455489
String currencyCode = accountsDbAdapter.getCurrencyCode(newAccountId);
456490
Currency currency = Currency.getInstance(currencyCode);
457491
mCurrencyTextView.setText(currency.getSymbol(Locale.getDefault()));
458-
492+
493+
Account.AccountType previousAccountType = mAccountType;
494+
mAccountType = accountsDbAdapter.getAccountType(newAccountId);
495+
toggleTransactionTypeState();
496+
497+
//if the new account has a different credit/debit philosophy as the previous one, then toggle the button
498+
if (mAccountType.hasInvertedCredit() != previousAccountType.hasInvertedCredit()){
499+
mTransactionTypeButton.toggle();
500+
}
501+
459502
updateTransferAccountsList();
460503
}
461504

@@ -478,7 +521,11 @@ private void saveNewTransaction() {
478521
long accountID = ((TransactionsActivity) getSherlockActivity()).getCurrentAccountID();
479522
Currency currency = Currency.getInstance(mTransactionsDbAdapter.getCurrencyCode(accountID));
480523
Money amount = new Money(amountBigd, currency);
481-
TransactionType type = mTransactionTypeButton.isChecked() ? TransactionType.DEBIT : TransactionType.CREDIT;
524+
TransactionType type;
525+
if (mAccountType.hasInvertedCredit()){
526+
type = amount.isNegative() ? TransactionType.CREDIT : TransactionType.DEBIT;
527+
} else
528+
type = amount.isNegative() ? TransactionType.DEBIT : TransactionType.CREDIT;
482529
if (mTransaction != null){
483530
mTransaction.setAmount(amount);
484531
mTransaction.setName(name);

app/src/org/gnucash/android/ui/transactions/TransactionsActivity.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ protected void onCreate(Bundle savedInstanceState) {
170170
if (transactionId > 0) {
171171
mSectionHeaderTransactions.setText(R.string.title_edit_transaction);
172172
args.putLong(NewTransactionFragment.SELECTED_TRANSACTION_ID, transactionId);
173+
args.putLong(TransactionsListFragment.SELECTED_ACCOUNT_ID, mAccountId);
173174
} else {
174175
mSectionHeaderTransactions.setText(R.string.title_add_transaction);
175176
args.putLong(TransactionsListFragment.SELECTED_ACCOUNT_ID, mAccountId);

0 commit comments

Comments
 (0)