X-Git-Url: https://git.ktnx.net/?p=mobile-ledger.git;a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fnet%2Fktnx%2Fmobileledger%2FNewTransactionActivity.java;h=853fd0a698b30c441bfe5838dd20f3419d0db3d8;hp=3e4b73ccc2b7e2da4c132cd45fd3fae611f3cc2c;hb=1c31cec3c678668cedf3d4e71ed51863b1d14489;hpb=e7f868db998a495e26167c3406818ba336d6f863 diff --git a/app/src/main/java/net/ktnx/mobileledger/NewTransactionActivity.java b/app/src/main/java/net/ktnx/mobileledger/NewTransactionActivity.java index 3e4b73cc..853fd0a6 100644 --- a/app/src/main/java/net/ktnx/mobileledger/NewTransactionActivity.java +++ b/app/src/main/java/net/ktnx/mobileledger/NewTransactionActivity.java @@ -1,5 +1,6 @@ package net.ktnx.mobileledger; +import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.database.Cursor; import android.database.MatrixCursor; @@ -8,6 +9,7 @@ import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; import android.provider.FontsContract; +import android.support.design.widget.BaseTransientBottomBar; import android.support.design.widget.Snackbar; import android.support.v4.app.DialogFragment; import android.support.v7.app.AppCompatActivity; @@ -17,6 +19,7 @@ import android.text.InputType; import android.text.TextWatcher; import android.util.Log; import android.util.TypedValue; +import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; @@ -30,21 +33,19 @@ import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; +import java.util.Date; import java.util.Objects; /* * TODO: auto-fill of transaction description * if Android O's implementation won't work, add a custom one * TODO: nicer progress while transaction is submitted - * TODO: periodic and manual refresh of available accounts - * (now done forcibly each time the main activity is started) * TODO: latest transactions, maybe with browsing further in the past? * TODO: reports * TODO: get rid of the custom session/cookie and auth code? * (the last problem with the POST was the missing content-length header) * TODO: app icon * TODO: nicer swiping removal with visual feedback - * TODO: activity with current balance * TODO: setup wizard * TODO: update accounts/check settings upon change of backend settings * */ @@ -65,8 +66,16 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal setSupportActionBar(toolbar); text_date = findViewById(R.id.new_transaction_date); + text_date.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public + void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) pickTransactionDate(v); + } + }); text_descr = findViewById(R.id.new_transaction_description); hook_autocompletion_adapter(text_descr, MobileLedgerDB.DESCRIPTION_HISTORY_TABLE, "description"); + hook_text_change_listener(text_descr); progress = findViewById(R.id.save_transaction_progress); @@ -108,7 +117,9 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal saver = new SaveTransactionTask(this); saver.setPref(PreferenceManager.getDefaultSharedPreferences(this)); - LedgerTransaction tr = new LedgerTransaction(text_date.getText().toString(), text_descr.getText().toString()); + String date = text_date.getText().toString(); + if (date.isEmpty()) date = String.valueOf(new Date().getDate()); + LedgerTransaction tr = new LedgerTransaction(date, text_descr.getText().toString()); TableLayout table = findViewById(R.id.new_transaction_accounts_table); for ( int i = 0; i < table.getChildCount(); i++ ) { @@ -202,7 +213,7 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal "SELECT %s as a, case when %s_upper LIKE ?||'%%' then 1 " + "WHEN %s_upper LIKE '%%:'||?||'%%' then 2 " + "WHEN %s_upper LIKE '%% '||?||'%%' then 3 " + "else 9 end " + - "FROM %s " + "WHERE %s_upper LIKE " + "'%%'||?||'%%' " + + "FROM %s " + "WHERE %s_upper LIKE '%%'||?||'%%' " + "ORDER BY 2, 1;", field, field, field, field, table, field), new String[]{str, str, str, str}); @@ -235,6 +246,8 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal mSave = menu.findItem(R.id.action_submit_transaction); if (mSave == null) throw new AssertionError(); + check_transaction_submittable(); + return true; } @@ -254,7 +267,8 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal acc.setWidth(0); final EditText amt = new EditText(this); - amt.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, 1f)); + amt.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, + TableRow.LayoutParams.MATCH_PARENT, 1f)); amt.setHint(R.string.new_transaction_amount_hint); amt.setWidth(0); amt.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED | InputType.TYPE_NUMBER_FLAG_DECIMAL ); @@ -263,6 +277,7 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal final TableRow row = new TableRow(this); row.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.MATCH_PARENT)); + row.setGravity(Gravity.BOTTOM); row.addView(acc); row.addView(amt); table.addView(row); @@ -279,50 +294,110 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal do_add_account_row(true); } + public + void resetTransactionFromMenu(MenuItem item) { + reset_form(); + } + public void saveTransactionFromMenu(MenuItem item) { save_transaction(); } + // rules: + // 1) at least two account names + // 2) each amount must have account name + // 3) amounts must balance to 0, or + // 3a) there must be exactly one empty amount + // 4) empty accounts with empty amounts are ignored + // 5) a row with an empty account name or empty amount is guaranteed to exist + @SuppressLint("DefaultLocale") private void check_transaction_submittable() { TableLayout table = findViewById(R.id.new_transaction_accounts_table); int accounts = 0; int accounts_with_values = 0; + int amounts = 0; + int amounts_with_accounts = 0; int empty_rows = 0; - for(int i = 0; i < table.getChildCount(); i++ ) { - TableRow row = (TableRow) table.getChildAt(i); + TextView empty_amount = null; + boolean single_empty_amount = false; + float running_total = 0f; + boolean have_description = + !((TextView) findViewById(R.id.new_transaction_description)).getText().toString() + .isEmpty(); + + try { + for (int i = 0; i < table.getChildCount(); i++) { + TableRow row = (TableRow) table.getChildAt(i); + + TextView acc_name_v = (TextView) row.getChildAt(0); + TextView amount_v = (TextView) row.getChildAt(1); + String amt = String.valueOf(amount_v.getText()); + String acc_name = String.valueOf(acc_name_v.getText()); + acc_name = acc_name.trim(); - TextView acc_name_v = (TextView) row.getChildAt(0); + if (!acc_name.isEmpty()) { + accounts++; - String acc_name = String.valueOf(acc_name_v.getText()); - acc_name = acc_name.trim(); - if (!acc_name.isEmpty()) { - accounts++; + if (!amt.isEmpty()) { + accounts_with_values++; + } + } + else empty_rows++; - TextView amount_v = (TextView) row.getChildAt(1); - String amt = String.valueOf(amount_v.getText()); + if (amt.isEmpty()) { + amount_v.setHint(String.format("%1.2f", 0f)); + if (empty_amount == null) { + empty_amount = amount_v; + single_empty_amount = true; + } + else if (!acc_name.isEmpty()) single_empty_amount = false; + } + else { + amounts++; + if (!acc_name.isEmpty()) amounts_with_accounts++; + running_total += Float.valueOf(amt); + } + } - if (!amt.isEmpty()) accounts_with_values++; - } else empty_rows++; - } + if ((empty_rows == 0) && ((table.getChildCount() == accounts) || (table.getChildCount() + == amounts))) + { + do_add_account_row(false); + } - if (accounts_with_values == accounts && empty_rows == 0) { - do_add_account_row(false); - } + if (have_description && (accounts >= 2) && (accounts_with_values >= (accounts - 1)) && ( + amounts_with_accounts == amounts)) + { + if (mSave != null) mSave.setVisible(true); + } + else if (mSave != null) mSave.setVisible(false); - if ((accounts >= 2) && (accounts_with_values >= (accounts - 1))) { - if (mSave != null) mSave.setVisible(true); - } else { + if (single_empty_amount) { + empty_amount + .setHint(String.format("%1.2f", (running_total > 0) ? -running_total : 0f)); + } + } + catch (NumberFormatException e) { + if (mSave != null) mSave.setVisible(false); + } + catch (Exception e) { + e.printStackTrace(); if (mSave != null) mSave.setVisible(false); } } @Override - public void done() { + public + void done(String error) { progress.setVisibility(View.INVISIBLE); Log.d("visuals", "hiding progress"); - reset_form(); + if (error == null) reset_form(); + else Snackbar.make(findViewById(R.id.new_transaction_accounts_table), error, + BaseTransientBottomBar.LENGTH_LONG).show(); + toggle_all_editing(true); + check_transaction_submittable(); } private void reset_form() {