diff --git a/app/src/main/java/org/gnucash/android/ui/transaction/SplitEditorFragment.java b/app/src/main/java/org/gnucash/android/ui/transaction/SplitEditorFragment.java index 6cf6116ff..6706e2925 100644 --- a/app/src/main/java/org/gnucash/android/ui/transaction/SplitEditorFragment.java +++ b/app/src/main/java/org/gnucash/android/ui/transaction/SplitEditorFragment.java @@ -475,7 +475,7 @@ private void initViews(final Split split) { splitUidTextView.setText(BaseModel.generateUID()); // - // Handle split + // Fill views from Split data // if (split != null) { @@ -484,8 +484,10 @@ private void initViews(final Split split) { splitAmountEditText.setCommodity(split.getValue() .getCommodity()); - splitAmountEditText.setValue(split.getFormattedValue() - .asBigDecimal()); + // TODO TW C 2020-03-07 : Mettre une préférence pour le signe + // Display abs value because switch button is visible + splitAmountEditText.setValue(split.getValueWithSignum() + .asBigDecimal().abs()); splitCurrencyTextView.setText(split.getValue() .getCommodity() diff --git a/app/src/main/java/org/gnucash/android/ui/transaction/TransactionDetailActivity.java b/app/src/main/java/org/gnucash/android/ui/transaction/TransactionDetailActivity.java index 4ce39ef0a..f227780da 100644 --- a/app/src/main/java/org/gnucash/android/ui/transaction/TransactionDetailActivity.java +++ b/app/src/main/java/org/gnucash/android/ui/transaction/TransactionDetailActivity.java @@ -23,7 +23,6 @@ import org.gnucash.android.model.ScheduledAction; import org.gnucash.android.model.Split; import org.gnucash.android.model.Transaction; -import org.gnucash.android.model.TransactionType; import org.gnucash.android.ui.common.FormActivity; import org.gnucash.android.ui.common.UxArgument; import org.gnucash.android.ui.passcode.PasscodeLockActivity; @@ -63,23 +62,22 @@ public SplitAmountViewHolder(View view, accountName.setText(accountsDbAdapter.getAccountFullName(accountUID)); - // quantity (positive or negative number) - Money quantity = split.getFormattedQuantity(); + // splitSignedAmount (positive or negative number) + Money splitSignedAmount = split.getValueWithSignum(); // Define debit or credit view - // #8xx -// TextView balanceView = quantity.isNegative() -// ? splitDebitView -// : splitCreditView; - TextView balanceView = TransactionType.CREDIT.equals(split.getType()) + TextView balanceView = splitSignedAmount.isNegative() ? splitCreditView : splitDebitView; final AccountType accountType = AccountsDbAdapter.getInstance() .getAccountType(split.getAccountUID()); + // Display absolute value because it is displayed either in debit or credit column accountType.displayBalance(balanceView, - quantity); + splitSignedAmount, + // TODO TW C 2020-03-07 : Mettre une préférence pour le signe + true); } } // Class SplitAmountViewHolder @@ -139,7 +137,8 @@ protected void onCreate(Bundle savedInstanceState) { /** * Reads the transaction information from the database and binds it to the views */ - private void bindViews(){ + private void bindViews() { + TransactionsDbAdapter transactionsDbAdapter = TransactionsDbAdapter.getInstance(); Transaction transaction = transactionsDbAdapter.getRecord(mTransactionUID); @@ -150,45 +149,67 @@ private void bindViews(){ mTransactionAccount.setText(getString(R.string.label_inside_account_with_name, AccountsDbAdapter.getInstance().getAccountFullName(mAccountUID))); // - // Account balance + // Add Debit/Credit Labels // - AccountsDbAdapter accountsDbAdapter = AccountsDbAdapter.getInstance(); - - // Compute balance at Transaction time - Money accountBalance = accountsDbAdapter.getAccountBalance(mAccountUID, -1, transaction.getTimeMillis()); - - // #8xx - // Define in which field (Debit or Credit) the balance shall be displayed - TextView balanceTextView = accountBalance.isNegative() ? mCreditBalance : mDebitBalance ; - - final AccountType accountType = accountsDbAdapter.getAccountType(mAccountUID); + mDetailTableRows = mDetailTableLayout.getChildCount(); + int index = 0; - accountType.displayBalance(balanceTextView, - accountBalance); + LayoutInflater inflater = LayoutInflater.from(this); + View view = inflater.inflate(R.layout.item_split_amount_info, + mDetailTableLayout, + false); + ((TextView) view.findViewById(R.id.split_debit)).setText(getString(R.string.label_debit)); + ((TextView) view.findViewById(R.id.split_credit)).setText(getString(R.string.label_credit)); + mDetailTableLayout.addView(view, + index++); // // Détails // - mDetailTableRows = mDetailTableLayout.getChildCount(); + AccountsDbAdapter accountsDbAdapter = AccountsDbAdapter.getInstance(); boolean useDoubleEntry = GnuCashApplication.isDoubleEntryEnabled(); - LayoutInflater inflater = LayoutInflater.from(this); - int index = 0; for (Split split : transaction.getSplits()) { - if (!useDoubleEntry && split.getAccountUID().equals( - accountsDbAdapter.getImbalanceAccountUID(split.getValue().getCommodity()))) { - //do now show imbalance accounts for single entry use case - continue; + if (!useDoubleEntry && split.getAccountUID() + .equals(accountsDbAdapter.getImbalanceAccountUID(split.getValue() + .getCommodity()))) { + //do not show imbalance accounts for single entry use case + + } else { + + view = inflater.inflate(R.layout.item_split_amount_info, + mDetailTableLayout, + false); + SplitAmountViewHolder viewHolder = new SplitAmountViewHolder(view, + split); + mDetailTableLayout.addView(viewHolder.itemView, + index++); } + } // for - View view = inflater.inflate(R.layout.item_split_amount_info, mDetailTableLayout, false); - SplitAmountViewHolder viewHolder = new SplitAmountViewHolder(view, split); - mDetailTableLayout.addView(viewHolder.itemView, index++); - } + // + // Account balance at Transaction time + // + + // Compute balance at Transaction time + Money accountBalance = accountsDbAdapter.getAccountBalance(mAccountUID, + -1, + transaction.getTimeMillis()); + + // #8xx + // Define in which field (Debit or Credit) the balance shall be displayed + TextView balanceTextView = accountBalance.isNegative() + ? mCreditBalance + : mDebitBalance; + + final AccountType accountType = accountsDbAdapter.getAccountType(mAccountUID); + + accountType.displayBalance(balanceTextView, + accountBalance); // // Date diff --git a/app/src/main/java/org/gnucash/android/ui/transaction/TransactionFormFragment.java b/app/src/main/java/org/gnucash/android/ui/transaction/TransactionFormFragment.java index 9101d20ec..271da6b09 100644 --- a/app/src/main/java/org/gnucash/android/ui/transaction/TransactionFormFragment.java +++ b/app/src/main/java/org/gnucash/android/ui/transaction/TransactionFormFragment.java @@ -251,14 +251,22 @@ public class TransactionFormFragment extends Fragment implements * Create the view and retrieve references to the UI elements */ @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.fragment_transaction_form, container, false); - ButterKnife.bind(this, v); + public View onCreateView(LayoutInflater inflater, + ViewGroup container, + Bundle savedInstanceState) { + + View v = inflater.inflate(R.layout.fragment_transaction_form, + container, + false); + ButterKnife.bind(this, + v); + mAmountEditText.bindListeners(mKeyboardView); + mOpenSplitEditor.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + openSplitEditor(); } }); @@ -318,8 +326,10 @@ public void onActivityCreated(Bundle savedInstanceState) { } setListeners(); + //updateTransferAccountsList must only be called after initializing mAccountsDbAdapter updateTransferAccountsList(); + mTransferAccountSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { /** * Flag for ignoring first call to this listener. @@ -427,21 +437,36 @@ public Cursor runQuery(CharSequence name) { }); mDescriptionEditText.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override - public void onItemClick(AdapterView adapterView, View view, int position, long id) { - mTransaction = new Transaction(mTransactionsDbAdapter.getRecord(id), true); + public void onItemClick(AdapterView adapterView, + View view, + int position, + long id) { + + mTransaction = new Transaction(mTransactionsDbAdapter.getRecord(id), + true); + mTransaction.setTime(System.currentTimeMillis()); + //we check here because next method will modify it and we want to catch user-modification boolean amountEntered = mAmountEditText.isInputModified(); + initializeViewsWithTransaction(); + List splitList = mTransaction.getSplits(); - boolean isSplitPair = splitList.size() == 2 && splitList.get(0).isPairOf(splitList.get(1)); - if (isSplitPair){ + boolean isSplitPair = splitList.size() == 2 && splitList.get(0) + .isPairOf(splitList.get(1)); + if (isSplitPair) { mSplitsList.clear(); if (!amountEntered) //if user already entered an amount - mAmountEditText.setValue(splitList.get(0).getValue().asBigDecimal()); + { + mAmountEditText.setValue(splitList.get(0) + .getValue() + .asBigDecimal()); + } } else { - if (amountEntered){ //if user entered own amount, clear loaded splits and use the user value + if (amountEntered) { //if user entered own amount, clear loaded splits and use the user value mSplitsList.clear(); setDoubleEntryViewsVisibility(View.VISIBLE); } else { @@ -462,19 +487,10 @@ public void onItemClick(AdapterView adapterView, View view, int position, lon * This method is called if the fragment is used for editing a transaction */ private void initializeViewsWithTransaction(){ + mDescriptionEditText.setText(mTransaction.getDescription()); mDescriptionEditText.setSelection(mDescriptionEditText.getText().length()); - mTransactionTypeSwitch.setViewsToColorize(mAmountEditText, - mCurrencyTextView); - - mTransactionTypeSwitch.setAccountType(mAccountType); - mTransactionTypeSwitch.setChecked(mTransaction.getBalance(mAccountUID).isNegative()); - - if (!mAmountEditText.isInputModified()){ - //when autocompleting, only change the amount if the user has not manually changed it already - mAmountEditText.setValue(mTransaction.getBalance(mAccountUID).asBigDecimal()); - } mCurrencyTextView.setText(mTransaction.getCommodity().getSymbol()); mNotesEditText.setText(mTransaction.getNote()); mDateTextView.setText(DATE_FORMATTER.format(mTransaction.getTimeMillis())); @@ -485,7 +501,10 @@ private void initializeViewsWithTransaction(){ //TODO: deep copy the split list. We need a copy so we can modify with impunity mSplitsList = new ArrayList<>(mTransaction.getSplits()); - toggleAmountInputEntryMode(mSplitsList.size() <= 2); + + final boolean isSimpleSplit = mSplitsList.size() <= 2; + + toggleAmountInputEntryMode(isSimpleSplit); if (mSplitsList.size() == 2){ for (Split split : mSplitsList) { @@ -496,20 +515,36 @@ private void initializeViewsWithTransaction(){ } } } + //if there are more than two splits (which is the default for one entry), then //disable editing of the transfer account. User should open editor if (mSplitsList.size() == 2 && mSplitsList.get(0).isPairOf(mSplitsList.get(1))) { + for (Split split : mTransaction.getSplits()) { //two splits, one belongs to this account and the other to another account if (mUseDoubleEntry && !split.getAccountUID().equals(mAccountUID)) { setSelectedTransferAccount(mAccountsDbAdapter.getID(split.getAccountUID())); } } + } else { setDoubleEntryViewsVisibility(View.GONE); } - String currencyCode = mTransactionsDbAdapter.getAccountCurrencyCode(mAccountUID); + if (!mAmountEditText.isInputModified()) { + //when autocompleting, only change the amount if the user has not manually changed it already + + // Compute balance signed value and display it + final BigDecimal signedTransactionBalance = mTransaction.getBalance(mAccountUID) + .asBigDecimal(); + + // TODO TW C 2020-03-07 : Mettre une préférence pour le signe + mAmountEditText.setValue(isSimpleSplit + ? signedTransactionBalance.abs() // Display abs value because switch button is visible + : signedTransactionBalance); // Display signed value because switch button is hidden + } + + String currencyCode = mTransactionsDbAdapter.getAccountCurrencyCode(mAccountUID); Commodity accountCommodity = Commodity.getInstance(currencyCode); mCurrencyTextView.setText(accountCommodity.getSymbol()); @@ -517,6 +552,7 @@ private void initializeViewsWithTransaction(){ mAmountEditText.setCommodity(commodity); mSaveTemplateCheckbox.setChecked(mTransaction.isTemplate()); + String scheduledActionUID = getArguments().getString(UxArgument.SCHEDULED_ACTION_UID); if (scheduledActionUID != null && !scheduledActionUID.isEmpty()) { ScheduledAction scheduledAction = ScheduledActionDbAdapter.getInstance().getRecord(scheduledActionUID); @@ -524,6 +560,14 @@ private void initializeViewsWithTransaction(){ mEventRecurrence.parse(mRecurrenceRule); mRecurrenceTextView.setText(scheduledAction.getRepeatString()); } + + mTransactionTypeSwitch.setViewsToColorize(mAmountEditText, + mCurrencyTextView); + mTransactionTypeSwitch.setAccountType(mAccountType); + mTransactionTypeSwitch.setChecked(mTransaction.getBalance(mAccountUID) + .isNegative()); + + } private void setDoubleEntryViewsVisibility(int visibility) { @@ -657,6 +701,7 @@ private void openSplitEditor() { mAccountUID); intent.putExtra(UxArgument.AMOUNT_STRING, baseAmountString); + intent.putParcelableArrayListExtra(UxArgument.SPLIT_LIST, (ArrayList) extractSplitsFromView()); @@ -734,35 +779,46 @@ private void setSelectedTransferAccount(long accountId){ /** * Returns a list of splits based on the input in the transaction form. + * * This only gets the splits from the simple view, and not those from the Split Editor. * If the Split Editor has been used and there is more than one split, then it returns {@link #mSplitsList} * @return List of splits in the view or {@link #mSplitsList} is there are more than 2 splits in the transaction */ - private List extractSplitsFromView(){ - if (mTransactionTypeSwitch.getVisibility() != View.VISIBLE){ + private List extractSplitsFromView() { + + if (mTransactionTypeSwitch.getVisibility() != View.VISIBLE) { return mSplitsList; } - BigDecimal amountBigd = mAmountEditText.getValue(); + BigDecimal amountBigD = mAmountEditText.getValue(); + String baseCurrencyCode = mTransactionsDbAdapter.getAccountCurrencyCode(mAccountUID); - Money value = new Money(amountBigd, Commodity.getInstance(baseCurrencyCode)); + + // Store signed amount + Money value = new Money(amountBigD, + Commodity.getInstance(baseCurrencyCode)); + Money quantity = new Money(value); - String transferAcctUID = getTransferAccountUID(); - CommoditiesDbAdapter cmdtyDbAdapter = CommoditiesDbAdapter.getInstance(); + String transferAcctUID = getTransferAccountUID(); + CommoditiesDbAdapter cmdtyDbAdapter = CommoditiesDbAdapter.getInstance(); + + if (isMultiCurrencyTransaction()) { + // multi-currency transaction - if (isMultiCurrencyTransaction()){ //if multi-currency transaction String transferCurrencyCode = mAccountsDbAdapter.getCurrencyCode(transferAcctUID); - String commodityUID = cmdtyDbAdapter.getCommodityUID(baseCurrencyCode); - String targetCmdtyUID = cmdtyDbAdapter.getCommodityUID(transferCurrencyCode); - + String commodityUID = cmdtyDbAdapter.getCommodityUID(baseCurrencyCode); + String targetCmdtyUID = cmdtyDbAdapter.getCommodityUID(transferCurrencyCode); + Pair pricePair = PricesDbAdapter.getInstance() - .getPrice(commodityUID, targetCmdtyUID); + .getPrice(commodityUID, + targetCmdtyUID); if (pricePair.first > 0 && pricePair.second > 0) { + quantity = quantity.multiply(pricePair.first.intValue()) - .divide(pricePair.second.intValue()) - .withCurrency(cmdtyDbAdapter.getRecord(targetCmdtyUID)); + .divide(pricePair.second.intValue()) + .withCurrency(cmdtyDbAdapter.getRecord(targetCmdtyUID)); } } @@ -770,21 +826,38 @@ private List extractSplitsFromView(){ Split split2; // Try to preserve the other split attributes. if (mSplitsList.size() >= 2) { + // Multi-split + split1 = mSplitsList.get(0); + // Store absolute value split1.setValue(value); + // Store absolute value split1.setQuantity(value); split1.setAccountUID(mAccountUID); split2 = mSplitsList.get(1); + // Store absolute value split2.setValue(value); + // Store absolute value split2.setQuantity(quantity); split2.setAccountUID(transferAcctUID); + } else { - split1 = new Split(value, mAccountUID); - split2 = new Split(value, quantity, transferAcctUID); + // Only 2 splits (usual case) + + // Store absolute value + split1 = new Split(value, + mAccountUID); + + // Store absolute value + split2 = new Split(value, + quantity, + transferAcctUID); } + split1.setType(mTransactionTypeSwitch.getTransactionType()); - split2.setType(mTransactionTypeSwitch.getTransactionType().invert()); + split2.setType(mTransactionTypeSwitch.getTransactionType() + .invert()); List splitList = new ArrayList<>(); splitList.add(split1); @@ -815,6 +888,7 @@ private List extractSplitsFromView(){ * @return New transaction object containing all info in the form */ private @NonNull Transaction extractTransactionFromView(){ + Calendar cal = new GregorianCalendar( mDate.get(Calendar.YEAR), mDate.get(Calendar.MONTH), @@ -881,6 +955,7 @@ private void saveNewTransaction() { } Transaction transaction = extractTransactionFromView(); + if (mEditMode) { //if editing an existing transaction transaction.setUID(mTransaction.getUID()); }