com.money.manager.ex.recurring.transactions.RecurringTransactionEditActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.money.manager.ex.recurring.transactions.RecurringTransactionEditActivity.java

Source

/*
 * 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));
    }
}