/*
* 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.investment;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CursorAdapter;
import android.widget.SpinnerAdapter;
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.Calculator;
import com.money.manager.ex.common.MmxBaseFragmentActivity;
import com.money.manager.ex.core.MenuHelper;
import com.money.manager.ex.core.UIHelper;
import com.money.manager.ex.datalayer.AccountRepository;
import com.money.manager.ex.datalayer.StockRepository;
import com.money.manager.ex.domainmodel.Account;
import com.money.manager.ex.domainmodel.Stock;
import com.money.manager.ex.servicelayer.AccountService;
import com.money.manager.ex.utils.MmxDate;
import com.money.manager.ex.utils.MmxDateTimeUtils;
import com.money.manager.ex.utils.SpinnerHelper;
import com.money.manager.ex.view.RobotoTextView;
import com.money.manager.ex.view.RobotoTextViewFontIcon;
import java.util.Calendar;
import java.util.Date;
import javax.inject.Inject;
import butterknife.ButterKnife;
import butterknife.OnClick;
import dagger.Lazy;
import info.javaperformance.money.Money;
import info.javaperformance.money.MoneyFactory;
/**
* Edit investment transaction (stock purchase).
*/
public class InvestmentTransactionEditActivity
extends MmxBaseFragmentActivity {
public static final String ARG_ACCOUNT_ID = "InvestmentTransactionEditActivity:AccountId";
public static final String ARG_STOCK_ID = "InvestmentTransactionEditActivity:StockId";
public static final String DATEPICKER_TAG = "datepicker";
public static final int REQUEST_NUM_SHARES = 1;
public static final int REQUEST_PURCHASE_PRICE = 2;
public static final int REQUEST_COMMISSION = 3;
public static final int REQUEST_CURRENT_PRICE = 4;
@Inject Lazy<MmxDateTimeUtils> dateTimeUtilsLazy;
private boolean mDirty = false;
private Account mAccount;
private Stock mStock;
private InvestmentTransactionViewHolder mViewHolder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_investment_transaction_edit);
MoneyManagerApplication.getApp().iocComponent.inject(this);
ButterKnife.bind(this);
setDisplayHomeAsUpEnabled(true);
// load account & currency
Intent intent = getIntent();
if (intent != null) {
int accountId = intent.getIntExtra(ARG_ACCOUNT_ID, Constants.NOT_SET);
if (accountId != Constants.NOT_SET) {
AccountRepository repository = new AccountRepository(this);
mAccount = repository.load(accountId);
}
int stockId = intent.getIntExtra(ARG_STOCK_ID, Constants.NOT_SET);
if (stockId != Constants.NOT_SET) {
StockRepository repo = new StockRepository(this);
mStock = repo.load(stockId);
} else {
mStock = Stock.create();
if (mAccount != null) {
mStock.setHeldAt(mAccount.getId());
}
}
}
initializeForm();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_CANCELED || data == null) return;
Money amount = Calculator.getAmountFromResult(data);
switch (requestCode) {
case REQUEST_NUM_SHARES:
mStock.setNumberOfShares(amount.toDouble());
showNumberOfShares();
showValue();
break;
case REQUEST_PURCHASE_PRICE:
mStock.setPurchasePrice(amount);
showPurchasePrice();
if (mStock.getCurrentPrice().isZero()) {
mStock.setCurrentPrice(amount);
showCurrentPrice();
// recalculate value
showValue();
}
break;
case REQUEST_COMMISSION:
mStock.setCommission(amount);
showCommission();
break;
case REQUEST_CURRENT_PRICE:
mStock.setCurrentPrice(amount);
showCurrentPrice();
showValue();
break;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
new MenuHelper(this, menu).addSaveToolbarIcon();
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically e clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
switch (id) {
case MenuHelper.save:
return onActionDoneClick();
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
onActionCancelClick();
}
@Override
public boolean onActionCancelClick() {
setResult(Activity.RESULT_CANCELED);
finish();
return true;
}
@Override
public boolean onActionDoneClick() {
if (save()) {
// set result ok and finish activity
setResult(RESULT_OK);
finish();
return true;
} else {
return false;
}
}
public void setDirty(boolean dirty) {
mDirty = dirty;
}
@OnClick(R.id.numSharesView)
public void onNumSharesClick() {
Money amount = MoneyFactory.fromDouble(mStock.getNumberOfShares());
Calculator.forActivity(this)
.amount(amount)
.roundToCurrency(false)
.show(REQUEST_NUM_SHARES);
}
@OnClick(R.id.purchasePriceView)
public void onPurchasePriceClick() {
if (mAccount == null) return;
Calculator.forActivity(this)
.roundToCurrency(false)
.amount(mStock.getPurchasePrice())
.currency(mAccount.getCurrencyId())
.show(REQUEST_PURCHASE_PRICE);
}
@OnClick(R.id.commissionView)
public void onCommissionClick() {
Calculator.forActivity(this)
.amount(mStock.getCommission())
.currency(mAccount.getCurrencyId())
.show(REQUEST_COMMISSION);
}
@OnClick(R.id.currentPriceView)
public void onCurrentPriceClick() {
Calculator.forActivity(this)
.currency(mAccount.getCurrencyId())
.amount(mStock.getCurrentPrice())
.show(REQUEST_CURRENT_PRICE);
}
/*
Private
*/
private void collectData() {
String stockName = mViewHolder.stockNameEdit.getText().toString().trim();
mStock.setName(stockName);
// Symbols are always uppercase.
String symbol = mViewHolder.symbolEdit.getText().toString()
.trim().replace(" ", "").toUpperCase();
mStock.setSymbol(symbol);
mStock.setNotes(mViewHolder.notesEdit.getText().toString());
}
private void displayStock(Stock stock, InvestmentTransactionViewHolder viewHolder) {
if (mAccount == null) return;
// Date
String dateDisplay = new MmxDate(stock.getPurchaseDate()).toString(Constants.LONG_DATE_PATTERN);
viewHolder.dateView.setText(dateDisplay);
// Account.
Cursor cursor = ((CursorAdapter) viewHolder.accountSpinner.getAdapter()).getCursor();
int accountIndex = SpinnerHelper.getPosition(mAccount.getName(), Account.ACCOUNTNAME, cursor);
if (accountIndex >= 0) {
viewHolder.accountSpinner.setSelection(accountIndex, true);
}
viewHolder.stockNameEdit.setText(stock.getName());
viewHolder.symbolEdit.setText(stock.getSymbol());
showNumberOfShares();
showPurchasePrice();
viewHolder.notesEdit.setText(stock.getNotes());
showCommission();
showCurrentPrice();
showValue();
}
private void initializeForm() {
View rootView = this.findViewById(R.id.content);
mViewHolder = new InvestmentTransactionViewHolder(rootView);
initDateControl(mViewHolder);
initAccountSelectors(mViewHolder);
displayStock(mStock, mViewHolder);
}
/**
* Initialize account selectors.
*/
private void initAccountSelectors(final InvestmentTransactionViewHolder viewHolder) {
Context context = this;
// Account list as the data source to populate the drop-downs.
AccountService accountService = new AccountService(context);
accountService.loadInvestmentAccountsToSpinner(viewHolder.accountSpinner, false);
// AccountRepository accountRepository = new AccountRepository(context);
final Integer accountId = mStock.getHeldAt();
// if (accountId != null) {
// addMissingAccountToSelectors(accountRepository, accountId);
// }
AdapterView.OnItemSelectedListener listener = new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
SpinnerAdapter adapter = viewHolder.accountSpinner.getAdapter();
Cursor cursor = (Cursor) adapter.getItem(position);
Account account = Account.from(cursor);
if (!account.getId().equals(accountId)) {
setDirty(true);
mStock.setHeldAt(account.getId());
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
};
viewHolder.accountSpinner.setOnItemSelectedListener(listener);
}
private void initDateControl(final InvestmentTransactionViewHolder viewHolder) {
// Purchase Date
viewHolder.dateView.setOnClickListener(new View.OnClickListener() {
CalendarDatePickerDialogFragment.OnDateSetListener listener = new CalendarDatePickerDialogFragment.OnDateSetListener() {
@Override
public void onDateSet(CalendarDatePickerDialogFragment dialog, int year, int monthOfYear, int dayOfMonth) {
setDirty(true);
MmxDate dateTime = new MmxDate(year, monthOfYear, dayOfMonth);
viewHolder.dateView.setText(dateTime.toString(Constants.LONG_DATE_PATTERN));
}
};
@Override
public void onClick(View v) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(mStock.getPurchaseDate());
CalendarDatePickerDialogFragment datePicker = new CalendarDatePickerDialogFragment()
.setFirstDayOfWeek(dateTimeUtilsLazy.get().getFirstDayOfWeek())
.setOnDateSetListener(listener)
.setPreselectedDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
if (new UIHelper(InvestmentTransactionEditActivity.this).isUsingDarkTheme()) {
datePicker.setThemeDark();
}
datePicker.show(getSupportFragmentManager(), DATEPICKER_TAG);
}
});
// prev/next day
viewHolder.previousDayButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MmxDate dateTime = new MmxDate(mStock.getPurchaseDate()).minusDays(1);
setDate(dateTime.toDate());
}
});
viewHolder.nextDayButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MmxDate dateTime = new MmxDate(mStock.getPurchaseDate()).plusDays(1);
setDate(dateTime.toDate());
}
});
}
private void showCommission() {
RobotoTextView view = (RobotoTextView) this.findViewById(R.id.commissionView);
if (view == null) return;
// todo: format the number of shares based on selected locale.
view.setText(mStock.getCommission().toString());
}
private void showCurrentPrice() {
RobotoTextView view = (RobotoTextView) this.findViewById(R.id.currentPriceView);
// todo: format the number of shares based on selected locale.
view.setText(mStock.getCurrentPrice().toString());
}
private void showNumberOfShares() {
RobotoTextViewFontIcon view = (RobotoTextViewFontIcon) this.findViewById(R.id.numSharesView);
if (view == null) return;
// todo: format the number of shares based on selected locale?
view.setText(mStock.getNumberOfShares().toString());
}
private void showPurchasePrice() {
RobotoTextView view = (RobotoTextView) this.findViewById(R.id.purchasePriceView);
// todo: format the number of shares based on selected locale.
view.setText(mStock.getPurchasePrice().toString());
}
private void showValue() {
RobotoTextView view = (RobotoTextView) this.findViewById(R.id.valueView);
//mViewHolder.
view.setText(mStock.getValue().toString());
}
private boolean save() {
collectData();
if (!validate()) return false;
// update
StockRepository repository = new StockRepository(getApplicationContext());
if (mStock.getId() != null) {
repository.save(mStock);
} else {
repository.insert(mStock);
}
return true;
}
private void setDate(Date dateTime) {
setDirty(true);
mStock.setPurchaseDate(dateTime);
showDate(dateTime);
}
private void showDate(Date date) {
String display = new MmxDate(date).toString(Constants.LONG_DATE_PATTERN);
mViewHolder.dateView.setText(display);
}
private boolean validate() {
// symbol must not be empty.
if (TextUtils.isEmpty(mStock.getSymbol())) {
new UIHelper(this).showToast(getString(R.string.symbol_required));
return false;
}
// number of shares, price?
return true;
}
}