Skip to content

Commit

Permalink
Feature: Delete account hierarchy (as option in delete confirmation d…
Browse files Browse the repository at this point in the history
…ialog)

Improved: Broaden the mime type of accepted files during import. This should enable selecting the import file with a wider range of apps
Fixed: Crash when deleting account from account list. The reloading of the list is now less jarring and more smooth as it should be
Fixed: Account color displayed on wrong account (due to view reuse)
  • Loading branch information
codinguser committed Jan 25, 2014
1 parent de981a1 commit f00a975
Show file tree
Hide file tree
Showing 18 changed files with 101 additions and 28 deletions.
7 changes: 7 additions & 0 deletions app/res/layout/dialog_account_delete.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>

<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/checkbox_delete_sub_accounts"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/label_delete_sub_accounts" />
1 change: 1 addition & 0 deletions app/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -377,4 +377,5 @@
</string-array>
<!-- Default title for color picker dialog [CHAR LIMIT=30] -->
<string name="color_picker_default_title">Select a Color</string>
<string name="label_delete_sub_accounts">Delete sub-accounts</string>
</resources>
1 change: 1 addition & 0 deletions app/res/values-el/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -391,4 +391,5 @@
</string-array>
<!-- Default title for color picker dialog [CHAR LIMIT=30] -->
<string name="color_picker_default_title">Select a Color</string>
<string name="label_delete_sub_accounts">Delete sub-accounts</string>
</resources>
1 change: 1 addition & 0 deletions app/res/values-es-rMX/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -375,4 +375,5 @@
</string-array>
<!-- Default title for color picker dialog [CHAR LIMIT=30] -->
<string name="color_picker_default_title">Select a Color</string>
<string name="label_delete_sub_accounts">Delete sub-accounts</string>
</resources>
1 change: 1 addition & 0 deletions app/res/values-es/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -375,4 +375,5 @@
</string-array>
<!-- Default title for color picker dialog [CHAR LIMIT=30] -->
<string name="color_picker_default_title">Select a Color</string>
<string name="label_delete_sub_accounts">Delete sub-accounts</string>
</resources>
1 change: 1 addition & 0 deletions app/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -373,4 +373,5 @@
</string-array>
<!-- Default title for color picker dialog [CHAR LIMIT=30] -->
<string name="color_picker_default_title">Select a Color</string>
<string name="label_delete_sub_accounts">Delete sub-accounts</string>
</resources>
1 change: 1 addition & 0 deletions app/res/values-hu/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -376,4 +376,5 @@
</string-array>
<!-- Default title for color picker dialog [CHAR LIMIT=30] -->
<string name="color_picker_default_title">Select a Color</string>
<string name="label_delete_sub_accounts">Delete sub-accounts</string>
</resources>
1 change: 1 addition & 0 deletions app/res/values-it/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -376,4 +376,5 @@
</string-array>
<!-- Default title for color picker dialog [CHAR LIMIT=30] -->
<string name="color_picker_default_title">Select a Color</string>
<string name="label_delete_sub_accounts">Delete sub-accounts</string>
</resources>
1 change: 1 addition & 0 deletions app/res/values-nb/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -378,4 +378,5 @@ format og importeres i regnskapsprogrammet GnuCash for PC.</string>
</string-array>
<!-- Default title for color picker dialog [CHAR LIMIT=30] -->
<string name="color_picker_default_title">Select a Color</string>
<string name="label_delete_sub_accounts">Delete sub-accounts</string>
</resources>
1 change: 1 addition & 0 deletions app/res/values-nl/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -377,4 +377,5 @@
</string-array>
<!-- Default title for color picker dialog [CHAR LIMIT=30] -->
<string name="color_picker_default_title">Select a Color</string>
<string name="label_delete_sub_accounts">Delete sub-accounts</string>
</resources>
1 change: 1 addition & 0 deletions app/res/values-pt-rBR/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -375,4 +375,5 @@
</string-array>
<!-- Default title for color picker dialog [CHAR LIMIT=30] -->
<string name="color_picker_default_title">Select a Color</string>
<string name="label_delete_sub_accounts">Delete sub-accounts</string>
</resources>
1 change: 1 addition & 0 deletions app/res/values-ru/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -373,4 +373,5 @@
</string-array>
<!-- Default title for color picker dialog [CHAR LIMIT=30] -->
<string name="color_picker_default_title">Select a Color</string>
<string name="label_delete_sub_accounts">Delete sub-accounts</string>
</resources>
1 change: 1 addition & 0 deletions app/res/values-zh/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -373,4 +373,5 @@
</string-array>
<!-- Default title for color picker dialog [CHAR LIMIT=30] -->
<string name="color_picker_default_title">Select a Color</string>
<string name="label_delete_sub_accounts">Delete sub-accounts</string>
</resources>
1 change: 1 addition & 0 deletions app/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -610,4 +610,5 @@
<!-- Content description for a selected color square. -->
<string name="color_swatch_description_selected">Color <xliff:g id="color_index" example="14">%1$d</xliff:g> selected</string>
<string name="label_account_color_and_type">Account Color &amp; Type</string>
<string name="label_delete_sub_accounts">Delete sub-accounts</string>
</resources>
60 changes: 51 additions & 9 deletions app/src/org/gnucash/android/db/AccountsDbAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,21 @@ public long addAccount(Account account){
return rowId;
}

