Java tutorial
/* * Copyright (C) 2012-2016 The Android Money Manager Ex Project Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.money.manager.ex.recurring.transactions; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import com.codetroopers.betterpickers.calendardatepicker.CalendarDatePickerDialogFragment; import com.money.manager.ex.Constants; import com.money.manager.ex.MoneyManagerApplication; import com.money.manager.ex.R; import com.money.manager.ex.common.events.AmountEnteredEvent; import com.money.manager.ex.core.NumericHelper; import com.money.manager.ex.core.UIHelper; import com.money.manager.ex.database.ISplitTransaction; import com.money.manager.ex.datalayer.SplitRecurringCategoriesRepository; import com.money.manager.ex.domainmodel.RecurringTransaction; import com.money.manager.ex.domainmodel.SplitRecurringCategory; import com.money.manager.ex.servicelayer.RecurringTransactionService; import com.money.manager.ex.datalayer.AccountRepository; import com.money.manager.ex.datalayer.RecurringTransactionRepository; import com.money.manager.ex.transactions.EditTransactionCommonFunctions; import com.money.manager.ex.core.Core; import com.money.manager.ex.core.TransactionTypes; import com.money.manager.ex.common.BaseFragmentActivity; import com.money.manager.ex.transactions.events.DialogNegativeClickedEvent; import com.money.manager.ex.transactions.events.DialogPositiveClickedEvent; import com.money.manager.ex.utils.MmxDateTimeUtils; import com.shamanland.fonticon.FontIconView; import com.squareup.sqlbrite.BriteDatabase; import org.greenrobot.eventbus.Subscribe; import org.joda.time.DateTime; import org.parceler.Parcels; import javax.inject.Inject; import timber.log.Timber; /** * Recurring transactions are stored in BillsDeposits table. */ public class RecurringTransactionEditActivity extends BaseFragmentActivity { // private static final String LOGCAT = RecurringTransactionEditActivity.class.getSimpleName(); public static final String KEY_MODEL = "RecurringTransactionEditActivity:Model"; public static final String KEY_BILL_DEPOSITS_ID = "RepeatingTransaction:BillDepositsId"; public static final String KEY_ACCOUNT_ID = "RepeatingTransaction:AccountId"; public static final String KEY_TO_ACCOUNT_NAME = "RepeatingTransaction:ToAccountName"; public static final String KEY_TRANS_CODE = "RepeatingTransaction:TransCode"; public static final String KEY_TRANS_STATUS = "RepeatingTransaction:TransStatus"; public static final String KEY_PAYEE_NAME = "RepeatingTransaction:PayeeName"; public static final String KEY_CATEGORY_NAME = "RepeatingTransaction:CategoryName"; public static final String KEY_SUBCATEGORY_NAME = "RepeatingTransaction:SubCategoryName"; public static final String KEY_NOTES = "RepeatingTransaction:Notes"; public static final String KEY_TRANS_NUMBER = "RepeatingTransaction:TransNumber"; public static final String KEY_SPLIT_TRANSACTION = "RepeatingTransaction:SplitCategory"; public static final String KEY_SPLIT_TRANSACTION_DELETED = "RepeatingTransaction:SplitTransactionDeleted"; public static final String KEY_ACTION = "RepeatingTransaction:Action"; public static final String TAG_DATEPICKER = "DatePicker"; @Inject BriteDatabase database; private String mIntentAction; // Form controls private RecurringTransactionViewHolder mViewHolder; private EditTransactionCommonFunctions mCommonFunctions; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_edit_recurring_transaction); MoneyManagerApplication.getApp().iocComponent.inject(this); RecurringTransaction tx = initializeModel(); mCommonFunctions = new EditTransactionCommonFunctions(this, tx, database); showStandardToolbarActions(); // manage update instance if (savedInstanceState != null) { restoreInstanceState(savedInstanceState); } // manage intent if (getIntent() != null) { if (savedInstanceState == null) { String action = getIntent().getAction(); if (action != null && action.equals(Intent.ACTION_EDIT)) { int id = getIntent().getIntExtra(KEY_BILL_DEPOSITS_ID, Constants.NOT_SET); // select data transaction loadRecurringTransaction(id); } else { mCommonFunctions.transactionEntity .setAccountId(getIntent().getIntExtra(KEY_ACCOUNT_ID, Constants.NOT_SET)); } } mIntentAction = getIntent().getAction(); // set title if (getSupportActionBar() != null) { getSupportActionBar() .setTitle(Intent.ACTION_INSERT.equals(mIntentAction) ? R.string.new_repeating_transaction : R.string.edit_repeating_transaction); } } // Controls initializeViewHolder(); initializeControls(); // refresh user interface mCommonFunctions.onTransactionTypeChanged(mCommonFunctions.transactionEntity.getTransactionType()); mCommonFunctions.showPayeeName(); mCommonFunctions.displayCategoryName(); showPaymentsLeft(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { mCommonFunctions.onActivityResult(requestCode, resultCode, data); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putParcelable(KEY_MODEL, Parcels.wrap(mCommonFunctions.transactionEntity)); // update the state interface outState.putString(KEY_TO_ACCOUNT_NAME, mCommonFunctions.mToAccountName); outState.putString(KEY_TRANS_CODE, mCommonFunctions.getTransactionType()); outState.putString(KEY_TRANS_STATUS, mCommonFunctions.transactionEntity.getStatus()); outState.putString(KEY_PAYEE_NAME, mCommonFunctions.payeeName); outState.putString(KEY_CATEGORY_NAME, mCommonFunctions.categoryName); outState.putString(KEY_SUBCATEGORY_NAME, mCommonFunctions.subCategoryName); outState.putString(KEY_TRANS_NUMBER, mCommonFunctions.viewHolder.edtTransNumber.getText().toString()); outState.putParcelable(KEY_SPLIT_TRANSACTION, Parcels.wrap(mCommonFunctions.mSplitTransactions)); outState.putParcelable(KEY_SPLIT_TRANSACTION_DELETED, Parcels.wrap(mCommonFunctions.mSplitTransactionsDeleted)); outState.putString(KEY_NOTES, String.valueOf(mCommonFunctions.viewHolder.edtNotes.getTag())); outState.putString(KEY_ACTION, mIntentAction); } @Override public boolean onActionCancelClick() { return mCommonFunctions.onActionCancelClick(); } @Override public void onBackPressed() { onActionCancelClick(); } @Override public boolean onActionDoneClick() { if (saveData()) { // set result ok, send broadcast to update widgets and finish activity setResult(RESULT_OK); finish(); } return super.onActionDoneClick(); } // Events @Subscribe public void onEvent(AmountEnteredEvent event) { int id = Integer.parseInt(event.requestId); mCommonFunctions.onFinishedInputAmountDialog(id, event.amount); } @Subscribe public void onEvent(DialogPositiveClickedEvent event) { mCommonFunctions.confirmDeletingCategories(); } @Subscribe public void onEvent(DialogNegativeClickedEvent event) { mCommonFunctions.cancelChangingTransactionToTransfer(); } // Public /** * refresh the UI control Payments Left */ public void showPaymentsLeft() { Recurrence recurrence = getRecurringTransaction().getRecurrence(); // Recurrence label mViewHolder.recurrenceLabel.setText( (recurrence == Recurrence.IN_X_DAYS) || (recurrence == Recurrence.IN_X_MONTHS) ? R.string.activates : R.string.occurs); // Payments Left header mViewHolder.paymentsLeftTextView.setVisibility(recurrence.getValue() > 0 ? View.VISIBLE : View.GONE); mViewHolder.paymentsLeftTextView .setText(recurrence.getValue() >= 11 ? R.string.activates : R.string.payments_left); // Payments Left input mViewHolder.paymentsLeftEditText.setVisibility(recurrence.getValue() > 0 ? View.VISIBLE : View.GONE); mViewHolder.paymentsLeftEditText .setHint(recurrence.getValue() >= 11 ? R.string.activates : R.string.payments_left); Integer occurrences = getRecurringTransaction().getPaymentsLeft(); if (occurrences == null) { occurrences = Constants.NOT_SET; getRecurringTransaction().setPaymentsLeft(Constants.NOT_SET); } String value = occurrences == Constants.NOT_SET ? "" : Integer.toString(occurrences); mViewHolder.paymentsLeftEditText.setText(value); // if (mRecurringTransaction.getPaymentsLeft() != null && mRecurringTransaction.getPaymentsLeft() >= 0) { // mViewHolder.paymentsLeftEditText.setText(Integer.toString(mRecurringTransaction.getPaymentsLeft())); // } } // Private private RecurringTransaction getRecurringTransaction() { return (RecurringTransaction) mCommonFunctions.transactionEntity; } private void initializeControls() { // Payment Date initializePaymentDateSelector(); // Account(s) mCommonFunctions.initAccountSelectors(); // Transaction type mCommonFunctions.initTransactionTypeSelector(); // status mCommonFunctions.initStatusSelector(); // Payee mCommonFunctions.initPayeeControls(); // Category mCommonFunctions.initCategoryControls(SplitRecurringCategory.class.getSimpleName()); // Split Categories mCommonFunctions.initSplitCategories(); // mark checked if there are existing split categories. boolean hasSplit = mCommonFunctions.hasSplitCategories(); mCommonFunctions.setSplit(hasSplit); // Amount and total amount mCommonFunctions.initAmountSelectors(); // transaction number mCommonFunctions.initTransactionNumberControls(); // notes mCommonFunctions.initNotesControls(); // Frequency Spinner spinFrequencies = (Spinner) findViewById(R.id.spinnerFrequencies); RecurringTransaction tx = (RecurringTransaction) mCommonFunctions.transactionEntity; Integer recurrence = tx.getRecurrenceInt(); if (recurrence >= 200) { recurrence = recurrence - 200; } // set auto execute without user acknowledgement if (recurrence >= 100) { recurrence = recurrence - 100; } // set auto execute on the next occurrence spinFrequencies.setSelection(recurrence, true); spinFrequencies.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { mCommonFunctions.setDirty(true); getRecurringTransaction().setRecurrence(position); showPaymentsLeft(); } @Override public void onNothingSelected(AdapterView<?> parent) { getRecurringTransaction().setRecurrence(Constants.NOT_SET); showPaymentsLeft(); } }); } private void initializePaymentDateSelector() { if (mViewHolder.paymentDateTextView == null) return; DateTime paymentDate = getRecurringTransaction().getPaymentDate(); mViewHolder.paymentDateTextView.setText(paymentDate.toString(Constants.LONG_DATE_PATTERN)); // mViewHolder.paymentDateTextView.setTag(paymentDate.toString(Constants.ISO_DATE_FORMAT)); mViewHolder.paymentDateTextView.setOnClickListener(new View.OnClickListener() { CalendarDatePickerDialogFragment.OnDateSetListener listener = new CalendarDatePickerDialogFragment.OnDateSetListener() { @Override public void onDateSet(CalendarDatePickerDialogFragment dialog, int year, int monthOfYear, int dayOfMonth) { DateTime dateTime = MmxDateTimeUtils.from(year, monthOfYear + 1, dayOfMonth); setPaymentDate(dateTime); } }; @Override public void onClick(View v) { // Show calendar with the current date selected. DateTime dateTime = getPaymentDate(); CalendarDatePickerDialogFragment datePicker = new CalendarDatePickerDialogFragment() .setFirstDayOfWeek(MmxDateTimeUtils.getFirstDayOfWeek()).setOnDateSetListener(listener) .setPreselectedDate(dateTime.getYear(), dateTime.getMonthOfYear() - 1, dateTime.getDayOfMonth()); if (new UIHelper(RecurringTransactionEditActivity.this).isDarkTheme()) { datePicker.setThemeDark(); } datePicker.show(getSupportFragmentManager(), TAG_DATEPICKER); } }); mViewHolder.paymentPreviousDayButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { DateTime dateTime = getPaymentDate().minusDays(1); setPaymentDate(dateTime); } }); mViewHolder.paymentNextDayButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { DateTime dateTime = getPaymentDate().plusDays(1); setPaymentDate(dateTime); } }); } private RecurringTransaction initializeModel() { RecurringTransaction tx = RecurringTransaction.createInstance(); tx.setDueDate(MmxDateTimeUtils.today()); tx.setPaymentDate(MmxDateTimeUtils.today()); return tx; } private void initializeViewHolder() { // Controls need to be at the beginning as they are referenced throughout the code. mCommonFunctions.findControls(this); mViewHolder = new RecurringTransactionViewHolder(); // Due Date = date mCommonFunctions.initDateSelector(); // Payment Date, next occurrence mViewHolder.paymentDateTextView = (TextView) findViewById(R.id.paymentDateTextView); // Previous/Next day adjustment buttons for the Payment Day mViewHolder.paymentPreviousDayButton = (FontIconView) findViewById(R.id.paymentPreviousDayButton); mViewHolder.paymentNextDayButton = (FontIconView) findViewById(R.id.paymentNextDayButton); // Recurrence label mViewHolder.recurrenceLabel = (TextView) findViewById(R.id.recurrenceLabel); // Payments Left label mViewHolder.paymentsLeftTextView = (TextView) findViewById(R.id.textViewTimesRepeated); // Payments Left text input mViewHolder.paymentsLeftEditText = (EditText) findViewById(R.id.editTextTimesRepeated); } /** * this method allows you to search the transaction data * @param recurringTransactionId transaction id * @return true if data selected, false nothing */ private boolean loadRecurringTransaction(int recurringTransactionId) { RecurringTransactionRepository repo = new RecurringTransactionRepository(this); mCommonFunctions.transactionEntity = repo.load(recurringTransactionId); if (mCommonFunctions.transactionEntity == null) return false; // Read data. String transCode = getRecurringTransaction().getTransactionCode(); mCommonFunctions.transactionEntity.setTransactionType(TransactionTypes.valueOf(transCode)); // load split transactions only if no category selected. if (!mCommonFunctions.transactionEntity.hasCategory() && mCommonFunctions.mSplitTransactions == null) { RecurringTransactionService recurringTransaction = new RecurringTransactionService( recurringTransactionId, this); mCommonFunctions.mSplitTransactions = recurringTransaction.loadSplitTransactions(); } AccountRepository accountRepository = new AccountRepository(this); mCommonFunctions.mToAccountName = accountRepository .loadName(mCommonFunctions.transactionEntity.getAccountToId()); mCommonFunctions.loadPayeeName(mCommonFunctions.transactionEntity.getPayeeId()); mCommonFunctions.loadCategoryName(); return true; } /** * validate data insert in activity * * @return validation result */ private boolean validateData() { if (!mCommonFunctions.validateData()) return false; Core core = new Core(this); // Due Date is required if (TextUtils.isEmpty(getRecurringTransaction().getDueDateString())) { core.alert(R.string.due_date_required); return false; } if (TextUtils.isEmpty(mCommonFunctions.viewHolder.dateTextView.getText().toString())) { core.alert(R.string.error_next_occurrence_not_populate); return false; } // Payments Left must have a value if (getRecurringTransaction().getPaymentsLeft() == null) { core.alert(R.string.payments_left_required); return false; } return true; } private void collectDataFromUI() { String value; // Payment Date // DateTime dateTime = MmxDateTimeUtils.from(mViewHolder.paymentDateTextView.getTag().toString()); // mRecurringTransaction.setPaymentDate(dateTime); // Payments Left value = mViewHolder.paymentsLeftEditText.getText().toString(); if (NumericHelper.isNumeric(value)) { int paymentsLeft = NumericHelper.toInt(value); getRecurringTransaction().setPaymentsLeft(paymentsLeft); } else { getRecurringTransaction().setPaymentsLeft(Constants.NOT_SET); } } /** * update data into database * * @return true if update data successful */ private boolean saveData() { // get data from input controls collectDataFromUI(); if (!validateData()) return false; boolean isTransfer = mCommonFunctions.transactionEntity.getTransactionType() .equals(TransactionTypes.Transfer); if (!isTransfer) { mCommonFunctions.resetTransfer(); } // Transaction. Need the id for split categories. if (!saveTransaction()) return false; // Split Categories if (mCommonFunctions.convertOneSplitIntoRegularTransaction()) { saveTransaction(); } if (!mCommonFunctions.isSplitSelected()) { // Delete any split categories if split is unchecked. mCommonFunctions.removeAllSplitCategories(); } if (!saveSplitCategories()) return false; return true; } private void restoreInstanceState(Bundle savedInstanceState) { // Restore the transaction entity. mCommonFunctions.transactionEntity = Parcels.unwrap(savedInstanceState.getParcelable(KEY_MODEL)); mCommonFunctions.mToAccountName = savedInstanceState.getString(KEY_TO_ACCOUNT_NAME); mCommonFunctions.payeeName = savedInstanceState.getString(KEY_PAYEE_NAME); mCommonFunctions.categoryName = savedInstanceState.getString(KEY_CATEGORY_NAME); mCommonFunctions.subCategoryName = savedInstanceState.getString(KEY_SUBCATEGORY_NAME); mCommonFunctions.mSplitTransactions = Parcels .unwrap(savedInstanceState.getParcelable(KEY_SPLIT_TRANSACTION)); mCommonFunctions.mSplitTransactionsDeleted = Parcels .unwrap(savedInstanceState.getParcelable(KEY_SPLIT_TRANSACTION_DELETED)); // action mIntentAction = savedInstanceState.getString(KEY_ACTION); } private boolean saveSplitCategories() { SplitRecurringCategoriesRepository splitRepo = new SplitRecurringCategoriesRepository(this); // deleted old split transaction if (mCommonFunctions.getDeletedSplitCategories().size() > 0) { if (!mCommonFunctions.deleteMarkedSplits(splitRepo)) return false; } // has split transaction boolean hasSplitCategories = mCommonFunctions.hasSplitCategories(); if (hasSplitCategories) { for (ISplitTransaction item : mCommonFunctions.mSplitTransactions) { SplitRecurringCategory splitEntity = (SplitRecurringCategory) item; splitEntity.setTransId(mCommonFunctions.transactionEntity.getId()); if (splitEntity.getId() == null || splitEntity.getId() == Constants.NOT_SET) { // insert data if (!splitRepo.insert(splitEntity)) { Toast.makeText(getApplicationContext(), R.string.db_checking_insert_failed, Toast.LENGTH_SHORT).show(); Timber.w("Insert new split transaction failed!"); return false; } } else { // update data if (!splitRepo.update(splitEntity)) { Toast.makeText(getApplicationContext(), R.string.db_checking_update_failed, Toast.LENGTH_SHORT).show(); Timber.w("Update split transaction failed!"); return false; } } } } return true; } private boolean saveTransaction() { RecurringTransactionRepository repo = new RecurringTransactionRepository(this); if (!mCommonFunctions.transactionEntity.hasId()) { // insert mCommonFunctions.transactionEntity = repo .insert((RecurringTransaction) mCommonFunctions.transactionEntity); if (mCommonFunctions.transactionEntity.getId() == Constants.NOT_SET) { new Core(this).alert(R.string.db_checking_insert_failed); Timber.w("Insert new repeating transaction failed!"); return false; } } else { // update if (!repo.update((RecurringTransaction) mCommonFunctions.transactionEntity)) { new Core(this).alert(R.string.db_checking_update_failed); Timber.w("Update repeating transaction failed!"); return false; } } return true; } private DateTime getPaymentDate() { DateTime dateTime = getRecurringTransaction().getPaymentDate(); if (dateTime == null) { dateTime = DateTime.now(); getRecurringTransaction().setPaymentDate(dateTime); } return dateTime; } private void setPaymentDate(DateTime dateTime) { mCommonFunctions.setDirty(true); getRecurringTransaction().setPaymentDate(dateTime); mViewHolder.paymentDateTextView.setText(dateTime.toString(Constants.LONG_DATE_PATTERN)); } }