/**
* This feature goes through all the rows in the accounts and changes value for <code>columnKey</code> to <code>newValue</code><br/>
* The <code>newValue</code> parameter is taken as string since SQLite typically stores everything as text.
* <p><b>This method affects all rows, exercise caution when using it</b></p>
* @param columnKey Column name to be changed
* @param newValue New value to be assigned to the columnKey
* @return Number of records affected
*/
public int updateAccounts(String columnKey, String newValue){
ContentValues contentValues = new ContentValues();
contentValues.put(columnKey, newValue);

return mDb.update(DatabaseHelper.ACCOUNTS_TABLE_NAME, contentValues, null, null);
}

/**
* Deletes an account with database id <code>rowId</code>
* All the transactions in the account will also be deleted
Expand Down Expand Up @@ -143,28 +158,47 @@ public int reassignParent(String oldParentUID, String newParentUID){
* Deletes an account while preserving the linked transactions
* Reassigns all transactions belonging to the account with id <code>rowId</code> to
* the account with id <code>accountReassignId</code> before deleting the account.
* @param rowIdToDelete
* @param accountReassignId
* @param accountId Database record ID of the account to be deleted
* @param accountReassignId Record ID of the account to which to reassign the transactions from the previous
* @return <code>true</code> if deletion was successful, <code>false</code> otherwise.
*/
public boolean transactionPreservingDelete(long rowIdToDelete, long accountReassignId){
public boolean transactionPreservingDelete(long accountId, long accountReassignId){
Cursor transactionsCursor = mDb.query(DatabaseHelper.TRANSACTIONS_TABLE_NAME,
new String[]{DatabaseHelper.KEY_ACCOUNT_UID},
DatabaseHelper.KEY_ACCOUNT_UID + " = " + rowIdToDelete,
DatabaseHelper.KEY_ACCOUNT_UID + " = " + accountId,
null, null, null, null);
if (transactionsCursor != null && transactionsCursor.getCount() > 0){
Log.d(TAG, "Found transactions. Migrating to new account");
ContentValues contentValues = new ContentValues();
contentValues.put(DatabaseHelper.KEY_ACCOUNT_UID, accountReassignId);
mDb.update(DatabaseHelper.TRANSACTIONS_TABLE_NAME,
contentValues,
DatabaseHelper.KEY_ACCOUNT_UID + "=" + rowIdToDelete,
DatabaseHelper.KEY_ACCOUNT_UID + "=" + accountId,
null);
transactionsCursor.close();
}
return destructiveDeleteAccount(rowIdToDelete);
return destructiveDeleteAccount(accountId);
}


/**
* Deletes an account and all its sub-accounts and transactions with it
* @param accountId Database record ID of account
* @return <code>true</code> if the account and subaccounts were all successfully deleted, <code>false</code> if
* even one was not deleted
*/
public boolean recursiveDestructiveDelete(long accountId){
Log.d(TAG, "Delete account with rowId with its transactions and sub-accounts: " + accountId);
boolean result = true;

List<Long> subAccountIds = getSubAccountIds(accountId);
for (long subAccountId : subAccountIds) {
result |= recursiveDestructiveDelete(subAccountId);
}
result |= destructiveDeleteAccount(accountId);

return result;
}

/**
* Builds an account instance with the provided cursor.
* The cursor should already be pointing to the account record in the database
Expand Down Expand Up @@ -433,7 +467,9 @@ public Cursor fetchAccounts(String condition){
* @return Account Balance of an account including sub-accounts
*/
public Money getAccountBalance(long accountId){
Money balance = Money.createInstance(getCurrencyCode(accountId));
String currencyCode = getCurrencyCode(accountId);
currencyCode = currencyCode == null ? Money.DEFAULT_CURRENCY_CODE : currencyCode;
Money balance = Money.createInstance(currencyCode);

List<Long> subAccounts = getSubAccountIds(accountId);
for (long id : subAccounts){
Expand Down Expand Up @@ -529,7 +565,10 @@ public int getSubAccountCount(long accountId){

String queryCount = "SELECT COUNT(*) FROM " + DatabaseHelper.ACCOUNTS_TABLE_NAME + " WHERE "
+ DatabaseHelper.KEY_PARENT_ACCOUNT_UID + " = ?";
Cursor cursor = mDb.rawQuery(queryCount, new String[]{getAccountUID(accountId)});
String accountUID = getAccountUID(accountId);
if (accountUID == null) //if the account UID is null, then the accountId param was invalid. Just return
return 0;
Cursor cursor = mDb.rawQuery(queryCount, new String[]{accountUID});
cursor.moveToFirst();
int count = cursor.getInt(0);
cursor.close();
Expand Down Expand Up @@ -677,6 +716,9 @@ public String getFullyQualifiedAccountName(long accountId){
* @return <code>true</code> if the account is a placeholder account, <code>false</code> otherwise
*/
public boolean isPlaceholderAccount(String accountUID){
if (accountUID == null)
return false;

Cursor cursor = mDb.query(DatabaseHelper.ACCOUNTS_TABLE_NAME,
new String[]{DatabaseHelper.KEY_ROW_ID, DatabaseHelper.KEY_PLACEHOLDER},
DatabaseHelper.KEY_UID + " = ?",
Expand Down
1 change: 0 additions & 1 deletion app/src/org/gnucash/android/export/qif/QifHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ public static String getQifHeader(Account.AccountType accountType){
* @return Imbalance account name
*/
public static String getImbalanceAccountName(Currency currency){
//TODO: localize this in the future
return GnuCashApplication.getAppContext().getString(R.string.imbalance_account_name) + "-" + currency.getCurrencyCode();
}
}
44 changes: 27 additions & 17 deletions app/src/org/gnucash/android/ui/accounts/AccountsListFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -286,26 +286,28 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
*/
public void tryDeleteAccount(long rowId) {
Account acc = mAccountsDbAdapter.getAccount(rowId);
if (acc.getTransactionCount() > 0) {
if (acc.getTransactionCount() > 0 || mAccountsDbAdapter.getSubAccountCount(rowId) > 0) {
showConfirmationDialog(rowId);
} else {
deleteAccount(rowId);
deleteAccount(rowId, false);
}
}

/**
* Deletes an account and show a {@link Toast} notification on success
*
* Deletes an account and show a {@link Toast} notification on success.
* When an account is deleted, all it's child accounts will be reassigned as children to its parent account
* @param rowId Record ID of the account to be deleted
*/
protected void deleteAccount(long rowId) {
protected void deleteAccount(long rowId, boolean deleteSubAccounts) {
String accountUID = mAccountsDbAdapter.getAccountUID(rowId);
boolean deleted = mAccountsDbAdapter.destructiveDeleteAccount(rowId);
String parentUID = mAccountsDbAdapter.getParentAccountUID(rowId);
boolean deleted = deleteSubAccounts ?
mAccountsDbAdapter.recursiveDestructiveDelete(rowId)
: mAccountsDbAdapter.destructiveDeleteAccount(rowId);
if (deleted) {
mAccountsDbAdapter.reassignParent(accountUID, null);
mAccountsDbAdapter.reassignParent(accountUID, parentUID);
Toast.makeText(getActivity(), R.string.toast_account_deleted, Toast.LENGTH_SHORT).show();
WidgetConfigurationActivity.updateAllWidgets(getActivity().getApplicationContext());
getLoaderManager().destroyLoader(0);
}
refresh();
}
Expand Down Expand Up @@ -548,10 +550,12 @@ public static DeleteConfirmationDialogFragment newInstance(int title, long id) {
public Dialog onCreateDialog(Bundle savedInstanceState) {
int title = getArguments().getInt("title");
final long rowId = getArguments().getLong(TransactionsListFragment.SELECTED_ACCOUNT_ID);

return new AlertDialog.Builder(getActivity())
LayoutInflater layoutInflater = getSherlockActivity().getLayoutInflater();
final View dialogLayout = layoutInflater.inflate(R.layout.dialog_account_delete, (ViewGroup) getView());
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity())
.setIcon(android.R.drawable.ic_delete)
.setTitle(title).setMessage(R.string.delete_account_confirmation_message)
.setView(dialogLayout)
.setPositiveButton(R.string.alert_dialog_ok_delete,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
Expand All @@ -561,21 +565,25 @@ public void onClick(DialogInterface dialog, int whichButton) {
accountsDbAdapter.deleteAllRecords();
accountsDbAdapter.close();
Toast.makeText(context, R.string.toast_all_accounts_deleted, Toast.LENGTH_SHORT).show();
} else
((AccountsListFragment) getTargetFragment()).deleteAccount(rowId);
} else {
CheckBox deleteSubAccountsCheckBox = (CheckBox) dialogLayout
.findViewById(R.id.checkbox_delete_sub_accounts);
((AccountsListFragment) getTargetFragment()).deleteAccount(rowId, deleteSubAccountsCheckBox.isChecked());
}
}
}
)
})
.setNegativeButton(R.string.alert_dialog_cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dismiss();
}
}
)
.create();

);
return dialogBuilder.create();
}

}
}

/**
* Extends {@link DatabaseCursorLoader} for loading of {@link Account} from the
Expand Down Expand Up @@ -679,6 +687,8 @@ public void bindView(View v, Context context, Cursor cursor) {
if (accountColor != null){
int color = Color.parseColor(accountColor);
colorStripView.setBackgroundColor(color);
} else {
colorStripView.setBackgroundColor(Color.TRANSPARENT);
}

boolean isPlaceholderAccount = mAccountsDbAdapter.isPlaceholderAccount(accountId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@
import org.gnucash.android.R;
import org.gnucash.android.data.Money;
import org.gnucash.android.db.AccountsDbAdapter;
import org.gnucash.android.db.DatabaseHelper;
import org.gnucash.android.db.TransactionsDbAdapter;
import org.gnucash.android.ui.accounts.AccountsActivity;
import org.gnucash.android.ui.accounts.AccountsListFragment;

import java.util.Currency;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
Expand Down Expand Up @@ -221,7 +223,7 @@ public void run() {

public void importAccounts() {
Intent pickIntent = new Intent(Intent.ACTION_GET_CONTENT);
pickIntent.setType("application/octet-stream");
pickIntent.setType("application/*");
Intent chooser = Intent.createChooser(pickIntent, "Select GnuCash account file");

startActivityForResult(chooser, AccountsListFragment.REQUEST_PICK_ACCOUNTS_FILE);
Expand Down

0 comments on commit f00a975

Please sign in to comment.