From 2a44855b10c5d1b0eb79e87e90cdb4ea31e790ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=80lex=20Magaz=20Gra=C3=A7a?= Date: Sun, 18 Oct 2015 22:03:09 +0200 Subject: [PATCH 01/17] Enable haptic feedback for the calculator keyboard. --- .../ui/util/widget/CalculatorKeyboard.java | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorKeyboard.java b/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorKeyboard.java index bb9f5d9f8..64bd15014 100644 --- a/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorKeyboard.java +++ b/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorKeyboard.java @@ -29,6 +29,7 @@ import android.inputmethodservice.Keyboard; import android.inputmethodservice.KeyboardView; import android.inputmethodservice.KeyboardView.OnKeyboardActionListener; +import android.provider.Settings; import android.support.annotation.XmlRes; import android.text.Editable; import android.view.HapticFeedbackConstants; @@ -69,6 +70,7 @@ public class CalculatorKeyboard { @Override public void onKey(int primaryCode, int[] keyCodes) { View focusCurrent = ((Activity)mContext).getWindow().getCurrentFocus(); + assert focusCurrent != null; /* if (focusCurrent == null || focusCurrent.getClass() != EditText.class) @@ -125,9 +127,8 @@ public void onKey(int primaryCode, int[] keyCodes) { } @Override - public void onPress(int arg0) { - // vibrate if haptic feedback is enabled: - if (hapticFeedback && arg0 != 0) + public void onPress(int primaryCode) { + if (isHapticFeedbackEnabled() && primaryCode != 0) mKeyboardView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); } @@ -139,6 +140,17 @@ public void onPress(int arg0) { @Override public void swipeUp() { } }; + /** + * Returns true if the haptic feedback is enabled. + * + * @return true if the haptic feedback is enabled in the system settings. + */ + private boolean isHapticFeedbackEnabled() { + int value = Settings.System.getInt(mKeyboardView.getContext().getContentResolver(), + Settings.System.HAPTIC_FEEDBACK_ENABLED, 0); + return value != 0; + } + /** * Create a custom keyboard, that uses the KeyboardView (with resource id viewid) of the host activity, * and load the keyboard layout from xml file layoutid (see {@link Keyboard} for description). @@ -186,15 +198,6 @@ public void hideCustomKeyboard() { mKeyboardView.setEnabled(false); } - /** - * Enables or disables the Haptic feedback on keyboard touches - * @param goEnabled true if you want haptic feedback, falso otherwise - */ - public void enableHapticFeedback(boolean goEnabled) { - mKeyboardView.setHapticFeedbackEnabled(goEnabled); - hapticFeedback = goEnabled; - } - public boolean onBackPressed() { if (isCustomKeyboardVisible()) { hideCustomKeyboard(); From a3916767a1c4e2f076c89f4f5d4298eff833fff4 Mon Sep 17 00:00:00 2001 From: Ngewi Fet Date: Fri, 30 Oct 2015 00:34:45 +0100 Subject: [PATCH 02/17] Add menu options for moving and duplicating transactions fixes #390 --- .../test/ui/TransactionsActivityTest.java | 33 +++++++++++ .../java/org/gnucash/android/model/Split.java | 2 +- .../transaction/TransactionsListFragment.java | 23 +++++++- .../dialog/BulkMoveDialogFragment.java | 59 +++++++++++-------- app/src/main/res/layout/dialog_bulk_move.xml | 3 +- .../res/menu/transactions_context_menu.xml | 16 ++--- app/src/main/res/values-af-rZA/strings.xml | 4 +- app/src/main/res/values-ar-rSA/strings.xml | 4 +- app/src/main/res/values-ca-rES/strings.xml | 4 +- app/src/main/res/values-cs-rCZ/strings.xml | 4 +- app/src/main/res/values-da-rDK/strings.xml | 4 +- app/src/main/res/values-de/strings.xml | 4 +- app/src/main/res/values-el-rGR/strings.xml | 4 +- app/src/main/res/values-en-rGB/strings.xml | 4 +- app/src/main/res/values-es-rMX/strings.xml | 4 +- app/src/main/res/values-es/strings.xml | 4 +- app/src/main/res/values-fi-rFI/strings.xml | 4 +- app/src/main/res/values-fr/strings.xml | 4 +- app/src/main/res/values-hu-rHU/strings.xml | 4 +- app/src/main/res/values-it-rIT/strings.xml | 4 +- app/src/main/res/values-iw-rIL/strings.xml | 4 +- app/src/main/res/values-ja-rJP/strings.xml | 4 +- app/src/main/res/values-ko-rKR/strings.xml | 4 +- app/src/main/res/values-nl-rNL/strings.xml | 4 +- app/src/main/res/values-no-rNO/strings.xml | 4 +- app/src/main/res/values-pl-rPL/strings.xml | 4 +- app/src/main/res/values-pt-rBR/strings.xml | 4 +- app/src/main/res/values-pt-rPT/strings.xml | 4 +- app/src/main/res/values-ro-rRO/strings.xml | 4 +- app/src/main/res/values-ru/strings.xml | 4 +- app/src/main/res/values-sr-rSP/strings.xml | 4 +- app/src/main/res/values-sv-rSE/strings.xml | 4 +- app/src/main/res/values-tr-rTR/strings.xml | 4 +- app/src/main/res/values-uk-rUA/strings.xml | 4 +- app/src/main/res/values-vi-rVN/strings.xml | 4 +- app/src/main/res/values-zh-rCN/strings.xml | 4 +- app/src/main/res/values-zh-rTW/strings.xml | 4 +- app/src/main/res/values/strings.xml | 2 + 38 files changed, 194 insertions(+), 68 deletions(-) diff --git a/app/src/androidTest/java/org/gnucash/android/test/ui/TransactionsActivityTest.java b/app/src/androidTest/java/org/gnucash/android/test/ui/TransactionsActivityTest.java index 51d3a4813..669660cc1 100644 --- a/app/src/androidTest/java/org/gnucash/android/test/ui/TransactionsActivityTest.java +++ b/app/src/androidTest/java/org/gnucash/android/test/ui/TransactionsActivityTest.java @@ -475,6 +475,39 @@ public void testDeleteTransaction(){ assertEquals(0, mTransactionsDbAdapter.getTransactionsCount(id)); } + @Test + public void testMoveTransaction(){ + Account account = new Account("Move account"); + account.setCurrency(Currency.getInstance(CURRENCY_CODE)); + mAccountsDbAdapter.addRecord(account); + + assertThat(mTransactionsDbAdapter.getAllTransactionsForAccount(account.getUID())).hasSize(0); + + onView(withId(R.id.options_menu)).perform(click()); + onView(withText(R.string.menu_move_transaction)).perform(click()); + + onView(withId(R.id.btn_save)).perform(click()); + + assertThat(mTransactionsDbAdapter.getAllTransactionsForAccount(DUMMY_ACCOUNT_UID)).hasSize(0); + + assertThat(mTransactionsDbAdapter.getAllTransactionsForAccount(account.getUID())).hasSize(1); + + } + + @Test + public void testDuplicateTransaction(){ + assertThat(mTransactionsDbAdapter.getAllTransactionsForAccount(DUMMY_ACCOUNT_UID)).hasSize(1); + + onView(withId(R.id.options_menu)).perform(click()); + onView(withText(R.string.menu_duplicate_transaction)).perform(click()); + + List dummyAccountTrns = mTransactionsDbAdapter.getAllTransactionsForAccount(DUMMY_ACCOUNT_UID); + assertThat(dummyAccountTrns).hasSize(2); + + assertThat(dummyAccountTrns.get(0).getDescription()).isEqualTo(dummyAccountTrns.get(1).getDescription()); + assertThat(dummyAccountTrns.get(0).getTimeMillis()).isNotEqualTo(dummyAccountTrns.get(1).getTimeMillis()); + } + //TODO: add normal transaction recording @Test public void testLegacyIntentTransactionRecording(){ diff --git a/app/src/main/java/org/gnucash/android/model/Split.java b/app/src/main/java/org/gnucash/android/model/Split.java index 3b14cdc33..39b619064 100644 --- a/app/src/main/java/org/gnucash/android/model/Split.java +++ b/app/src/main/java/org/gnucash/android/model/Split.java @@ -2,7 +2,6 @@ import android.support.annotation.NonNull; -import android.util.Log; import org.gnucash.android.db.AccountsDbAdapter; @@ -91,6 +90,7 @@ public Split(Split sourceSplit, boolean generateUID){ this.mValue = new Money(sourceSplit.mValue); this.mQuantity = new Money(sourceSplit.mQuantity); + //todo: clone reconciled status if (generateUID){ generateUID(); } else { diff --git a/app/src/main/java/org/gnucash/android/ui/transaction/TransactionsListFragment.java b/app/src/main/java/org/gnucash/android/ui/transaction/TransactionsListFragment.java index b6f80e65e..8015d8325 100644 --- a/app/src/main/java/org/gnucash/android/ui/transaction/TransactionsListFragment.java +++ b/app/src/main/java/org/gnucash/android/ui/transaction/TransactionsListFragment.java @@ -42,18 +42,20 @@ import org.gnucash.android.R; import org.gnucash.android.db.AccountsDbAdapter; -import org.gnucash.android.ui.util.CursorRecyclerAdapter; import org.gnucash.android.db.DatabaseCursorLoader; import org.gnucash.android.db.DatabaseSchema; import org.gnucash.android.db.SplitsDbAdapter; import org.gnucash.android.db.TransactionsDbAdapter; import org.gnucash.android.model.Money; import org.gnucash.android.model.Split; +import org.gnucash.android.model.Transaction; import org.gnucash.android.ui.common.FormActivity; import org.gnucash.android.ui.common.UxArgument; -import org.gnucash.android.ui.util.widget.EmptyRecyclerView; -import org.gnucash.android.ui.util.Refreshable; import org.gnucash.android.ui.homescreen.WidgetConfigurationActivity; +import org.gnucash.android.ui.transaction.dialog.BulkMoveDialogFragment; +import org.gnucash.android.ui.util.CursorRecyclerAdapter; +import org.gnucash.android.ui.util.Refreshable; +import org.gnucash.android.ui.util.widget.EmptyRecyclerView; import org.ocpsoft.prettytime.PrettyTime; import java.util.Date; @@ -319,6 +321,21 @@ public boolean onMenuItemClick(MenuItem item) { refresh(); return true; + case R.id.context_menu_duplicate_transaction: + Transaction transaction = mTransactionsDbAdapter.getRecord(transactionId); + Transaction duplicate = new Transaction(transaction, true); + duplicate.setTime(System.currentTimeMillis()); + mTransactionsDbAdapter.addRecord(duplicate); + refresh(); + return true; + + case R.id.context_menu_move_transaction: + long[] ids = new long[]{transactionId}; + BulkMoveDialogFragment fragment = BulkMoveDialogFragment.newInstance(ids, mAccountUID); + fragment.show(getActivity().getSupportFragmentManager(), "bulk_move_transactions"); + fragment.setTargetFragment(TransactionsListFragment.this, 0); + return true; + default: return false; diff --git a/app/src/main/java/org/gnucash/android/ui/transaction/dialog/BulkMoveDialogFragment.java b/app/src/main/java/org/gnucash/android/ui/transaction/dialog/BulkMoveDialogFragment.java index 9a2eb2af6..74469f0ea 100644 --- a/app/src/main/java/org/gnucash/android/ui/transaction/dialog/BulkMoveDialogFragment.java +++ b/app/src/main/java/org/gnucash/android/ui/transaction/dialog/BulkMoveDialogFragment.java @@ -33,9 +33,9 @@ import org.gnucash.android.db.DatabaseSchema; import org.gnucash.android.db.TransactionsDbAdapter; import org.gnucash.android.ui.common.UxArgument; +import org.gnucash.android.ui.homescreen.WidgetConfigurationActivity; import org.gnucash.android.ui.transaction.TransactionsActivity; import org.gnucash.android.ui.util.Refreshable; -import org.gnucash.android.ui.homescreen.WidgetConfigurationActivity; import org.gnucash.android.util.QualifiedAccountNameCursorAdapter; /** @@ -69,6 +69,21 @@ public class BulkMoveDialogFragment extends DialogFragment { */ String mOriginAccountUID = null; + /** + * Create new instance of the bulk move dialog + * @param transactionIds Array of transaction database record IDs + * @param originAccountUID Account from which to move the transactions + * @return BulkMoveDialogFragment instance with arguments set + */ + public static BulkMoveDialogFragment newInstance(long[] transactionIds, String originAccountUID){ + Bundle args = new Bundle(); + args.putLongArray(UxArgument.SELECTED_TRANSACTION_IDS, transactionIds); + args.putString(UxArgument.ORIGIN_ACCOUNT_UID, originAccountUID); + BulkMoveDialogFragment bulkMoveDialogFragment = new BulkMoveDialogFragment(); + bulkMoveDialogFragment.setArguments(args); + return bulkMoveDialogFragment; + } + /** * Creates the view and retrieves references to the dialog elements */ @@ -84,7 +99,13 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, mCancelButton = (Button) v.findViewById(R.id.btn_cancel); return v; } - + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setStyle(DialogFragment.STYLE_NORMAL, R.style.Theme_AppCompat_Light_Dialog); + } + @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); @@ -97,22 +118,15 @@ public void onActivityCreated(Bundle savedInstanceState) { String title = getActivity().getString(R.string.title_move_transactions, mTransactionIds.length); getDialog().setTitle(title); - - /* - Accounts database adapter - */ - //FIXME: move only to accounts which have the same currency as this one + AccountsDbAdapter accountsDbAdapter = AccountsDbAdapter.getInstance(); String conditions = "(" + DatabaseSchema.AccountEntry.COLUMN_UID + " != ? AND " + DatabaseSchema.AccountEntry.COLUMN_CURRENCY + " = ? AND " - + DatabaseSchema.AccountEntry.COLUMN_UID + " != ? AND " + + DatabaseSchema.AccountEntry.COLUMN_HIDDEN + " = 0 AND " + DatabaseSchema.AccountEntry.COLUMN_PLACEHOLDER + " = 0" + ")"; Cursor cursor = accountsDbAdapter.fetchAccountsOrderedByFullName(conditions, - new String[]{mOriginAccountUID, - accountsDbAdapter.getCurrencyCode(mOriginAccountUID), - "" + accountsDbAdapter.getOrCreateGnuCashRootAccountUID() - }); + new String[]{mOriginAccountUID, accountsDbAdapter.getCurrencyCode(mOriginAccountUID)}); SimpleCursorAdapter mCursorAdapter = new QualifiedAccountNameCursorAdapter(getActivity(), cursor); mDestinationAccountSpinner.setAdapter(mCursorAdapter); @@ -132,34 +146,29 @@ public void onClick(View v) { }); mOkButton.setOnClickListener(new View.OnClickListener() { - + @Override public void onClick(View v) { - if (mTransactionIds == null){ + if (mTransactionIds == null) { dismiss(); } - + long dstAccountId = mDestinationAccountSpinner.getSelectedItemId(); TransactionsDbAdapter trxnAdapter = TransactionsDbAdapter.getInstance(); - if (!trxnAdapter.getAccountCurrencyCode(dstAccountId).equals(trxnAdapter.getAccountCurrencyCode(mOriginAccountUID))){ + if (!trxnAdapter.getAccountCurrencyCode(dstAccountId).equals(trxnAdapter.getAccountCurrencyCode(mOriginAccountUID))) { Toast.makeText(getActivity(), R.string.toast_incompatible_currency, Toast.LENGTH_LONG).show(); return; } - String srcAccountUID = ((TransactionsActivity)getActivity()).getCurrentAccountUID(); - String dstAccountUID = AccountsDbAdapter.getInstance().getUID(dstAccountId); + String srcAccountUID = ((TransactionsActivity) getActivity()).getCurrentAccountUID(); + String dstAccountUID = AccountsDbAdapter.getInstance().getUID(dstAccountId); for (long trxnId : mTransactionIds) { trxnAdapter.moveTransaction(trxnAdapter.getUID(trxnId), srcAccountUID, dstAccountUID); } WidgetConfigurationActivity.updateAllWidgets(getActivity()); - ((Refreshable)getTargetFragment()).refresh(); + ((Refreshable) getTargetFragment()).refresh(); dismiss(); - } + } }); } - - @Override - public void onDestroyView() { - super.onDestroyView(); - } } diff --git a/app/src/main/res/layout/dialog_bulk_move.xml b/app/src/main/res/layout/dialog_bulk_move.xml index 6842701a1..2965ab278 100644 --- a/app/src/main/res/layout/dialog_bulk_move.xml +++ b/app/src/main/res/layout/dialog_bulk_move.xml @@ -18,6 +18,7 @@ + android:layout_marginBottom="@dimen/dialog_padding" /> diff --git a/app/src/main/res/menu/transactions_context_menu.xml b/app/src/main/res/menu/transactions_context_menu.xml index 3fcaea326..cd4f77178 100644 --- a/app/src/main/res/menu/transactions_context_menu.xml +++ b/app/src/main/res/menu/transactions_context_menu.xml @@ -17,17 +17,19 @@ - + android:orderInCategory="1" /> + + android:orderInCategory="3"/> \ No newline at end of file diff --git a/app/src/main/res/values-af-rZA/strings.xml b/app/src/main/res/values-af-rZA/strings.xml index 50b75c145..4405a1a7e 100644 --- a/app/src/main/res/values-af-rZA/strings.xml +++ b/app/src/main/res/values-af-rZA/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info @@ -560,6 +560,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-ar-rSA/strings.xml b/app/src/main/res/values-ar-rSA/strings.xml index 534395d68..6f113e0fa 100644 --- a/app/src/main/res/values-ar-rSA/strings.xml +++ b/app/src/main/res/values-ar-rSA/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info @@ -580,6 +580,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-ca-rES/strings.xml b/app/src/main/res/values-ca-rES/strings.xml index b2bee3511..237766a53 100644 --- a/app/src/main/res/values-ca-rES/strings.xml +++ b/app/src/main/res/values-ca-rES/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Crea un compte Edita el compte Informació @@ -560,6 +560,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Mes actual Últims 3 mesos diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index 89e3c213a..32d54f207 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info @@ -565,6 +565,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-da-rDK/strings.xml b/app/src/main/res/values-da-rDK/strings.xml index ecc78a9e6..64f49945d 100644 --- a/app/src/main/res/values-da-rDK/strings.xml +++ b/app/src/main/res/values-da-rDK/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Opprett konto Rediger konto Informasjon @@ -557,6 +557,8 @@ Ingen brukerinformasjon vil bli delt i denne prosessen! Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 4cd9833a9..ccfdafc00 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Neues Konto Konto bearbeiten Info @@ -557,6 +557,8 @@ No user-identifiable information will be collected as part of this process!Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-el-rGR/strings.xml b/app/src/main/res/values-el-rGR/strings.xml index 41ed80bd7..7dceb5301 100644 --- a/app/src/main/res/values-el-rGR/strings.xml +++ b/app/src/main/res/values-el-rGR/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Δημιουργία Λογαριασμού Επεξεργασία Λογαριασμού Πληροφορίες @@ -571,6 +571,8 @@ No user-identifiable information will be collected as part of this process! Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml index 50b75c145..4405a1a7e 100644 --- a/app/src/main/res/values-en-rGB/strings.xml +++ b/app/src/main/res/values-en-rGB/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info @@ -560,6 +560,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-es-rMX/strings.xml b/app/src/main/res/values-es-rMX/strings.xml index d08d62a42..7307dc418 100644 --- a/app/src/main/res/values-es-rMX/strings.xml +++ b/app/src/main/res/values-es-rMX/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Crear Cuenta Editar Cuenta Detalles @@ -557,6 +557,8 @@ Este proceso solo recoge información que no permite identificar al usuarioShare ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Mes actual Últimos 3 meses diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index e944b750f..77320ff90 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Crear cuenta Editar cuenta Información @@ -557,6 +557,8 @@ Este proceso solo recoge información que no permite identificar al usuarioCompartir ideas, discutir cambios o reportar problemas Traducir o revisar en CrowdIn ¡No hay aplicaciones compatibles para recibir las transacciones exportadas! + Move... + Duplicate Mes actual Últimos 3 meses diff --git a/app/src/main/res/values-fi-rFI/strings.xml b/app/src/main/res/values-fi-rFI/strings.xml index 50b75c145..4405a1a7e 100644 --- a/app/src/main/res/values-fi-rFI/strings.xml +++ b/app/src/main/res/values-fi-rFI/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info @@ -560,6 +560,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index a86b54ded..48e555b33 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Créer un compte Éditer le compte Informations @@ -557,6 +557,8 @@ Aucune information permettant d\'identifier l\'utilisateur ne sera recueillis da Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Mois actuel 3 derniers mois diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu-rHU/strings.xml index 9235b3920..dff6c8a4b 100644 --- a/app/src/main/res/values-hu-rHU/strings.xml +++ b/app/src/main/res/values-hu-rHU/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info @@ -562,6 +562,8 @@ No user-identifiable information will be collected as part of this process! Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-it-rIT/strings.xml b/app/src/main/res/values-it-rIT/strings.xml index 74f887085..d4f913820 100644 --- a/app/src/main/res/values-it-rIT/strings.xml +++ b/app/src/main/res/values-it-rIT/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Crea conto Modifica conto Informazioni @@ -561,6 +561,8 @@ No user-identifiable information will be collected as part of this process! Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Mese corrente Ultimi 3 mesi diff --git a/app/src/main/res/values-iw-rIL/strings.xml b/app/src/main/res/values-iw-rIL/strings.xml index 50b75c145..4405a1a7e 100644 --- a/app/src/main/res/values-iw-rIL/strings.xml +++ b/app/src/main/res/values-iw-rIL/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info @@ -560,6 +560,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index a9cd88e95..4e4bd3749 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info @@ -555,6 +555,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index a9cd88e95..4e4bd3749 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info @@ -555,6 +555,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-nl-rNL/strings.xml b/app/src/main/res/values-nl-rNL/strings.xml index c94a245c6..e26d8cf7c 100644 --- a/app/src/main/res/values-nl-rNL/strings.xml +++ b/app/src/main/res/values-nl-rNL/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Nieuwe rekening Rekening bewerken Info @@ -561,6 +561,8 @@ No user-identifiable information will be collected as part of this process! Ideeën uitwisselen, bespreken van wijzigingen of problemen melden Vertalen of nalezen op CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Huidige maand Afgelopen 3 maanden diff --git a/app/src/main/res/values-no-rNO/strings.xml b/app/src/main/res/values-no-rNO/strings.xml index c8e206d1b..7cc6c2e35 100644 --- a/app/src/main/res/values-no-rNO/strings.xml +++ b/app/src/main/res/values-no-rNO/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Opprett konto Rediger konto Informasjon @@ -551,6 +551,8 @@ Dele ideer, diskutere endringer eller rapportere problemer Oversette eller korrekturles på CrowdIn Ingen kompatible apper til å motta de eksporterte transaksjonene! + Move... + Duplicate Gjeldende måned Siste 3 måneder diff --git a/app/src/main/res/values-pl-rPL/strings.xml b/app/src/main/res/values-pl-rPL/strings.xml index de0866270..4ea6191a9 100644 --- a/app/src/main/res/values-pl-rPL/strings.xml +++ b/app/src/main/res/values-pl-rPL/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Utwórz konto Edytuj konto Info @@ -558,6 +558,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Bieżący miesiąc Ostatnie 3 miesiące diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index f0fb762dc..931acfce0 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Criar Conta Editar Conta Info @@ -555,6 +555,8 @@ Neste processo não serão recolhidas informações do utilizador! Compartilhe ideias, discuta alterações ou reporte problemas Traduza ou corrija as traduções no Crowdln No compatible apps to receive the exported transactions! + Move... + Duplicate Mês atual Last 3 meses diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index dcbc98d27..8e1b45fa1 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Criar Conta Editar Conta Informação @@ -555,6 +555,8 @@ Neste processo não serão recolhidas informações do utilizador! Partilhe ideias, discuta alterações ou reporte problemas Traduza ou reveja em Crowdin No compatible apps to receive the exported transactions! + Move... + Duplicate Mês actual Últimos 3 meses diff --git a/app/src/main/res/values-ro-rRO/strings.xml b/app/src/main/res/values-ro-rRO/strings.xml index 89e3c213a..32d54f207 100644 --- a/app/src/main/res/values-ro-rRO/strings.xml +++ b/app/src/main/res/values-ro-rRO/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info @@ -565,6 +565,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 980eb03ce..194d130ea 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Создать счёт Редактировать счёт Информация @@ -563,6 +563,8 @@ Поделиться идеями, обсудить изменения или сообщить о проблемах Перевести или вычитать на CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Текущий месяц Последний квартал diff --git a/app/src/main/res/values-sr-rSP/strings.xml b/app/src/main/res/values-sr-rSP/strings.xml index 2674bfc38..a016973b5 100644 --- a/app/src/main/res/values-sr-rSP/strings.xml +++ b/app/src/main/res/values-sr-rSP/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Креирај рачун Уреди рачун Инфо @@ -565,6 +565,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index 50b75c145..4405a1a7e 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info @@ -560,6 +560,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-tr-rTR/strings.xml b/app/src/main/res/values-tr-rTR/strings.xml index f5123c727..1725c5f37 100644 --- a/app/src/main/res/values-tr-rTR/strings.xml +++ b/app/src/main/res/values-tr-rTR/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Hesap Oluştur Hesabı Düzenle Bilgilendirme @@ -560,6 +560,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-uk-rUA/strings.xml b/app/src/main/res/values-uk-rUA/strings.xml index bf0fdc534..d54528d16 100644 --- a/app/src/main/res/values-uk-rUA/strings.xml +++ b/app/src/main/res/values-uk-rUA/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Створити рахунок Редагувати рахунок Інформація @@ -561,6 +561,8 @@ Поділитися ідеями, обговорити зміни або повідомити про проблеми Перекласти або вичитати на CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Поточний місяць Останній квартал diff --git a/app/src/main/res/values-vi-rVN/strings.xml b/app/src/main/res/values-vi-rVN/strings.xml index a9cd88e95..4e4bd3749 100644 --- a/app/src/main/res/values-vi-rVN/strings.xml +++ b/app/src/main/res/values-vi-rVN/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info @@ -555,6 +555,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 44fd7204c..3a675aa18 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + 创建科目 修改科目 信息 @@ -552,6 +552,8 @@ No user-identifiable information will be collected as part of this process! Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 3e026919d..98921c6c9 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + 创建科目 修改科目 信息 @@ -552,6 +552,8 @@ No user-identifiable information will be collected as part of this process! Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 01ad48ff3..948ec1b40 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -566,6 +566,8 @@ Share ideas, discuss changes or report problems Translate or proof-read on CrowdIn No compatible apps to receive the exported transactions! + Move... + Duplicate Current month Last 3 months From bf7616c414bb52ee7072dccbedd2a4f1dbc3b1b4 Mon Sep 17 00:00:00 2001 From: Ngewi Fet Date: Fri, 30 Oct 2015 14:58:22 +0100 Subject: [PATCH 03/17] Fix account delete dialog not showing "move" option Add translation for Norwegian Bokmal to crowdin config --- app/build.gradle | 4 +- .../android/ui/account/AccountsActivity.java | 2 +- .../account/DeleteAccountDialogFragment.java | 6 + .../dialog/BulkMoveDialogFragment.java | 2 +- .../res/layout/radio_group_delete_or_move.xml | 4 +- app/src/main/res/values-af-rZA/strings.xml | 2 +- app/src/main/res/values-ar-rSA/strings.xml | 2 +- app/src/main/res/values-ca-rES/strings.xml | 2 +- app/src/main/res/values-cs-rCZ/strings.xml | 2 +- app/src/main/res/values-da-rDK/strings.xml | 2 +- app/src/main/res/values-de/strings.xml | 2 +- app/src/main/res/values-el-rGR/strings.xml | 2 +- app/src/main/res/values-en-rGB/strings.xml | 2 +- app/src/main/res/values-es-rMX/strings.xml | 2 +- app/src/main/res/values-es/strings.xml | 2 +- app/src/main/res/values-fi-rFI/strings.xml | 2 +- app/src/main/res/values-fr/strings.xml | 2 +- app/src/main/res/values-hu-rHU/strings.xml | 2 +- app/src/main/res/values-it-rIT/strings.xml | 2 +- app/src/main/res/values-iw-rIL/strings.xml | 2 +- app/src/main/res/values-ja-rJP/strings.xml | 2 +- app/src/main/res/values-ko-rKR/strings.xml | 2 +- app/src/main/res/values-nb/strings.xml | 564 ++++++++++++++++++ app/src/main/res/values-nl-rNL/strings.xml | 2 +- app/src/main/res/values-no-rNO/strings.xml | 2 +- app/src/main/res/values-pl-rPL/strings.xml | 2 +- app/src/main/res/values-pt-rBR/strings.xml | 2 +- app/src/main/res/values-pt-rPT/strings.xml | 2 +- app/src/main/res/values-ro-rRO/strings.xml | 2 +- app/src/main/res/values-ru/strings.xml | 2 +- app/src/main/res/values-sr-rSP/strings.xml | 2 +- app/src/main/res/values-sv-rSE/strings.xml | 2 +- app/src/main/res/values-tr-rTR/strings.xml | 2 +- app/src/main/res/values-uk-rUA/strings.xml | 2 +- app/src/main/res/values-vi-rVN/strings.xml | 2 +- app/src/main/res/values-zh-rCN/strings.xml | 2 +- app/src/main/res/values-zh-rTW/strings.xml | 2 +- app/src/main/res/values/styles.xml | 4 + crowdin.yaml | 1 + 39 files changed, 612 insertions(+), 37 deletions(-) create mode 100644 app/src/main/res/values-nb/strings.xml diff --git a/app/build.gradle b/app/build.gradle index 2a9d08c54..794cb4062 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'io.fabric' def versionMajor = 2 def versionMinor = 0 -def versionPatch = 0 -def versionBuild = 8 +def versionPatch = 1 +def versionBuild = 0 def buildTime() { def df = new SimpleDateFormat("yyyyMMdd HH:mm 'UTC'") diff --git a/app/src/main/java/org/gnucash/android/ui/account/AccountsActivity.java b/app/src/main/java/org/gnucash/android/ui/account/AccountsActivity.java index a9a260c97..878eae0a7 100644 --- a/app/src/main/java/org/gnucash/android/ui/account/AccountsActivity.java +++ b/app/src/main/java/org/gnucash/android/ui/account/AccountsActivity.java @@ -152,7 +152,7 @@ public class AccountsActivity extends BaseDrawerActivity implements OnAccountCli /** * Configuration for rating the app */ - public static RateThisApp.Config rateAppConfig = new RateThisApp.Config(14, 30);; + public static RateThisApp.Config rateAppConfig = new RateThisApp.Config(14, 50); /** * Adapter for managing the sub-account and transaction fragment pages in the accounts view diff --git a/app/src/main/java/org/gnucash/android/ui/account/DeleteAccountDialogFragment.java b/app/src/main/java/org/gnucash/android/ui/account/DeleteAccountDialogFragment.java index 91663c3c2..0fe8c70ea 100644 --- a/app/src/main/java/org/gnucash/android/ui/account/DeleteAccountDialogFragment.java +++ b/app/src/main/java/org/gnucash/android/ui/account/DeleteAccountDialogFragment.java @@ -99,6 +99,12 @@ public static DeleteAccountDialogFragment newInstance(String accountUID) { return fragment; } + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setStyle(DialogFragment.STYLE_NORMAL, R.style.CustomDialog); + } + @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.dialog_account_delete, container, false); diff --git a/app/src/main/java/org/gnucash/android/ui/transaction/dialog/BulkMoveDialogFragment.java b/app/src/main/java/org/gnucash/android/ui/transaction/dialog/BulkMoveDialogFragment.java index 74469f0ea..2122c96c9 100644 --- a/app/src/main/java/org/gnucash/android/ui/transaction/dialog/BulkMoveDialogFragment.java +++ b/app/src/main/java/org/gnucash/android/ui/transaction/dialog/BulkMoveDialogFragment.java @@ -103,7 +103,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setStyle(DialogFragment.STYLE_NORMAL, R.style.Theme_AppCompat_Light_Dialog); + setStyle(DialogFragment.STYLE_NORMAL, R.style.CustomDialog); } @Override diff --git a/app/src/main/res/layout/radio_group_delete_or_move.xml b/app/src/main/res/layout/radio_group_delete_or_move.xml index 0e7933d2a..63c088348 100644 --- a/app/src/main/res/layout/radio_group_delete_or_move.xml +++ b/app/src/main/res/layout/radio_group_delete_or_move.xml @@ -48,7 +48,7 @@ android:text="@string/label_move_to" /> + android:layout_width="match_parent" + android:layout_height="?android:listPreferredItemHeight"/> diff --git a/app/src/main/res/values-af-rZA/strings.xml b/app/src/main/res/values-af-rZA/strings.xml index 4405a1a7e..c68c7e3c1 100644 --- a/app/src/main/res/values-af-rZA/strings.xml +++ b/app/src/main/res/values-af-rZA/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info diff --git a/app/src/main/res/values-ar-rSA/strings.xml b/app/src/main/res/values-ar-rSA/strings.xml index 6f113e0fa..a20a0ecc5 100644 --- a/app/src/main/res/values-ar-rSA/strings.xml +++ b/app/src/main/res/values-ar-rSA/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info diff --git a/app/src/main/res/values-ca-rES/strings.xml b/app/src/main/res/values-ca-rES/strings.xml index 237766a53..372981249 100644 --- a/app/src/main/res/values-ca-rES/strings.xml +++ b/app/src/main/res/values-ca-rES/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Crea un compte Edita el compte Informació diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index 32d54f207..e9bb88a3e 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info diff --git a/app/src/main/res/values-da-rDK/strings.xml b/app/src/main/res/values-da-rDK/strings.xml index 64f49945d..4a8c1c1b0 100644 --- a/app/src/main/res/values-da-rDK/strings.xml +++ b/app/src/main/res/values-da-rDK/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Opprett konto Rediger konto Informasjon diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index ccfdafc00..385b3bba5 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Neues Konto Konto bearbeiten Info diff --git a/app/src/main/res/values-el-rGR/strings.xml b/app/src/main/res/values-el-rGR/strings.xml index 7dceb5301..1eb4bb06a 100644 --- a/app/src/main/res/values-el-rGR/strings.xml +++ b/app/src/main/res/values-el-rGR/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Δημιουργία Λογαριασμού Επεξεργασία Λογαριασμού Πληροφορίες diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml index 4405a1a7e..c68c7e3c1 100644 --- a/app/src/main/res/values-en-rGB/strings.xml +++ b/app/src/main/res/values-en-rGB/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info diff --git a/app/src/main/res/values-es-rMX/strings.xml b/app/src/main/res/values-es-rMX/strings.xml index 7307dc418..dadd5fb70 100644 --- a/app/src/main/res/values-es-rMX/strings.xml +++ b/app/src/main/res/values-es-rMX/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Crear Cuenta Editar Cuenta Detalles diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 77320ff90..48e4feae8 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Crear cuenta Editar cuenta Información diff --git a/app/src/main/res/values-fi-rFI/strings.xml b/app/src/main/res/values-fi-rFI/strings.xml index 4405a1a7e..c68c7e3c1 100644 --- a/app/src/main/res/values-fi-rFI/strings.xml +++ b/app/src/main/res/values-fi-rFI/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 48e555b33..10ac0756c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Créer un compte Éditer le compte Informations diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu-rHU/strings.xml index dff6c8a4b..d16cedb1f 100644 --- a/app/src/main/res/values-hu-rHU/strings.xml +++ b/app/src/main/res/values-hu-rHU/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info diff --git a/app/src/main/res/values-it-rIT/strings.xml b/app/src/main/res/values-it-rIT/strings.xml index d4f913820..d6df017c2 100644 --- a/app/src/main/res/values-it-rIT/strings.xml +++ b/app/src/main/res/values-it-rIT/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Crea conto Modifica conto Informazioni diff --git a/app/src/main/res/values-iw-rIL/strings.xml b/app/src/main/res/values-iw-rIL/strings.xml index 4405a1a7e..c68c7e3c1 100644 --- a/app/src/main/res/values-iw-rIL/strings.xml +++ b/app/src/main/res/values-iw-rIL/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index 4e4bd3749..462514032 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index 4e4bd3749..462514032 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml new file mode 100644 index 000000000..e3ac6da33 --- /dev/null +++ b/app/src/main/res/values-nb/strings.xml @@ -0,0 +1,564 @@ + + + + + Opprett konto + Rediger konto + Informasjon + Eksport... + Legge til en ny transaksjon i en konto + Ingen kontoer for å vise + Kontonavn + Avbryt + Lagre + Angi passord + Feil passord, prøv igjen + Passord satt + Bekreft passordet ditt + Ugyldig passord bekreftelse. Prøv på nytt + Beskrivelse + Beløp + Ny transaksjon + Ingen transaksjoner å vise + DATO & TID + Konto + DEBET + KREDIT + Kontoer + Transaksjoner + Slett + Slett + Avbryt + Konto slettet + Bekreft sletting + Alle transaksjoner i denne kontoen vil også slettes + Redigere transaksjonen + Legg til notat + FLYTT + %1$d valgt + Saldo: + Eksporter til: + Eksport av transaksjoner + Eksportere alle transaksjoner + Standard eksporteres bare nye transaksjoner siden siste eksport. Merk dette alternativet for å eksportere alle transaksjoner + Feil ved eksport av %1$s + Eksporter + Slette etter eksport + Alle eksporterte transaksjoner slettes når eksport er fullført + Innstillinger + + SD-kort + DropBox + Google Disk + Send til… + + Flytt + Flytt %1$d transaksjon(er) + Målkonto + Aksesser SD-kort + Kan ikke flytte transaksjonene. \nMålkontoen bruker en annen valuta enn opprinnelig konto + Generelt + Om + Velg standardvaluta + Standardvaluta + Standardvalutaen som skal tilordnes nye kontoer + Aktiverer registrering av transaksjoner i GnuCash for Android + Aktiverer oppretting av kontoer i GnuCash for Android + Dine GnuCash data + Lese og endre GnuCash data + Registrere transaksjoner i GnuCash + Opprette kontoer i GnuCash + Vis konto + Opprett konto + Velg kontoer å opprette + + Afghanske + Algeriske dinarer + Argentinsk Peso + Armensk Dram + Arubiske gylden + Australske Dollar + Aserbajdsjanske Manat + Bahamian Dollar + Bahraini dinarer + Baht + Balboa + Barbados Dollar + Hviterussiske rubler + Belize Dollar + Bermudian Dollar + Bolivar Fuerte + Boliviano + Brasilianske Real + Brunei Dollar + Bulgarske Lev + Burundi Franc + Kanadiske Dollar + Kapp Verde Escudo + Caymanøyene Dollar + CFA Franc BCEAO + CFA Franc BEAC + CFP Franc + Chilenske pesos + Testing valuta + Colombianske Peso + Comoro Franc + Kongolesiske Franc + Konvertible Mark + Cordoba Oro + Costa Rica kolon + Kroatiske Kuna + Cubansk konvertibel Peso + Cubansk Peso + Tsjekkiske Koruna + Dalasi + Dansk Krone + Denar + Djibouti Franc + Dobra + Dominikanske pesos + Dong + Østkaribiske Dollar + Egyptisk pund + El Salvador kolon + Ethiopian Birr + Euro + Falklandske pund + Fiji Dollar + Forint + Ghana Cedi + Gibraltarske pund + Gull + Gourde + Guarani + Guinea Franc + Guyana Dollar + Hong Kong Dollar + Hryvnia + Islandske kroner + Indiske rupi + Iranske Rial + Irakiske dinarer + Jamaicanske Dollar + Jordanske dinarer + Kenyanske Shilling + Kina + Kip + Kuwaitiske dinarer + Kwacha + Kwanza + Kyat + Lari + Latviske Lats + Libanesiske pund + Lek + Lempira + Leone + Liberiske Dollar + Libyske dinarer + Lilangeni + Litauisk Litas + Loti + Gassiske Ariary + Malaysiske Ringgit + Mauritius rupi + Meksikansk Peso + Meksikansk Unidad de inversjon (UDI) + Moldova Leu + Marokkanske Dirham + Mosambik Metical + Mvdol + Naira + Nakfa + Namibiske Dollar + Nepalske rupi + Nederlandske antillegylden + Israelske shekel + Nye rumenske Leu + Nye taiwanske Dollar + Newzealandske Dollar + Ngultrum + Nordkoreanske Won + Norske kroner + Nuevo Sol + Ouguiya + Pa\'anga + Pakistanske rupi + Palladium + Pataca + Filippinske Peso + Platina + Pund Sterling + Pula + Qatari Rial + Quetzal + Rand + Omansk Rial + Riel + Rufiyaa + Rupiah + Russisk rubel + Rwanda Franc + Sankthelenske pund + Saudiarabiske Riyal + SDR (spesielle tegning rett) + Serbiske dinarer + Seychellene rupi + Sølv + Singapor Dollar + Salomonøyene Dollar + Som + Somaliske Shilling + Somoni + Sør Sudanske pund + Srilankiske rupi + Sucre + Sudanske pund + Surinam Dollar + Svenske kroner + Sveitsiske Franc + Syriske pund + Taka + Tala + Tanzanianske Shilling + Tenge + Ingen valuta + Trinidad og Tobagos Dollar + Tugrik + Tunisiske dinarer + Tyrkiske Lira + Turkmensk nye Manat + UAE Dirham + Ugandiske Shilling + UIC Franc + Unidad de Valor Real + Unidades de fomento + Uruguay Peso no Unidades Indexadas (URUIURUI) + Uruguayanske peso + US Dollar + Usbekiske Sum + Vatu + WIR Euro + WIR Franc + Won + Yemeni Rial + Yen + Yuan Renminbi + Zambiske Kwacha + Zimbabwiske Dollar + Zloty + + Det finnes ingen kontoer i GnuCash.\nOpprett en konto før du legger til en widget + Byggversjon + Lisens + Apache Lisens v2.0. Klikk for mer informasjon + Generelle innstillinger + Velg konto + Det finnes ingen transaksjoner som er tilgjengelige for eksport + Passord + Passordpreferanser + Passord aktivert + Passord deaktivert + Endre passord + Om GnuCash + En mobil økonomistyrer og utgiftsfører laget for Android + Om + %1$s filen er eksportert til: \n + GnuCash Android %1$s eksport + GnuCash Android eksport fra + Transaksjoner + Transaksjonsinnstillinger + Kontoinnstillinger + Standard transaksjonstype + Standard transaksjonstype å bruke, kredit- eller debet + + KREDIT + DEBET + + Er du sikker på at du vil slette alle transaksjoner? + Er du sikker på at du vil slette denne transaksjonen? + Eksport + Eksportere alle transaksjoner + Slett eksporterte transaksjoner + Standard eksport e-post + Standard postadresse å sende eksporter til. Du kan endre dette når du eksporterer. + Overføringskonto + Alle transaksjoner blir en overføring fra en konto til en annen + Aktiver dobbel bokføring + Balanse + Angi kontonavn for å opprette en konto + Valuta + Overordnet konto + Bruk XML OFX topptekst + Aktiver dette alternativet når du eksporterer til tredjeparts programvare, borsett fra GnuCash for PC + Hva er nytt + +- Nytt Material app design \n +- Multivaluta transaksjoner \n +- Kalkulator til transaksjonsbeløp \n +- Forbedrede rapport muligheter \n +- Ny Hjelp & Tilbakemeldingsseksjon \n +- Mange feilrettinger og forbedringer \n + Avvis + Angi et beløp for å lagre transaksjonen + Multi-valutatransaksjoner kan ikke endres + Importere GnuCash kontoer + Importere kontoer + Det oppstod en feil under import av GnuCash kontoene + GnuCash kontoer importert + Importere kontostrukturen eksportert fra GnuCash desktop + Importere GnuCash XML + Slett alle kontoer i databasen. Alle transaksjoner vil også bli slettet. + Slette alle kontoer + Kontoer + Alle kontoer ble slettet + Er du sikker på at du vil slette alle kontoer og transaksjoner? \n\nDenne operasjonen kan ikke angres! + Kontotype + Alle transaksjoner i alle kontoer vil bli slettet! + Slett alle transaksjoner + Alle transaksjoner slettet! + Importere kontoer + Trykk igjen for å bekrefte. ALLE oppføringene slettes!! + Transaksjoner + Underkontoer + Søk + Standard eksportformat + Filformat som skal brukes som standard når du eksporterer transaksjoner + Eksporter transaksjoner… + Gjentakelse + Ubalanse + Eksportere transaksjoner + Ingen gjentakende transaksjoner å vise. + Slettet gjentakende transaksjon + Plassholder-konto + Standardkontoen for overføring + + %d under-konto + %d under-kontoer + + + KONTANTER + BANK + KREDITTKORT + AKTIVA + GJELD + INNTEKT + UTGIFT + UTGÅENDE + INNGÅENDE + EGENKAPITAL + VALUTA + AKSJE + FOND + TRADING + + + QIF + OFX + XML + + Velg en farge + Konto farge & Type + Slett underkontoer + Siste + Favoritter + Alle + Oppretter standard GnuCash kontostruktur + Opprette standardkontoer + Alle eksisterende kontoer og transaksjoner på enheten blir slettet.\n\nEr du sikker på at du vil fortsette? + Planlagte transaksjoner + Velkommen til GnuCash Android! \nDu kan enten opprette et hierarki av brukte kontoer, eller importere din egen GnuCash kontostruktur. \n\nBegge alternativer er også tilgjengelige i app innstillinger så du kan velge senere. + Transaksjoner + Velg sted for eksport + Notat + Bruke + Motta + Uttak + Innskudd + Betaling + Belast + Reduser + Øk + Inntekt + Rabatt + Utgift + Regning + Faktura + Kjøp + Selg + Gjentar + Ingen nylig sikkerhetskopi funnet + Åpningssaldoer + Egenkapital + Aktiver lagring av den gjeldende saldoen (før sletting av transaksjoner) som ny startsaldo etter sletting av transaksjoner + Lagre konto startsaldoer + OFX støtter ikke dobbeltoppføringstransaksjoner + Genererer separate QIF filer per valuta + Transaksjonssplitter + Ubalanse: + Legge til splitt + Favoritt + Navigasjonskuffen åpnet + Navigasjonsskuff lukket + Rapporter + Sektordiagram + Linjediagram + Stolpediagram + Rapportinnstillinger + Velg valuta + Kontofarge i rapporter + Bruke kontofargen i søyle/sektordiagrammet + Rapporter + Sorter etter størrelse + Vis forklaring + Vis etiketter + Vis prosent + Viser gjennomsnittslinjer + Grupper mindre deler + Ingen diagramdata tilgjengelig + Total + Totalt + Andre + Prosentandelen av valgte verdien beregnet ut i fra totalbeløpet + Prosentandelen av valgte verdien beregnet ut i fra gjeldende stacked bar amount + Lagre som mal + Denne kontoen inneholder transaksjoner. \nHva vil du gjøre med disse transaksjonene + Denne kontoen inneholder underordnede kontoer. \nHva vil du gjøre med disse + Slett transaksjoner + Opprette og angi en konto for overføring eller deaktivere dobbel bokføring for å lagre transaksjonen + Trykk for å opprette plan + Gjenopprette sikkerhetskopi… + Backup & eksport + DropBox Sync + Sikkerhetskopiering + Aktiver synkronisering til DropBox + Velg GnuCash XML-fil + Innstillinger for sikkerhetskopiering + Opprett sikkerhetskopi + Som standard lagres sikkerhetskopier på SD minne-kortet + Velg en bestemt backup å gjenopprette + Sikkerhetskopiering vellykket + Sikkerhetskopiering mislyktes + Eksporterer alle kontoer og transaksjoner + Google Drive Sync + Aktiver Sync til Google Disk + Installer en filbehandler for å velge filer + Velg sikkerhetskopien som skal gjenopprettes + Favoritter + Åpne… + Rapporter + Planlagte transaksjoner + Eksport… + Innstillinger + + Daglig + Hver %d dag + + + Ukentlig + Hver %d uke + + + Månedlig + Hver %d måned + + + Årlig + Hvert %d år + + Aktiver Logging av feil + Send automatisk informasjon om feil på app til utviklerne. + Format + Finner ikke sikkerhetskopimappen. Kontroller at SD-kortet er montert! + Angi ditt gamle passord + Skriv inn ditt nye passord + Planlagte eksporteringer + Eksporter + Ingen planlagte eksporter å vise + Opprette ekporteringsplan + Eksportert til: %1$s + Forklaringen er for lang + Kontobeskrivelse + Ingen nylige kontoer + Ingen favoritt kontoer + Planlagte handlinger + "Avsluttet. Sist kjørt på %1$s" + Velg en søyle for å vise detaljer + Neste + Ferdig + Standardvaluta + Konfigurering av konto + Velg valuta + Alternativer for tilbakemelding + Opprette standardkontoer + Import kontoene mine + La meg håndtere det + Andre… + Send feilrapporter automatisk + Deaktivere programstopprapporter + Tilbake + Oppsett av GnuCash + Velkommen til GnuCash + Før du hopper i det i \nla oss sette opp et par ting\n\nTrykk neste for å fortsette + Splitt Editor + Sjekk at alle splitter har gyldig beløp før lagring! + Ugyldig uttrykk! + Planlagt gjentakende transaksjon + En valutakurs kreves + Det konverterte beløpet kreves + Overføre penger + + Merk et stykke for å se detaljer + Periode: + Fra: + Til: + Oppgi enten konvertert beløp eller valutakursen for å overføre penger + Valutakurs + Hent verdi + Konvertert beløp + Ark + Utgifter for de siste 3 månedene + Totalt Eiendeler + Totalt Gjeld + Formue + Eiendeler + Gjeld + Egenkapital + + Flytt til: + Gruppere etter + Måned + Kvartal + År + Balanseskjema + Totalt: + Google + Community + Oversette GnuCash + Dele ideer, diskutere endringer eller rapportere problemer + Oversette eller korrekturles på CrowdIn + Ingen kompatible apper til å motta de eksporterte transaksjonene! + Move... + Duplicate + + Gjeldende måned + Siste 3 måneder + Siste 6 måneder + Siste 12 måneder + Tidsrom + Tilpasset tidsrom… + + diff --git a/app/src/main/res/values-nl-rNL/strings.xml b/app/src/main/res/values-nl-rNL/strings.xml index e26d8cf7c..92b7a0758 100644 --- a/app/src/main/res/values-nl-rNL/strings.xml +++ b/app/src/main/res/values-nl-rNL/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Nieuwe rekening Rekening bewerken Info diff --git a/app/src/main/res/values-no-rNO/strings.xml b/app/src/main/res/values-no-rNO/strings.xml index 7cc6c2e35..e3ac6da33 100644 --- a/app/src/main/res/values-no-rNO/strings.xml +++ b/app/src/main/res/values-no-rNO/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Opprett konto Rediger konto Informasjon diff --git a/app/src/main/res/values-pl-rPL/strings.xml b/app/src/main/res/values-pl-rPL/strings.xml index 4ea6191a9..037c42413 100644 --- a/app/src/main/res/values-pl-rPL/strings.xml +++ b/app/src/main/res/values-pl-rPL/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Utwórz konto Edytuj konto Info diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 931acfce0..e4462c438 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Criar Conta Editar Conta Info diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 8e1b45fa1..41a4bd963 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Criar Conta Editar Conta Informação diff --git a/app/src/main/res/values-ro-rRO/strings.xml b/app/src/main/res/values-ro-rRO/strings.xml index 32d54f207..e9bb88a3e 100644 --- a/app/src/main/res/values-ro-rRO/strings.xml +++ b/app/src/main/res/values-ro-rRO/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 194d130ea..5049bae9d 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Создать счёт Редактировать счёт Информация diff --git a/app/src/main/res/values-sr-rSP/strings.xml b/app/src/main/res/values-sr-rSP/strings.xml index a016973b5..6dfa1c6c3 100644 --- a/app/src/main/res/values-sr-rSP/strings.xml +++ b/app/src/main/res/values-sr-rSP/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Креирај рачун Уреди рачун Инфо diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index 4405a1a7e..c68c7e3c1 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info diff --git a/app/src/main/res/values-tr-rTR/strings.xml b/app/src/main/res/values-tr-rTR/strings.xml index 1725c5f37..a9ade4bde 100644 --- a/app/src/main/res/values-tr-rTR/strings.xml +++ b/app/src/main/res/values-tr-rTR/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Hesap Oluştur Hesabı Düzenle Bilgilendirme diff --git a/app/src/main/res/values-uk-rUA/strings.xml b/app/src/main/res/values-uk-rUA/strings.xml index d54528d16..9c123a97a 100644 --- a/app/src/main/res/values-uk-rUA/strings.xml +++ b/app/src/main/res/values-uk-rUA/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Створити рахунок Редагувати рахунок Інформація diff --git a/app/src/main/res/values-vi-rVN/strings.xml b/app/src/main/res/values-vi-rVN/strings.xml index 4e4bd3749..462514032 100644 --- a/app/src/main/res/values-vi-rVN/strings.xml +++ b/app/src/main/res/values-vi-rVN/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + Create Account Edit Account Info diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 3a675aa18..61b7b55ec 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + 创建科目 修改科目 信息 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 98921c6c9..becfd7de5 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + 创建科目 修改科目 信息 diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 4ad7a3e83..37a1f3145 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -141,4 +141,8 @@ @android:color/black + + \ No newline at end of file diff --git a/crowdin.yaml b/crowdin.yaml index 061390717..cadbb798b 100644 --- a/crowdin.yaml +++ b/crowdin.yaml @@ -10,4 +10,5 @@ files: de: de ru: ru fr: fr + nb: nb es-ES: es From 041c4a3904ca6424ee07a62375ac14b7731e4b82 Mon Sep 17 00:00:00 2001 From: Yongxin Wang Date: Sat, 31 Oct 2015 12:15:52 +0800 Subject: [PATCH 04/17] fix bug when import old exports --- .../main/java/org/gnucash/android/model/Transaction.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/gnucash/android/model/Transaction.java b/app/src/main/java/org/gnucash/android/model/Transaction.java index f6fc9beaa..f0e2586a1 100644 --- a/app/src/main/java/org/gnucash/android/model/Transaction.java +++ b/app/src/main/java/org/gnucash/android/model/Transaction.java @@ -259,8 +259,10 @@ public Money getImbalance(){ Money imbalance = Money.createZeroInstance(mCurrencyCode); for (Split split : mSplitList) { if (!split.getValue().getCurrency().getCurrencyCode().equals(mCurrencyCode)) { - // values in transactions are always in the same currency - throw new RuntimeException("Splits values in transaction are not in the same currency"); + // this may happen when importing XML exported from GNCA before 2.0.0 + // these transactions should only be imported from XML exported from GNC desktop + // so imbalance split should not be generated for them + return Money.createZeroInstance(mCurrencyCode); } Money amount = split.getValue().absolute(); if (split.getType() == TransactionType.DEBIT) From a2a8d5015d890b4c14ca169a04ed1b3a338109d6 Mon Sep 17 00:00:00 2001 From: Ngewi Fet Date: Tue, 3 Nov 2015 13:53:13 +0100 Subject: [PATCH 05/17] Use commodity fraction digits instead of those from Currency Currency fraction digits seem to vary with Android/Java version and device. This leads to inconsistencies in the way balances are calculated. By using our Commodities, we are sure that we get consistent values across all devices since pre-load the database ourselves --- .../android/db/CommoditiesDbAdapter.java | 6 +- .../gnucash/android/db/DatabaseHelper.java | 3 +- .../gnucash/android/db/DatabaseSchema.java | 2 +- .../gnucash/android/db/MigrationHelper.java | 7 +-- .../gnucash/android/db/SplitsDbAdapter.java | 17 +++--- .../android/export/xml/GncXmlExporter.java | 17 +++--- .../android/export/xml/GncXmlHelper.java | 9 +-- .../importer/CommoditiesXmlHandler.java | 15 +++++ .../org/gnucash/android/model/Commodity.java | 61 ++++++++++++++++--- .../java/org/gnucash/android/model/Money.java | 43 +++++++------ .../receivers/TransactionRecorder.java | 5 +- .../android/ui/account/AccountsActivity.java | 2 +- .../dialog/TransferFundsDialogFragment.java | 6 +- .../ui/util/widget/CalculatorEditText.java | 7 ++- .../test/unit/export/GncXmlHelperTest.java | 8 ++- .../android/test/unit/model/AccountTest.java | 15 +++++ .../test/unit/model/CommodityTest.java | 49 +++++++++++++++ .../android/test/unit/model/MoneyTest.java | 9 +++ .../android/test/unit/model/SplitTest.java | 8 +++ 19 files changed, 224 insertions(+), 65 deletions(-) create mode 100644 app/src/test/java/org/gnucash/android/test/unit/model/CommodityTest.java diff --git a/app/src/main/java/org/gnucash/android/db/CommoditiesDbAdapter.java b/app/src/main/java/org/gnucash/android/db/CommoditiesDbAdapter.java index 3a62142e2..043a8291a 100644 --- a/app/src/main/java/org/gnucash/android/db/CommoditiesDbAdapter.java +++ b/app/src/main/java/org/gnucash/android/db/CommoditiesDbAdapter.java @@ -37,7 +37,7 @@ protected SQLiteStatement compileReplaceStatement(@NonNull final Commodity commo + CommodityEntry.COLUMN_MNEMONIC + " , " + CommodityEntry.COLUMN_LOCAL_SYMBOL + " , " + CommodityEntry.COLUMN_CUSIP + " , " - + CommodityEntry.COLUMN_FRACTION + " , " + + CommodityEntry.COLUMN_SMALLEST_FRACTION + " , " + CommodityEntry.COLUMN_QUOTE_FLAG + " ) VALUES ( ? , ? , ? , ? , ? , ? , ? , ? ) "); } @@ -48,7 +48,7 @@ protected SQLiteStatement compileReplaceStatement(@NonNull final Commodity commo mReplaceStatement.bindString(4, commodity.getMnemonic()); mReplaceStatement.bindString(5, commodity.getLocalSymbol()); mReplaceStatement.bindString(6, commodity.getCusip()); - mReplaceStatement.bindLong(7, commodity.getFraction()); + mReplaceStatement.bindLong(7, commodity.getSmallestFraction()); mReplaceStatement.bindLong(8, commodity.getQuoteFlag()); return mReplaceStatement; @@ -62,7 +62,7 @@ public Commodity buildModelInstance(@NonNull final Cursor cursor) { String cusip = cursor.getString(cursor.getColumnIndexOrThrow(CommodityEntry.COLUMN_CUSIP)); String localSymbol = cursor.getString(cursor.getColumnIndexOrThrow(CommodityEntry.COLUMN_LOCAL_SYMBOL)); - int fraction = cursor.getInt(cursor.getColumnIndexOrThrow(CommodityEntry.COLUMN_FRACTION)); + int fraction = cursor.getInt(cursor.getColumnIndexOrThrow(CommodityEntry.COLUMN_SMALLEST_FRACTION)); int quoteFlag = cursor.getInt(cursor.getColumnIndexOrThrow(CommodityEntry.COLUMN_QUOTE_FLAG)); Commodity commodity = new Commodity(fullname, mnemonic, fraction); diff --git a/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java b/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java index 968b4c094..5af6e0e97 100644 --- a/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java +++ b/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java @@ -31,7 +31,6 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.Locale; import javax.xml.parsers.ParserConfigurationException; @@ -143,7 +142,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { + CommodityEntry.COLUMN_MNEMONIC + " varchar(255) not null, " + CommodityEntry.COLUMN_LOCAL_SYMBOL+ " varchar(255) not null default '', " + CommodityEntry.COLUMN_CUSIP + " varchar(255), " - + CommodityEntry.COLUMN_FRACTION + " integer not null, " + + CommodityEntry.COLUMN_SMALLEST_FRACTION + " integer not null, " + CommodityEntry.COLUMN_QUOTE_FLAG + " integer not null, " + CommodityEntry.COLUMN_CREATED_AT + " TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, " + CommodityEntry.COLUMN_MODIFIED_AT + " TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP " diff --git a/app/src/main/java/org/gnucash/android/db/DatabaseSchema.java b/app/src/main/java/org/gnucash/android/db/DatabaseSchema.java index de4b3e72b..c39568a32 100644 --- a/app/src/main/java/org/gnucash/android/db/DatabaseSchema.java +++ b/app/src/main/java/org/gnucash/android/db/DatabaseSchema.java @@ -160,7 +160,7 @@ public static abstract class CommodityEntry implements CommonColumns { /** * The fraction is the number of sub-units that the basic commodity can be divided into */ - public static final String COLUMN_FRACTION = "fraction"; + public static final String COLUMN_SMALLEST_FRACTION = "fraction"; /** * A CUSIP is a nine-character alphanumeric code that identifies a North American financial security diff --git a/app/src/main/java/org/gnucash/android/db/MigrationHelper.java b/app/src/main/java/org/gnucash/android/db/MigrationHelper.java index 943087c0e..b8039c6b0 100644 --- a/app/src/main/java/org/gnucash/android/db/MigrationHelper.java +++ b/app/src/main/java/org/gnucash/android/db/MigrationHelper.java @@ -53,7 +53,6 @@ import java.sql.Timestamp; import java.util.ArrayList; import java.util.List; -import java.util.UUID; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; @@ -853,7 +852,7 @@ static int upgradeDbToVersion9(SQLiteDatabase db){ + CommodityEntry.COLUMN_MNEMONIC + " varchar(255) not null, " + CommodityEntry.COLUMN_LOCAL_SYMBOL+ " varchar(255) not null default '', " + CommodityEntry.COLUMN_CUSIP + " varchar(255), " - + CommodityEntry.COLUMN_FRACTION + " integer not null, " + + CommodityEntry.COLUMN_SMALLEST_FRACTION + " integer not null, " + CommodityEntry.COLUMN_QUOTE_FLAG + " integer not null, " + CommodityEntry.COLUMN_CREATED_AT + " TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, " + CommodityEntry.COLUMN_MODIFIED_AT + " TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP " @@ -958,7 +957,7 @@ static int upgradeDbToVersion9(SQLiteDatabase db){ String query = "SELECT " + "A." + AccountEntry.COLUMN_UID + " AS account_uid " + " FROM " + AccountEntry.TABLE_NAME + " AS A, " + CommodityEntry.TABLE_NAME + " AS C " + " WHERE A." + AccountEntry.COLUMN_CURRENCY + " = C." + CommodityEntry.COLUMN_MNEMONIC - + " AND C." + CommodityEntry.COLUMN_FRACTION + "= 1"; + + " AND C." + CommodityEntry.COLUMN_SMALLEST_FRACTION + "= 1"; Cursor cursor = db.rawQuery(query, null); @@ -1007,7 +1006,7 @@ static int upgradeDbToVersion9(SQLiteDatabase db){ query = "SELECT " + "A." + AccountEntry.COLUMN_UID + " AS account_uid " + " FROM " + AccountEntry.TABLE_NAME + " AS A, " + CommodityEntry.TABLE_NAME + " AS C " + " WHERE A." + AccountEntry.COLUMN_CURRENCY + " = C." + CommodityEntry.COLUMN_MNEMONIC - + " AND C." + CommodityEntry.COLUMN_FRACTION + "= 1000"; + + " AND C." + CommodityEntry.COLUMN_SMALLEST_FRACTION + "= 1000"; cursor = db.rawQuery(query, null); diff --git a/app/src/main/java/org/gnucash/android/db/SplitsDbAdapter.java b/app/src/main/java/org/gnucash/android/db/SplitsDbAdapter.java index b96b85fa1..84215fc81 100644 --- a/app/src/main/java/org/gnucash/android/db/SplitsDbAdapter.java +++ b/app/src/main/java/org/gnucash/android/db/SplitsDbAdapter.java @@ -28,6 +28,7 @@ import org.gnucash.android.app.GnuCashApplication; import org.gnucash.android.model.AccountType; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.Split; import org.gnucash.android.model.TransactionType; @@ -210,21 +211,21 @@ private Money calculateSplitBalance(List accountUIDList, String currency Money total = Money.createZeroInstance(currencyCode); CommoditiesDbAdapter commoditiesDbAdapter = null; PricesDbAdapter pricesDbAdapter = null; - Currency currency = null; + Commodity commodity = null; String currencyUID = null; while (cursor.moveToNext()) { long amount_num = cursor.getLong(0); long amount_denom = cursor.getLong(1); - String commodity = cursor.getString(2); + String commodityCode = cursor.getString(2); //Log.d(getClass().getName(), commodity + " " + amount_num + "/" + amount_denom); - if (commodity.equals("XXX") || amount_num == 0) { + if (commodityCode.equals("XXX") || amount_num == 0) { // ignore custom currency continue; } if (!hasDebitNormalBalance) { amount_num = -amount_num; } - if (commodity.equals(currencyCode)) { + if (commodityCode.equals(currencyCode)) { // currency matches total = total.add(new Money(amount_num, amount_denom, currencyCode)); //Log.d(getClass().getName(), "currency " + commodity + " sub - total " + total); @@ -233,11 +234,11 @@ private Money calculateSplitBalance(List accountUIDList, String currency if (commoditiesDbAdapter == null) { commoditiesDbAdapter = new CommoditiesDbAdapter(mDb); pricesDbAdapter = new PricesDbAdapter(mDb); - currency = Currency.getInstance(currencyCode); + commodity = commoditiesDbAdapter.getCommodity(currencyCode); currencyUID = commoditiesDbAdapter.getCommodityUID(currencyCode); } // get price - String commodityUID = commoditiesDbAdapter.getCommodityUID(commodity); + String commodityUID = commoditiesDbAdapter.getCommodityUID(commodityCode); Pair price = pricesDbAdapter.getPrice(commodityUID, currencyUID); if (price.first <= 0 || price.second <= 0) { // no price exists, just ignore it @@ -245,8 +246,8 @@ private Money calculateSplitBalance(List accountUIDList, String currency } BigDecimal amount = Money.getBigDecimal(amount_num, amount_denom); BigDecimal amountConverted = amount.multiply(new BigDecimal(price.first)) - .divide(new BigDecimal(price.second), currency.getDefaultFractionDigits(), BigDecimal.ROUND_HALF_EVEN); - total = total.add(new Money(amountConverted, currency)); + .divide(new BigDecimal(price.second), commodity.getSmallestFractionDigits(), BigDecimal.ROUND_HALF_EVEN); + total = total.add(new Money(amountConverted, commodity)); //Log.d(getClass().getName(), "currency " + commodity + " sub - total " + total); } } diff --git a/app/src/main/java/org/gnucash/android/export/xml/GncXmlExporter.java b/app/src/main/java/org/gnucash/android/export/xml/GncXmlExporter.java index 8577781f7..6d8179ebd 100644 --- a/app/src/main/java/org/gnucash/android/export/xml/GncXmlExporter.java +++ b/app/src/main/java/org/gnucash/android/export/xml/GncXmlExporter.java @@ -23,6 +23,7 @@ import com.crashlytics.android.Crashlytics; +import org.gnucash.android.db.CommoditiesDbAdapter; import org.gnucash.android.db.DatabaseSchema; import org.gnucash.android.db.TransactionsDbAdapter; import org.gnucash.android.export.ExportFormat; @@ -31,6 +32,7 @@ import org.gnucash.android.model.Account; import org.gnucash.android.model.AccountType; import org.gnucash.android.model.BaseModel; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.PeriodType; import org.gnucash.android.model.ScheduledAction; @@ -147,8 +149,9 @@ private void exportAccounts(XmlSerializer xmlSerializer) throws IOException { xmlSerializer.endTag(null, GncXmlHelper.TAG_COMMODITY_ID); xmlSerializer.endTag(null, GncXmlHelper.TAG_ACCOUNT_COMMODITY); // commodity scu + Commodity commodity = CommoditiesDbAdapter.getInstance().getCommodity(acctCurrencyCode); xmlSerializer.startTag(null, GncXmlHelper.TAG_COMMODITY_SCU); - xmlSerializer.text(Integer.toString((int) Math.pow(10, Currency.getInstance(acctCurrencyCode).getDefaultFractionDigits()))); + xmlSerializer.text(Integer.toString(commodity.getSmallestFraction())); xmlSerializer.endTag(null, GncXmlHelper.TAG_COMMODITY_SCU); // account description String description = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseSchema.AccountEntry.COLUMN_DESCRIPTION)); @@ -283,7 +286,7 @@ private void exportTransactions(XmlSerializer xmlSerializer, boolean exportTempl TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_TIMESTAMP + " ASC , " + TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_UID + " ASC "); String lastTrxUID = ""; - Currency trxCurrency = null; + Commodity trnCommodity = null; String denomString = "100"; if (exportTemplates) { @@ -319,14 +322,14 @@ private void exportTransactions(XmlSerializer xmlSerializer, boolean exportTempl xmlSerializer.text(curTrxUID); xmlSerializer.endTag(null, GncXmlHelper.TAG_TRX_ID); // currency - String currency = cursor.getString(cursor.getColumnIndexOrThrow("trans_currency")); - trxCurrency = Currency.getInstance(currency); + String currencyCode = cursor.getString(cursor.getColumnIndexOrThrow("trans_currency")); + trnCommodity = CommoditiesDbAdapter.getInstance().getCommodity(currencyCode);//Currency.getInstance(currencyCode); xmlSerializer.startTag(null, GncXmlHelper.TAG_TRX_CURRENCY); xmlSerializer.startTag(null, GncXmlHelper.TAG_COMMODITY_SPACE); xmlSerializer.text("ISO4217"); xmlSerializer.endTag(null, GncXmlHelper.TAG_COMMODITY_SPACE); xmlSerializer.startTag(null, GncXmlHelper.TAG_COMMODITY_ID); - xmlSerializer.text(currency); + xmlSerializer.text(currencyCode); xmlSerializer.endTag(null, GncXmlHelper.TAG_COMMODITY_ID); xmlSerializer.endTag(null, GncXmlHelper.TAG_TRX_CURRENCY); // date posted, time which user put on the transaction @@ -456,14 +459,14 @@ private void exportTransactions(XmlSerializer xmlSerializer, boolean exportTempl slotValues.add(GncXmlHelper.formatTemplateSplitAmount(splitAmount)); slotKeys.add(GncXmlHelper.KEY_CREDIT_NUMERIC); slotTypes.add(GncXmlHelper.ATTR_VALUE_NUMERIC); - slotValues.add(GncXmlHelper.formatSplitAmount(splitAmount, trxCurrency)); + slotValues.add(GncXmlHelper.formatSplitAmount(splitAmount, trnCommodity)); } else { slotKeys.add(GncXmlHelper.KEY_DEBIT_FORMULA); slotTypes.add(GncXmlHelper.ATTR_VALUE_STRING); slotValues.add(GncXmlHelper.formatTemplateSplitAmount(splitAmount)); slotKeys.add(GncXmlHelper.KEY_DEBIT_NUMERIC); slotTypes.add(GncXmlHelper.ATTR_VALUE_NUMERIC); - slotValues.add(GncXmlHelper.formatSplitAmount(splitAmount, trxCurrency)); + slotValues.add(GncXmlHelper.formatSplitAmount(splitAmount, trnCommodity)); } exportSlots(xmlSerializer, slotKeys, slotTypes, slotValues); diff --git a/app/src/main/java/org/gnucash/android/export/xml/GncXmlHelper.java b/app/src/main/java/org/gnucash/android/export/xml/GncXmlHelper.java index 92de9512e..6a13908ca 100644 --- a/app/src/main/java/org/gnucash/android/export/xml/GncXmlHelper.java +++ b/app/src/main/java/org/gnucash/android/export/xml/GncXmlHelper.java @@ -19,6 +19,8 @@ import android.support.annotation.NonNull; +import org.gnucash.android.db.CommoditiesDbAdapter; +import org.gnucash.android.model.Commodity; import org.gnucash.android.ui.transaction.TransactionFormFragment; import java.math.BigDecimal; @@ -194,12 +196,11 @@ public static BigDecimal parseSplitAmount(String amountString) throws ParseExcep /** * Formats money amounts for splits in the format 2550/100 * @param amount Split amount as BigDecimal - * @param trxCurrency Currency of the transaction + * @param commodity Commodity of the transaction * @return Formatted split amount */ - public static String formatSplitAmount(BigDecimal amount, Currency trxCurrency){ - int fractionDigits = trxCurrency.getDefaultFractionDigits(); - int denomInt = (int) Math.pow(10, fractionDigits); + public static String formatSplitAmount(BigDecimal amount, Commodity commodity){ + int denomInt = commodity.getSmallestFraction(); BigDecimal denom = new BigDecimal(denomInt); String denomString = Integer.toString(denomInt); diff --git a/app/src/main/java/org/gnucash/android/importer/CommoditiesXmlHandler.java b/app/src/main/java/org/gnucash/android/importer/CommoditiesXmlHandler.java index 6b4ce3a1c..34e75e032 100644 --- a/app/src/main/java/org/gnucash/android/importer/CommoditiesXmlHandler.java +++ b/app/src/main/java/org/gnucash/android/importer/CommoditiesXmlHandler.java @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2015 Ngewi Fet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.gnucash.android.importer; import android.database.sqlite.SQLiteDatabase; diff --git a/app/src/main/java/org/gnucash/android/model/Commodity.java b/app/src/main/java/org/gnucash/android/model/Commodity.java index 169e2d15b..154c3169b 100644 --- a/app/src/main/java/org/gnucash/android/model/Commodity.java +++ b/app/src/main/java/org/gnucash/android/model/Commodity.java @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2015 Ngewi Fet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.gnucash.android.model; /** @@ -16,19 +31,19 @@ public enum Namespace { ISO4217 } //Namespace for commodities private String mFullname; private String mCusip; private String mLocalSymbol = ""; - private int mFraction; + private int mSmallestFraction; private int mQuoteFlag; /** * Create a new commodity * @param fullname Official full name of the currency * @param mnemonic Official abbreviated designation for the currency - * @param fraction Number of sub-units that the basic commodity can be divided into + * @param smallestFraction Number of sub-units that the basic commodity can be divided into, as power of 10. e.g. 10^<number_of_fraction_digits> */ - public Commodity(String fullname, String mnemonic, int fraction){ + public Commodity(String fullname, String mnemonic, int smallestFraction){ this.mFullname = fullname; this.mMnemonic = mnemonic; - this.mFraction = fraction; + setSmallestFraction(smallestFraction); } public Namespace getNamespace() { @@ -88,12 +103,42 @@ public void setLocalSymbol(String localSymbol) { this.mLocalSymbol = localSymbol; } - public int getFraction() { - return mFraction; + /** + * Returns the smallest fraction supported by the commodity as a power of 10. + *

i.e. for commodities with no fractions, 1 is returned, for commodities with 2 fractions, 100 is returned

+ * @return Smallest fraction as power of 10 + */ + public int getSmallestFraction() { + return mSmallestFraction; + } + + /** + * Returns the (minimum) number of digits that this commodity supports in its fractional part + * @return Number of digits in fraction + */ + public int getSmallestFractionDigits(){ + switch (mSmallestFraction) { + case 1: return 0; + case 10: return 1; + case 100: return 2; + case 1000: return 3; + default: + throw new UnsupportedOperationException("Invalid fraction digits in commodity with fraction: " + mSmallestFraction); + } } - public void setFraction(int fraction) { - this.mFraction = fraction; + /** + * Sets the smallest fraction for the commodity. + *

The fraction is a power of 10. So commodities with 2 fraction digits, have fraction of 10^2 = 100.
+ * If the parameter is any other value, a default fraction of 100 will be set

+ * @param smallestFraction Smallest fraction as power of ten + * @throws IllegalArgumentException if the smallest fraction is not a power of 10 + */ + public void setSmallestFraction(int smallestFraction) { + if (smallestFraction != 1 && smallestFraction != 10 && smallestFraction != 100 && smallestFraction != 1000 && smallestFraction != 10000) //make sure we are not getting digits + this.mSmallestFraction = 100; + else + this.mSmallestFraction = smallestFraction; } public int getQuoteFlag() { diff --git a/app/src/main/java/org/gnucash/android/model/Money.java b/app/src/main/java/org/gnucash/android/model/Money.java index 20024b1c3..686bc3797 100644 --- a/app/src/main/java/org/gnucash/android/model/Money.java +++ b/app/src/main/java/org/gnucash/android/model/Money.java @@ -23,6 +23,7 @@ import com.crashlytics.android.Crashlytics; import org.gnucash.android.app.GnuCashApplication; +import org.gnucash.android.db.CommoditiesDbAdapter; import java.math.BigDecimal; import java.math.BigInteger; @@ -49,11 +50,12 @@ */ public final class Money implements Comparable{ + //// FIXME: 03.11.2015 Currency#getDefaultFractionDigits() is unreliable. Switch to Commodity /** * Currency of the account */ private Currency mCurrency; - + /** * Amount value held by this object */ @@ -135,7 +137,17 @@ public Money(BigDecimal amount, Currency currency){ this.mAmount = amount; setCurrency(currency); } - + + /** + * Creates a new money amount + * @param amount Value of the amount + * @param commodity Commodity of the money + */ + public Money(BigDecimal amount, Commodity commodity){ + this.mAmount = amount; + mCurrency = Currency.getInstance(commodity.getMnemonic()); + } + /** * Overloaded constructor. * Accepts strings as arguments and parses them to create the Money object @@ -269,7 +281,8 @@ public long getDenominator() { * @return Scale of amount as integer */ private int getScale() { - int scale = mCurrency.getDefaultFractionDigits(); + Commodity commodity = CommoditiesDbAdapter.getInstance().getCommodity(mCurrency.getCurrencyCode()); + int scale = commodity.getSmallestFractionDigits(); if (scale < 0) { scale = mAmount.scale(); } @@ -322,8 +335,9 @@ public String asString(){ */ public String formattedString(Locale locale){ NumberFormat formatter = NumberFormat.getInstance(locale); - formatter.setMinimumFractionDigits(mCurrency.getDefaultFractionDigits()); - formatter.setMaximumFractionDigits(mCurrency.getDefaultFractionDigits()); + Commodity commodity = CommoditiesDbAdapter.getInstance().getCommodity(mCurrency.getCurrencyCode()); + formatter.setMinimumFractionDigits(commodity.getSmallestFractionDigits()); + formatter.setMaximumFractionDigits(commodity.getSmallestFractionDigits()); return formatter.format(asDouble()) + " " + mCurrency.getSymbol(locale); } @@ -349,7 +363,8 @@ public Money negate(){ * @param amount {@link BigDecimal} amount to be set */ private void setAmount(BigDecimal amount) { - mAmount = amount.setScale(mCurrency.getDefaultFractionDigits(), ROUNDING_MODE); + Commodity commodity = CommoditiesDbAdapter.getInstance().getCommodity(mCurrency.getCurrencyCode()); + mAmount = amount.setScale(commodity.getSmallestFractionDigits(), ROUNDING_MODE); } /** @@ -472,20 +487,8 @@ public boolean isNegative(){ * @return String representation of the amount (without currency) of the Money object */ public String toPlainString(){ - return mAmount.setScale(mCurrency.getDefaultFractionDigits(), ROUNDING_MODE).toPlainString(); - } - - /** - * Returns the formatted amount in the default locale - *

This prints the money amount with locale formatting like the decimal separation character

- * @return Locale-formatted amount - */ - public String formattedAmount(){ - NumberFormat formatter = NumberFormat.getInstance(); - formatter.setMinimumFractionDigits(mCurrency.getDefaultFractionDigits()); - formatter.setMaximumFractionDigits(mCurrency.getDefaultFractionDigits()); - formatter.setGroupingUsed(false); - return formatter.format(asDouble()); + Commodity commodity = CommoditiesDbAdapter.getInstance().getCommodity(getCurrency().getCurrencyCode()); + return mAmount.setScale(commodity.getSmallestFractionDigits(), ROUNDING_MODE).toPlainString(); } /** diff --git a/app/src/main/java/org/gnucash/android/receivers/TransactionRecorder.java b/app/src/main/java/org/gnucash/android/receivers/TransactionRecorder.java index 3e192af09..b31475996 100644 --- a/app/src/main/java/org/gnucash/android/receivers/TransactionRecorder.java +++ b/app/src/main/java/org/gnucash/android/receivers/TransactionRecorder.java @@ -24,8 +24,10 @@ import com.crashlytics.android.Crashlytics; +import org.gnucash.android.db.CommoditiesDbAdapter; import org.gnucash.android.db.TransactionsDbAdapter; import org.gnucash.android.model.Account; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.Split; import org.gnucash.android.model.Transaction; @@ -73,7 +75,8 @@ public void onReceive(Context context, Intent intent) { if (accountUID != null) { TransactionType type = TransactionType.valueOf(args.getString(Transaction.EXTRA_TRANSACTION_TYPE)); BigDecimal amountBigDecimal = (BigDecimal) args.getSerializable(Transaction.EXTRA_AMOUNT); - amountBigDecimal = amountBigDecimal.setScale(Currency.getInstance(currencyCode).getDefaultFractionDigits(), BigDecimal.ROUND_HALF_EVEN).round(MathContext.DECIMAL128); + Commodity commodity = CommoditiesDbAdapter.getInstance().getCommodity(currencyCode); + amountBigDecimal = amountBigDecimal.setScale(commodity.getSmallestFractionDigits(), BigDecimal.ROUND_HALF_EVEN).round(MathContext.DECIMAL128); Money amount = new Money(amountBigDecimal, Currency.getInstance(currencyCode)); Split split = new Split(amount.absolute(), accountUID); split.setType(type); diff --git a/app/src/main/java/org/gnucash/android/ui/account/AccountsActivity.java b/app/src/main/java/org/gnucash/android/ui/account/AccountsActivity.java index 878eae0a7..6a1915a61 100644 --- a/app/src/main/java/org/gnucash/android/ui/account/AccountsActivity.java +++ b/app/src/main/java/org/gnucash/android/ui/account/AccountsActivity.java @@ -152,7 +152,7 @@ public class AccountsActivity extends BaseDrawerActivity implements OnAccountCli /** * Configuration for rating the app */ - public static RateThisApp.Config rateAppConfig = new RateThisApp.Config(14, 50); + public static RateThisApp.Config rateAppConfig = new RateThisApp.Config(14, 100); /** * Adapter for managing the sub-account and transaction fragment pages in the accounts view diff --git a/app/src/main/java/org/gnucash/android/ui/transaction/dialog/TransferFundsDialogFragment.java b/app/src/main/java/org/gnucash/android/ui/transaction/dialog/TransferFundsDialogFragment.java index 2a40a34f4..9166d21e3 100644 --- a/app/src/main/java/org/gnucash/android/ui/transaction/dialog/TransferFundsDialogFragment.java +++ b/app/src/main/java/org/gnucash/android/ui/transaction/dialog/TransferFundsDialogFragment.java @@ -37,6 +37,7 @@ import org.gnucash.android.R; import org.gnucash.android.db.CommoditiesDbAdapter; import org.gnucash.android.db.PricesDbAdapter; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.Price; import org.gnucash.android.ui.transaction.TransactionFormFragment; @@ -107,7 +108,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa CommoditiesDbAdapter commoditiesDbAdapter = CommoditiesDbAdapter.getInstance(); String commodityUID = commoditiesDbAdapter.getCommodityUID(fromCurrency.getCurrencyCode()); - String currencyUID = commoditiesDbAdapter.getCommodityUID(mTargetCurrency.getCurrencyCode()); + Commodity currencyCommodity = commoditiesDbAdapter.getCommodity(mTargetCurrency.getCurrencyCode()); + String currencyUID = currencyCommodity.getUID(); PricesDbAdapter pricesDbAdapter = PricesDbAdapter.getInstance(); Pair price = pricesDbAdapter.getPrice(commodityUID, currencyUID); @@ -116,7 +118,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa BigDecimal num = new BigDecimal(price.first); BigDecimal denom = new BigDecimal(price.second); mExchangeRateInput.setText(num.divide(denom, MathContext.DECIMAL32).toString()); - mConvertedAmountInput.setText(mOriginAmount.asBigDecimal().multiply(num).divide(denom, mTargetCurrency.getDefaultFractionDigits(), BigDecimal.ROUND_HALF_EVEN).toString()); + mConvertedAmountInput.setText(mOriginAmount.asBigDecimal().multiply(num).divide(denom, currencyCommodity.getSmallestFractionDigits(), BigDecimal.ROUND_HALF_EVEN).toString()); } mExchangeRateInput.addTextChangedListener(textChangeListener); diff --git a/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorEditText.java b/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorEditText.java index 9805df25c..c0ebf47eb 100644 --- a/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorEditText.java +++ b/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorEditText.java @@ -37,6 +37,8 @@ import org.gnucash.android.R; import org.gnucash.android.app.GnuCashApplication; +import org.gnucash.android.db.CommoditiesDbAdapter; +import org.gnucash.android.model.Commodity; import org.gnucash.android.ui.common.FormActivity; import java.math.BigDecimal; @@ -327,11 +329,12 @@ public BigDecimal getValue(){ * @param amount BigDecimal amount */ public void setValue(BigDecimal amount){ - BigDecimal newAmount = amount.setScale(mCurrency.getDefaultFractionDigits(), BigDecimal.ROUND_HALF_EVEN); + Commodity commodity = CommoditiesDbAdapter.getInstance().getCommodity(mCurrency.getCurrencyCode()); + BigDecimal newAmount = amount.setScale(commodity.getSmallestFractionDigits(), BigDecimal.ROUND_HALF_EVEN); DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.getDefault()); formatter.setMinimumFractionDigits(0); - formatter.setMaximumFractionDigits(mCurrency.getDefaultFractionDigits()); + formatter.setMaximumFractionDigits(commodity.getSmallestFractionDigits()); formatter.setGroupingUsed(false); String resultString = formatter.format(newAmount.doubleValue()); diff --git a/app/src/test/java/org/gnucash/android/test/unit/export/GncXmlHelperTest.java b/app/src/test/java/org/gnucash/android/test/unit/export/GncXmlHelperTest.java index 20bc2e092..0e4c811f1 100644 --- a/app/src/test/java/org/gnucash/android/test/unit/export/GncXmlHelperTest.java +++ b/app/src/test/java/org/gnucash/android/test/unit/export/GncXmlHelperTest.java @@ -1,6 +1,7 @@ package org.gnucash.android.test.unit.export; import org.gnucash.android.export.xml.GncXmlHelper; +import org.gnucash.android.model.Commodity; import org.junit.Test; import java.math.BigDecimal; @@ -34,13 +35,16 @@ public void shouldFailToParseWronglyFormattedInput() throws ParseException { @Test public void testFormatSplitAmount(){ + Commodity usdCommodity = new Commodity("US Dollars", "USD", 100); + Commodity euroCommodity = new Commodity("Euro", "EUR", 100); + BigDecimal bigDecimal = new BigDecimal("45.90"); - String amount = GncXmlHelper.formatSplitAmount(bigDecimal, Currency.getInstance("USD")); + String amount = GncXmlHelper.formatSplitAmount(bigDecimal, usdCommodity); assertThat(amount).isEqualTo("4590/100"); bigDecimal = new BigDecimal("350"); - amount = GncXmlHelper.formatSplitAmount(bigDecimal, Currency.getInstance("EUR")); + amount = GncXmlHelper.formatSplitAmount(bigDecimal, euroCommodity); assertThat(amount).isEqualTo("35000/100"); } } diff --git a/app/src/test/java/org/gnucash/android/test/unit/model/AccountTest.java b/app/src/test/java/org/gnucash/android/test/unit/model/AccountTest.java index e3b9193aa..ff14d1754 100644 --- a/app/src/test/java/org/gnucash/android/test/unit/model/AccountTest.java +++ b/app/src/test/java/org/gnucash/android/test/unit/model/AccountTest.java @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2012 - 2014 Ngewi Fet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.gnucash.android.test.unit.model; import org.gnucash.android.model.Account; diff --git a/app/src/test/java/org/gnucash/android/test/unit/model/CommodityTest.java b/app/src/test/java/org/gnucash/android/test/unit/model/CommodityTest.java new file mode 100644 index 000000000..14d82b9b5 --- /dev/null +++ b/app/src/test/java/org/gnucash/android/test/unit/model/CommodityTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015 Ngewi Fet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gnucash.android.test.unit.model; + +import org.gnucash.android.model.Commodity; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test commodities + */ +public class CommodityTest { + + @Test + public void setSmallestFraction_shouldNotUseDigits(){ + Commodity commodity = new Commodity("Test", "USD", 4); + assertThat(commodity.getSmallestFraction()).isEqualTo(100); + + commodity.setSmallestFraction(1000); + assertThat(commodity.getSmallestFraction()).isEqualTo(1000); + } + + @Test + public void testSmallestFractionDigits(){ + Commodity commodity = new Commodity("Test", "USD", 4); + assertThat(commodity.getSmallestFractionDigits()).isEqualTo(2); + + commodity.setSmallestFraction(10); + assertThat(commodity.getSmallestFractionDigits()).isEqualTo(1); + + commodity.setSmallestFraction(1); + assertThat(commodity.getSmallestFractionDigits()).isEqualTo(0); + + } +} diff --git a/app/src/test/java/org/gnucash/android/test/unit/model/MoneyTest.java b/app/src/test/java/org/gnucash/android/test/unit/model/MoneyTest.java index 2e0fbaac6..1cf406d8b 100644 --- a/app/src/test/java/org/gnucash/android/test/unit/model/MoneyTest.java +++ b/app/src/test/java/org/gnucash/android/test/unit/model/MoneyTest.java @@ -21,12 +21,21 @@ import java.util.Locale; import static org.assertj.core.api.Assertions.assertThat; + +import org.gnucash.android.BuildConfig; import org.gnucash.android.model.Money; +import org.gnucash.android.test.unit.util.GnucashTestRunner; +import org.gnucash.android.test.unit.util.ShadowCrashlytics; +import org.gnucash.android.test.unit.util.ShadowUserVoice; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; import static org.junit.Assert.*; +@RunWith(GnucashTestRunner.class) +@Config(constants = BuildConfig.class, sdk = 21, packageName = "org.gnucash.android", shadows = {ShadowCrashlytics.class, ShadowUserVoice.class}) public class MoneyTest{ private static final String CURRENCY_CODE = "EUR"; diff --git a/app/src/test/java/org/gnucash/android/test/unit/model/SplitTest.java b/app/src/test/java/org/gnucash/android/test/unit/model/SplitTest.java index 647cc15cc..c6b88efac 100644 --- a/app/src/test/java/org/gnucash/android/test/unit/model/SplitTest.java +++ b/app/src/test/java/org/gnucash/android/test/unit/model/SplitTest.java @@ -1,10 +1,16 @@ package org.gnucash.android.test.unit.model; +import org.gnucash.android.BuildConfig; import org.gnucash.android.model.Money; import org.gnucash.android.model.Split; import org.gnucash.android.model.Transaction; import org.gnucash.android.model.TransactionType; +import org.gnucash.android.test.unit.util.GnucashTestRunner; +import org.gnucash.android.test.unit.util.ShadowCrashlytics; +import org.gnucash.android.test.unit.util.ShadowUserVoice; import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; import java.math.BigDecimal; import java.util.Currency; @@ -16,6 +22,8 @@ * * @author Ngewi */ +@RunWith(GnucashTestRunner.class) +@Config(constants = BuildConfig.class, sdk = 21, packageName = "org.gnucash.android", shadows = {ShadowCrashlytics.class, ShadowUserVoice.class}) public class SplitTest { @Test From 6fb17c7423cf3ad83c77c66c75212e504dc9561e Mon Sep 17 00:00:00 2001 From: Ngewi Fet Date: Tue, 3 Nov 2015 15:36:40 +0100 Subject: [PATCH 06/17] Change Money to use Commodity instead of Currency --- .../android/test/ui/AccountsActivityTest.java | 5 +- .../android/test/ui/PieChartReportTest.java | 3 +- .../android/importer/GncXmlHandler.java | 16 +- .../org/gnucash/android/model/Account.java | 8 + .../org/gnucash/android/model/BaseModel.java | 9 +- .../org/gnucash/android/model/Commodity.java | 79 ++++++- .../java/org/gnucash/android/model/Money.java | 194 ++++++++---------- .../receivers/TransactionRecorder.java | 2 +- .../ui/transaction/SplitEditorFragment.java | 9 +- .../transaction/TransactionFormFragment.java | 7 +- .../dialog/TransferFundsDialogFragment.java | 2 +- .../test/unit/db/AccountsDbAdapterTest.java | 3 +- .../unit/db/TransactionsDbAdapterTest.java | 7 +- .../android/test/unit/model/MoneyTest.java | 18 +- .../android/test/unit/model/SplitTest.java | 7 +- 15 files changed, 216 insertions(+), 153 deletions(-) diff --git a/app/src/androidTest/java/org/gnucash/android/test/ui/AccountsActivityTest.java b/app/src/androidTest/java/org/gnucash/android/test/ui/AccountsActivityTest.java index e5723586c..ecae2fa06 100644 --- a/app/src/androidTest/java/org/gnucash/android/test/ui/AccountsActivityTest.java +++ b/app/src/androidTest/java/org/gnucash/android/test/ui/AccountsActivityTest.java @@ -40,6 +40,7 @@ import org.gnucash.android.db.TransactionsDbAdapter; import org.gnucash.android.model.Account; import org.gnucash.android.model.AccountType; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.Split; import org.gnucash.android.model.Transaction; @@ -80,7 +81,7 @@ @RunWith(AndroidJUnit4.class) public class AccountsActivityTest extends ActivityInstrumentationTestCase2 { private static final String DUMMY_ACCOUNT_CURRENCY_CODE = "USD"; - private static final Currency DUMMY_ACCOUNT_CURRENCY = Currency.getInstance(DUMMY_ACCOUNT_CURRENCY_CODE); + private static final Commodity DUMMY_ACCOUNT_CURRENCY = Commodity.getInstance(DUMMY_ACCOUNT_CURRENCY_CODE); private static final String DUMMY_ACCOUNT_NAME = "Dummy account"; public static final String DUMMY_ACCOUNT_UID = "dummy-account"; private DatabaseHelper mDbHelper; @@ -282,7 +283,7 @@ public void editingAccountShouldNotDeleteTransactions(){ .perform(click()); Account account = new Account("Transfer Account"); - account.setCurrency(DUMMY_ACCOUNT_CURRENCY); + account.setCurrency(Currency.getInstance(DUMMY_ACCOUNT_CURRENCY.getCurrencyCode())); Transaction transaction = new Transaction("Simple trxn"); transaction.setCurrencyCode(DUMMY_ACCOUNT_CURRENCY.getCurrencyCode()); Split split = new Split(new Money(BigDecimal.TEN, DUMMY_ACCOUNT_CURRENCY), account.getUID()); diff --git a/app/src/androidTest/java/org/gnucash/android/test/ui/PieChartReportTest.java b/app/src/androidTest/java/org/gnucash/android/test/ui/PieChartReportTest.java index 59ef63c4f..72ce5e0fe 100644 --- a/app/src/androidTest/java/org/gnucash/android/test/ui/PieChartReportTest.java +++ b/app/src/androidTest/java/org/gnucash/android/test/ui/PieChartReportTest.java @@ -42,6 +42,7 @@ import org.gnucash.android.importer.GncXmlImporter; import org.gnucash.android.model.Account; import org.gnucash.android.model.AccountType; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.Split; import org.gnucash.android.model.Transaction; @@ -94,7 +95,7 @@ public class PieChartReportTest extends ActivityInstrumentationTestCase2This is used when parsing splits to assign the right currencies to the splits

* @param accountUID GUID of the account - * @return Currency of the account + * @return Commodity of the account */ - private Currency getCurrencyForAccount(String accountUID){ + private Commodity getCommodityForAccount(String accountUID){ try { - return mAccountMap.get(accountUID).getCurrency(); + return mAccountMap.get(accountUID).getCommodity(); } catch (Exception e) { Crashlytics.logException(e); - return Currency.getInstance(Money.DEFAULT_CURRENCY_CODE); + return Commodity.getInstance(Money.DEFAULT_CURRENCY_CODE); } } @@ -870,7 +870,7 @@ private Currency getCurrencyForAccount(String accountUID){ private void handleEndOfTemplateNumericSlot(String characterString, TransactionType splitType) { try { BigDecimal amountBigD = GncXmlHelper.parseSplitAmount(characterString); - Money amount = new Money(amountBigD, getCurrencyForAccount(mSplit.getAccountUID())); + Money amount = new Money(amountBigD, getCommodityForAccount(mSplit.getAccountUID())); mSplit.setValue(amount.absolute()); mSplit.setType(splitType); mIgnoreTemplateTransaction = false; //we have successfully parsed an amount diff --git a/app/src/main/java/org/gnucash/android/model/Account.java b/app/src/main/java/org/gnucash/android/model/Account.java index 42ca52790..2b1025b4a 100644 --- a/app/src/main/java/org/gnucash/android/model/Account.java +++ b/app/src/main/java/org/gnucash/android/model/Account.java @@ -334,6 +334,14 @@ public Currency getCurrency() { return mCurrency; } + /** + * Return the commodity for this account + * @return + */ + public Commodity getCommodity(){ + return Commodity.getInstance(mCurrency.getCurrencyCode()); + } + /** * Sets the currency to be used by this account * @param currency the mCurrency to set diff --git a/app/src/main/java/org/gnucash/android/model/BaseModel.java b/app/src/main/java/org/gnucash/android/model/BaseModel.java index eefde82a5..cf741495d 100644 --- a/app/src/main/java/org/gnucash/android/model/BaseModel.java +++ b/app/src/main/java/org/gnucash/android/model/BaseModel.java @@ -108,6 +108,11 @@ public void setModifiedTimestamp(Timestamp modifiedTimestamp) { this.mModifiedTimestamp = modifiedTimestamp; } + /** + * Two instances are considered equal if their GUID's are the same + * @param o BaseModel instance to compare + * @return {@code true} if both instances are equal, {@code false} otherwise + */ @Override public boolean equals(Object o) { if (this == o) return true; @@ -115,12 +120,12 @@ public boolean equals(Object o) { BaseModel baseModel = (BaseModel) o; - return mUID.equals(baseModel.mUID); + return getUID().equals(baseModel.getUID()); } @Override public int hashCode() { - return mUID.hashCode(); + return getUID().hashCode(); } } diff --git a/app/src/main/java/org/gnucash/android/model/Commodity.java b/app/src/main/java/org/gnucash/android/model/Commodity.java index 154c3169b..892325126 100644 --- a/app/src/main/java/org/gnucash/android/model/Commodity.java +++ b/app/src/main/java/org/gnucash/android/model/Commodity.java @@ -15,6 +15,8 @@ */ package org.gnucash.android.model; +import org.gnucash.android.db.CommoditiesDbAdapter; + /** * Commodities are the currencies used in the application. * At the moment only ISO4217 currencies are supported @@ -23,6 +25,23 @@ public class Commodity extends BaseModel { public enum Namespace { ISO4217 } //Namespace for commodities private Namespace mNamespace = Namespace.ISO4217; +/* + public static final Commodity USD = CommoditiesDbAdapter.getInstance().getCommodity("USD"); + public static final Commodity EUR = CommoditiesDbAdapter.getInstance().getCommodity("EUR"); + public static final Commodity GBP = CommoditiesDbAdapter.getInstance().getCommodity("GBP"); + public static final Commodity CHF = CommoditiesDbAdapter.getInstance().getCommodity("CHF"); + public static final Commodity CAD = CommoditiesDbAdapter.getInstance().getCommodity("CAD"); + public static final Commodity JPY = CommoditiesDbAdapter.getInstance().getCommodity("JPY"); + public static final Commodity AUD = CommoditiesDbAdapter.getInstance().getCommodity("AUD"); +*/ + + public static final Commodity USD = new Commodity("", "USD", 100); + public static final Commodity EUR = new Commodity("", "EUR", 100); + public static final Commodity GBP = new Commodity("", "GBP", 100); + public static final Commodity CHF = new Commodity("", "CHF", 100); + public static final Commodity CAD = new Commodity("", "CAD", 100); + public static final Commodity JPY = new Commodity("", "JPY", 1); + public static final Commodity AUD = new Commodity("", "AUD", 100); /** * This is the currency code for ISO4217 currencies @@ -46,6 +65,23 @@ public Commodity(String fullname, String mnemonic, int smallestFraction){ setSmallestFraction(smallestFraction); } + /** + * Returns an instance of commodity for the specified currencyCode + * @param currencyCode ISO 4217 currency code (3-letter) + */ + public static Commodity getInstance(String currencyCode){ + switch (currencyCode){ //save time for database trip + case "USD": return USD; + case "EUR": return EUR; + case "GBP": return GBP; + case "CHF": return CHF; + case "JPY": return JPY; + case "AUD": return AUD; + case "CAD": return CAD; + default: return CommoditiesDbAdapter.getInstance().getCommodity(currencyCode); + } + } + public Namespace getNamespace() { return mNamespace; } @@ -62,6 +98,14 @@ public String getMnemonic() { return mMnemonic; } + /** + * Alias for {@link #getMnemonic()} + * @return ISO 4217 code for this commodity + */ + public String getCurrencyCode(){ + return getMnemonic(); + } + public void setMnemonic(String mMnemonic) { this.mMnemonic = mMnemonic; } @@ -114,7 +158,10 @@ public int getSmallestFraction() { /** * Returns the (minimum) number of digits that this commodity supports in its fractional part + *

For any unsupported values for the smallest fraction, a default value of 2 is returned. + * Supported values for the smallest fraction are powers of 10 i.e. 1, 10, 100 etc

* @return Number of digits in fraction + * @see #getSmallestFraction() */ public int getSmallestFractionDigits(){ switch (mSmallestFraction) { @@ -122,8 +169,12 @@ public int getSmallestFractionDigits(){ case 10: return 1; case 100: return 2; case 1000: return 3; + case 10000: return 4; + case 100000: return 5; + case 1000000: return 6; default: - throw new UnsupportedOperationException("Invalid fraction digits in commodity with fraction: " + mSmallestFraction); + return 2; + //throw new UnsupportedOperationException("Invalid fraction digits in commodity with fraction: " + mSmallestFraction); } } @@ -135,7 +186,9 @@ public int getSmallestFractionDigits(){ * @throws IllegalArgumentException if the smallest fraction is not a power of 10 */ public void setSmallestFraction(int smallestFraction) { - if (smallestFraction != 1 && smallestFraction != 10 && smallestFraction != 100 && smallestFraction != 1000 && smallestFraction != 10000) //make sure we are not getting digits + if (smallestFraction != 1 && smallestFraction != 10 && smallestFraction != 100 + && smallestFraction != 1000 && smallestFraction != 10000 + && smallestFraction != 1000000 ) //make sure we are not getting digits this.mSmallestFraction = 100; else this.mSmallestFraction = smallestFraction; @@ -148,4 +201,26 @@ public int getQuoteFlag() { public void setQuoteFlag(int quoteFlag) { this.mQuoteFlag = quoteFlag; } + + /** + * Overrides {@link BaseModel#equals(Object)} to compare only the currency codes of the commodity. + *

Two commodities are considered equal if they have the same currency code

+ * @param o Commodity instance to compare + * @return {@code true} if both instances have same currency code, {@code false} otherwise + */ + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Commodity commodity = (Commodity) o; + + return mMnemonic.equals(commodity.mMnemonic); + + } + + @Override + public int hashCode() { + return mMnemonic.hashCode(); + } } diff --git a/app/src/main/java/org/gnucash/android/model/Money.java b/app/src/main/java/org/gnucash/android/model/Money.java index 686bc3797..6e101b845 100644 --- a/app/src/main/java/org/gnucash/android/model/Money.java +++ b/app/src/main/java/org/gnucash/android/model/Money.java @@ -23,7 +23,6 @@ import com.crashlytics.android.Crashlytics; import org.gnucash.android.app.GnuCashApplication; -import org.gnucash.android.db.CommoditiesDbAdapter; import java.math.BigDecimal; import java.math.BigInteger; @@ -50,34 +49,21 @@ */ public final class Money implements Comparable{ - //// FIXME: 03.11.2015 Currency#getDefaultFractionDigits() is unreliable. Switch to Commodity /** * Currency of the account */ - private Currency mCurrency; + private Commodity mCommodity; /** * Amount value held by this object */ private BigDecimal mAmount; - - /** - * Default rounding mode for Money objects - * Defaults to {@link RoundingMode#HALF_EVEN} - */ - private static final RoundingMode DEFAULT_ROUNDING_MODE = RoundingMode.HALF_EVEN; - - /** - * Number of decimal places to limit the fractions to when performing operations - * Defaults to 2 decimal places - */ - private static final int DEFAULT_DECIMAL_PLACES = 2; - + /** * Rounding mode to be applied when performing operations - * Defaults to {@link #DEFAULT_ROUNDING_MODE} + * Defaults to {@link RoundingMode#HALF_EVEN} */ - protected RoundingMode ROUNDING_MODE = DEFAULT_ROUNDING_MODE; + protected RoundingMode ROUNDING_MODE = RoundingMode.HALF_EVEN; /** * Default currency code (according ISO 4217) @@ -99,19 +85,11 @@ public final class Money implements Comparable{ public static Money getZeroInstance(){ if (sDefaultZero == null) { String currencyCode = Currency.getInstance(GnuCashApplication.getDefaultLocale()).getCurrencyCode(); - sDefaultZero = new Money(BigDecimal.ZERO, Currency.getInstance(currencyCode)); + sDefaultZero = new Money(BigDecimal.ZERO, Commodity.getInstance(currencyCode)); } return sDefaultZero; } - /** - * Default constructor - * Initializes the object with an amount of 0 and currency set to the device default locale - */ - public Money() { - init(); - } - public static BigDecimal getBigDecimal(long numerator, long denominator) { int scale; if (numerator == 0 && denominator == 0) { @@ -128,16 +106,6 @@ public static BigDecimal getBigDecimal(long numerator, long denominator) { return new BigDecimal(BigInteger.valueOf(numerator), scale); } - /** - * Overloaded constructor - * @param amount {@link BigDecimal} value of the money instance - * @param currency {@link Currency} associated with the amount - */ - public Money(BigDecimal amount, Currency currency){ - this.mAmount = amount; - setCurrency(currency); - } - /** * Creates a new money amount * @param amount Value of the amount @@ -145,7 +113,7 @@ public Money(BigDecimal amount, Currency currency){ */ public Money(BigDecimal amount, Commodity commodity){ this.mAmount = amount; - mCurrency = Currency.getInstance(commodity.getMnemonic()); + this.mCommodity = commodity; } /** @@ -155,7 +123,7 @@ public Money(BigDecimal amount, Commodity commodity){ * @param currencyCode Currency code as specified by ISO 4217 */ public Money(String amount, String currencyCode){ - setCurrency(Currency.getInstance(currencyCode)); + mCommodity = Commodity.getInstance(currencyCode); setAmount(amount); } @@ -168,17 +136,7 @@ public Money(String amount, String currencyCode){ */ public Money(long numerator, long denominator, String currencyCode){ mAmount = getBigDecimal(numerator, denominator); - setCurrency(Currency.getInstance(currencyCode)); - } - - /** - * Overloaded constructor. - * Initializes the currency to that specified by {@link Money#DEFAULT_CURRENCY_CODE} - * @param amount Value associated with this Money object - */ - public Money(String amount){ - init(); - setAmount(parseToDecimal(amount)); + setCommodity(currencyCode); } /** @@ -187,7 +145,7 @@ public Money(String amount){ * @param money Money instance to be cloned */ public Money(Money money){ - setCurrency(money.getCurrency()); + setCommodity(money.getCommodity()); setAmount(money.asBigDecimal()); } @@ -196,46 +154,52 @@ public Money(Money money){ * @param currencyCode Currency to use for this money instance * @return Money object with value 0 and currency currencyCode */ - public static Money createZeroInstance(String currencyCode){ - return new Money(BigDecimal.ZERO, Currency.getInstance(currencyCode)); + public static Money createZeroInstance(@NonNull String currencyCode){ + Commodity commodity = Commodity.getInstance(currencyCode); + return new Money(BigDecimal.ZERO, commodity); } /** - * Initializes the amount and currency to their default values - * @see {@link Money#DEFAULT_CURRENCY_CODE}, {@link #DEFAULT_ROUNDING_MODE}, {@link #DEFAULT_DECIMAL_PLACES} + * Returns the currency of the money object + * @return {@link Currency} of the money value */ - private void init() { - mCurrency = Currency.getInstance(Money.DEFAULT_CURRENCY_CODE); - mAmount = BigDecimal.ZERO.setScale(DEFAULT_DECIMAL_PLACES, DEFAULT_ROUNDING_MODE); + public Currency getCurrency() { + return Currency.getInstance(mCommodity.getCurrencyCode()); } /** - * Returns the currency of the money object - * @return {@link Currency} of the money value + * Returns the commodity used by the Money + * @return Instance of commodity */ - public Currency getCurrency() { - return mCurrency; + public Commodity getCommodity(){ + return mCommodity; } /** * Returns a new Money object the currency specified by currency * and the same value as this one. No value exchange between the currencies is performed. - * @param currency {@link Currency} to assign to new Money object + * @param commodity {@link Commodity} to assign to new Money object * @return {@link Money} object with same value as current object, but with new currency */ - public Money withCurrency(Currency currency){ - return new Money(mAmount, currency); + public Money withCurrency(@NonNull Commodity commodity){ + return new Money(mAmount, commodity); } - + /** - * Sets the currency of the money object. - * No currency value conversion is performed. The old value for the amount is not changed - * This method is only used internally when creating the Money object. - * Money objects are immutable and hence this method should not be called out of a constructor - * @param currency {@link Currency} to assign to the Money object + * Sets the commodity for the Money + *

No currency conversion is performed

+ * @param commodity Commodity instance */ - private void setCurrency(Currency currency) { - this.mCurrency = currency; + private void setCommodity(@NonNull Commodity commodity){ + this.mCommodity = commodity; + } + + /** + * Sets the commodity for the Money + * @param currencyCode ISO 4217 currency code + */ + private void setCommodity(@NonNull String currencyCode){ + mCommodity = Commodity.getInstance(currencyCode); } /** @@ -247,7 +211,7 @@ public long getNumerator() { try { return mAmount.scaleByPowerOfTen(getScale()).longValueExact(); } catch (ArithmeticException e) { - Log.e(getClass().getName(), "Currency " + mCurrency.getCurrencyCode() + + Log.e(getClass().getName(), "Currency " + mCommodity.getCurrencyCode() + " with scale " + getScale() + " has amount " + mAmount.toString()); throw e; @@ -281,8 +245,7 @@ public long getDenominator() { * @return Scale of amount as integer */ private int getScale() { - Commodity commodity = CommoditiesDbAdapter.getInstance().getCommodity(mCurrency.getCurrencyCode()); - int scale = commodity.getSmallestFractionDigits(); + int scale = mCommodity.getSmallestFractionDigits(); if (scale < 0) { scale = mAmount.scale(); } @@ -308,16 +271,6 @@ public double asDouble(){ return mAmount.doubleValue(); } - /** - * Returns integer value of this Money amount. - * The fractional part is discarded - * @return Integer representation of this amount - * @see BigDecimal#intValue() - */ - public int intValue(){ - return mAmount.intValue(); - } - /** * An alias for {@link #toPlainString()} * @return Money formatted as a string (excludes the currency) @@ -334,11 +287,28 @@ public String asString(){ * @return String containing formatted Money representation */ public String formattedString(Locale locale){ + NumberFormat currencyFormat = NumberFormat.getCurrencyInstance(locale); + Currency currency = Currency.getInstance(mCommodity.getCurrencyCode()); + currencyFormat.setCurrency(currency); + + String symbol; + if (mCommodity.getCurrencyCode().equalsIgnoreCase("USD") && !locale.equals(Locale.US)) { + symbol = "US$"; + } else { + symbol = currency.getSymbol(Locale.US); // US locale has the best symbol formatting table. + } + DecimalFormatSymbols decimalFormatSymbols = ((DecimalFormat)currencyFormat).getDecimalFormatSymbols(); + decimalFormatSymbols.setCurrencySymbol(symbol); + ((DecimalFormat)currencyFormat).setDecimalFormatSymbols(decimalFormatSymbols); + + return currencyFormat.format(asDouble()); +/* NumberFormat formatter = NumberFormat.getInstance(locale); - Commodity commodity = CommoditiesDbAdapter.getInstance().getCommodity(mCurrency.getCurrencyCode()); - formatter.setMinimumFractionDigits(commodity.getSmallestFractionDigits()); - formatter.setMaximumFractionDigits(commodity.getSmallestFractionDigits()); - return formatter.format(asDouble()) + " " + mCurrency.getSymbol(locale); + formatter.setMinimumFractionDigits(mCommodity.getSmallestFractionDigits()); + formatter.setMaximumFractionDigits(mCommodity.getSmallestFractionDigits()); + Currency currency = Currency.getInstance(mCommodity.getCurrencyCode()); + return formatter.format(asDouble()) + " " + currency.getSymbol(locale); +*/ } /** @@ -355,16 +325,15 @@ public String formattedString(){ * @return Negated Money object */ public Money negate(){ - return new Money(mAmount.negate(), mCurrency); + return new Money(mAmount.negate(), mCommodity); } /** * Sets the amount value of this Money object * @param amount {@link BigDecimal} amount to be set */ - private void setAmount(BigDecimal amount) { - Commodity commodity = CommoditiesDbAdapter.getInstance().getCommodity(mCurrency.getCurrencyCode()); - mAmount = amount.setScale(commodity.getSmallestFractionDigits(), ROUNDING_MODE); + private void setAmount(@NonNull BigDecimal amount) { + mAmount = amount.setScale(mCommodity.getSmallestFractionDigits(), ROUNDING_MODE); } /** @@ -385,11 +354,11 @@ private void setAmount(String amount){ * @throws IllegalArgumentException if the Money objects to be added have different Currencies */ public Money add(Money addend){ - if (!mCurrency.equals(addend.mCurrency)) + if (!mCommodity.equals(addend.mCommodity)) throw new IllegalArgumentException("Only Money with same currency can be added"); BigDecimal bigD = mAmount.add(addend.mAmount); - return new Money(bigD, mCurrency); + return new Money(bigD, mCommodity); } /** @@ -401,11 +370,11 @@ public Money add(Money addend){ * @throws IllegalArgumentException if the Money objects to be added have different Currencies */ public Money subtract(Money subtrahend){ - if (!mCurrency.equals(subtrahend.mCurrency)) + if (!mCommodity.equals(subtrahend.mCommodity)) throw new IllegalArgumentException("Operation can only be performed on money with same currency"); BigDecimal bigD = mAmount.subtract(subtrahend.mAmount); - return new Money(bigD, mCurrency); + return new Money(bigD, mCommodity); } /** @@ -417,11 +386,11 @@ public Money subtract(Money subtrahend){ * @throws IllegalArgumentException if the Money objects to be added have different Currencies */ public Money divide(Money divisor){ - if (!mCurrency.equals(divisor.mCurrency)) + if (!mCommodity.equals(divisor.mCommodity)) throw new IllegalArgumentException("Operation can only be performed on money with same currency"); - BigDecimal bigD = mAmount.divide(divisor.mAmount); - return new Money(bigD, mCurrency); + BigDecimal bigD = mAmount.divide(divisor.mAmount, mCommodity.getSmallestFractionDigits(), ROUNDING_MODE); + return new Money(bigD, mCommodity); } /** @@ -431,7 +400,7 @@ public Money divide(Money divisor){ * @return Money object whose value is the quotient of this object and divisor */ public Money divide(int divisor){ - Money moneyDiv = new Money(new BigDecimal(divisor), mCurrency); + Money moneyDiv = new Money(new BigDecimal(divisor), mCommodity); return divide(moneyDiv); } @@ -444,11 +413,11 @@ public Money divide(int divisor){ * @throws IllegalArgumentException if the Money objects to be added have different Currencies */ public Money multiply(Money money){ - if (!mCurrency.equals(money.mCurrency)) + if (!mCommodity.equals(money.mCommodity)) throw new IllegalArgumentException("Operation can only be performed on money with same currency"); BigDecimal bigD = mAmount.multiply(money.mAmount); - return new Money(bigD, mCurrency); + return new Money(bigD, mCommodity); } /** @@ -459,7 +428,7 @@ public Money multiply(Money money){ * @return Money object whose value is the product of this objects values and multiplier */ public Money multiply(int multiplier){ - Money moneyFactor = new Money(new BigDecimal(multiplier), mCurrency); + Money moneyFactor = new Money(new BigDecimal(multiplier), mCommodity); return multiply(moneyFactor); } @@ -469,8 +438,8 @@ public Money multiply(int multiplier){ * @param multiplier Factor to multiply the amount by. * @return Money object whose value is the product of this objects values and multiplier */ - public Money multiply(BigDecimal multiplier){ - return new Money(mAmount.multiply(multiplier), mCurrency); + public Money multiply(@NonNull BigDecimal multiplier){ + return new Money(mAmount.multiply(multiplier), mCommodity); } /** @@ -487,8 +456,7 @@ public boolean isNegative(){ * @return String representation of the amount (without currency) of the Money object */ public String toPlainString(){ - Commodity commodity = CommoditiesDbAdapter.getInstance().getCommodity(getCurrency().getCurrencyCode()); - return mAmount.setScale(commodity.getSmallestFractionDigits(), ROUNDING_MODE).toPlainString(); + return mAmount.setScale(mCommodity.getSmallestFractionDigits(), ROUNDING_MODE).toPlainString(); } /** @@ -506,7 +474,7 @@ public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (mAmount.hashCode()); - result = prime * result + (mCurrency.hashCode()); + result = prime * result + (mCommodity.hashCode()); return result; } @@ -526,14 +494,14 @@ public boolean equals(Object obj) { Money other = (Money) obj; if (!mAmount.equals(other.mAmount)) return false; - if (!mCurrency.equals(other.mCurrency)) + if (!mCommodity.equals(other.mCommodity)) return false; return true; } @Override public int compareTo(@NonNull Money another) { - if (!mCurrency.equals(another.mCurrency)) + if (!mCommodity.equals(another.mCommodity)) throw new IllegalArgumentException("Cannot compare different currencies yet"); return mAmount.compareTo(another.mAmount); } @@ -564,7 +532,7 @@ public static BigDecimal parseToDecimal(String amountString){ * @return Money object with absolute value of this instance */ public Money absolute() { - return new Money(mAmount.abs(), mCurrency); + return new Money(mAmount.abs(), mCommodity); } /** diff --git a/app/src/main/java/org/gnucash/android/receivers/TransactionRecorder.java b/app/src/main/java/org/gnucash/android/receivers/TransactionRecorder.java index b31475996..469b0a997 100644 --- a/app/src/main/java/org/gnucash/android/receivers/TransactionRecorder.java +++ b/app/src/main/java/org/gnucash/android/receivers/TransactionRecorder.java @@ -77,7 +77,7 @@ public void onReceive(Context context, Intent intent) { BigDecimal amountBigDecimal = (BigDecimal) args.getSerializable(Transaction.EXTRA_AMOUNT); Commodity commodity = CommoditiesDbAdapter.getInstance().getCommodity(currencyCode); amountBigDecimal = amountBigDecimal.setScale(commodity.getSmallestFractionDigits(), BigDecimal.ROUND_HALF_EVEN).round(MathContext.DECIMAL128); - Money amount = new Money(amountBigDecimal, Currency.getInstance(currencyCode)); + Money amount = new Money(amountBigDecimal, Commodity.getInstance(currencyCode)); Split split = new Split(amount.absolute(), accountUID); split.setType(type); transaction.addSplit(split); 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 0d2afb910..f4500c7f0 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 @@ -44,6 +44,7 @@ import org.gnucash.android.db.DatabaseSchema; import org.gnucash.android.model.AccountType; import org.gnucash.android.model.BaseModel; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.Split; import org.gnucash.android.model.Transaction; @@ -133,8 +134,8 @@ public void onActivityCreated(Bundle savedInstanceState) { //aha! there are some splits. Let's load those instead loadSplitViews(splitList); } else { - final Currency currency = Currency.getInstance(mAccountsDbAdapter.getAccountCurrencyCode(mAccountUID)); - Split split = new Split(new Money(mBaseAmount.abs(), currency), mAccountUID); + final String currencyCode = mAccountsDbAdapter.getAccountCurrencyCode(mAccountUID); + Split split = new Split(new Money(mBaseAmount.abs(), Commodity.getInstance(currencyCode)), mAccountUID); AccountType accountType = mAccountsDbAdapter.getAccountType(mAccountUID); TransactionType transactionType = Transaction.getTypeForBalance(accountType, mBaseAmount.signum() < 0); split.setType(transactionType); @@ -354,7 +355,7 @@ private List extractSplitsFromView(){ BigDecimal amountBigDecimal = viewHolder.splitAmountEditText.getValue(); String currencyCode = mAccountsDbAdapter.getCurrencyCode(mAccountUID); - Money valueAmount = new Money(amountBigDecimal.abs(), Currency.getInstance(currencyCode)); + Money valueAmount = new Money(amountBigDecimal.abs(), Commodity.getInstance(currencyCode)); String accountUID = mAccountsDbAdapter.getUID(viewHolder.accountsSpinner.getSelectedItemId()); Split split = new Split(valueAmount, accountUID); @@ -404,7 +405,7 @@ public void onItemSelected(AdapterView parentView, View selectedItemView, int if (amountBigD == null) return; - Money amount = new Money(amountBigD, Currency.getInstance(fromCurrencyCode)); + Money amount = new Money(amountBigD, Commodity.getInstance(fromCurrencyCode)); TransferFundsDialogFragment fragment = TransferFundsDialogFragment.getInstance(amount, targetCurrencyCode, mSplitViewHolder); fragment.show(getFragmentManager(), "tranfer_funds_editor"); 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 025d305bd..77d5222b7 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 @@ -62,6 +62,7 @@ import org.gnucash.android.db.ScheduledActionDbAdapter; import org.gnucash.android.db.TransactionsDbAdapter; import org.gnucash.android.model.AccountType; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.ScheduledAction; import org.gnucash.android.model.Split; @@ -269,9 +270,9 @@ private void startTransferFunds() { return; BigDecimal amountBigd = mAmountEditText.getValue(); - if (mSplitQuantity != null || amountBigd.equals(BigDecimal.ZERO)) + if (amountBigd.equals(BigDecimal.ZERO)) return; - Money amount = new Money(amountBigd, fromCurrency).absolute(); + Money amount = new Money(amountBigd, Commodity.getInstance(fromCurrency.getCurrencyCode())).absolute(); TransferFundsDialogFragment fragment = TransferFundsDialogFragment.getInstance(amount, targetCurrency, this); @@ -724,7 +725,7 @@ private void saveNewTransaction() { BigDecimal amountBigd = mAmountEditText.getValue(); Currency currency = Currency.getInstance(mTransactionsDbAdapter.getAccountCurrencyCode(mAccountUID)); - Money amount = new Money(amountBigd, currency).absolute(); + Money amount = new Money(amountBigd, Commodity.getInstance(currency.getCurrencyCode())).absolute(); if (mSplitsList.size() == 1){ //means split editor was opened but no split was added String transferAcctUID; diff --git a/app/src/main/java/org/gnucash/android/ui/transaction/dialog/TransferFundsDialogFragment.java b/app/src/main/java/org/gnucash/android/ui/transaction/dialog/TransferFundsDialogFragment.java index 9166d21e3..20b28c6fa 100644 --- a/app/src/main/java/org/gnucash/android/ui/transaction/dialog/TransferFundsDialogFragment.java +++ b/app/src/main/java/org/gnucash/android/ui/transaction/dialog/TransferFundsDialogFragment.java @@ -205,7 +205,7 @@ private void transferFunds(){ } BigDecimal amount = TransactionFormFragment.parseInputToDecimal(convertedAmount); - mConvertedAmount = new Money(amount, mTargetCurrency); + mConvertedAmount = new Money(amount, Commodity.getInstance(mTargetCurrency.getCurrencyCode())); } if (mOnTransferFundsListener != null) { diff --git a/app/src/test/java/org/gnucash/android/test/unit/db/AccountsDbAdapterTest.java b/app/src/test/java/org/gnucash/android/test/unit/db/AccountsDbAdapterTest.java index 5baf5fb47..ba5bb7103 100644 --- a/app/src/test/java/org/gnucash/android/test/unit/db/AccountsDbAdapterTest.java +++ b/app/src/test/java/org/gnucash/android/test/unit/db/AccountsDbAdapterTest.java @@ -11,6 +11,7 @@ import org.gnucash.android.importer.GncXmlImporter; import org.gnucash.android.model.Account; import org.gnucash.android.model.AccountType; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.ScheduledAction; import org.gnucash.android.model.Split; @@ -261,7 +262,7 @@ public void shouldComputeAccountBalanceCorrectly(){ Transaction transaction = new Transaction("Test description"); mTransactionsDbAdapter.addRecord(transaction); - Split split = new Split(new Money(BigDecimal.TEN, Currency.getInstance("USD")), account.getUID()); + Split split = new Split(new Money(BigDecimal.TEN, Commodity.getInstance("USD")), account.getUID()); split.setTransactionUID(transaction.getUID()); split.setType(TransactionType.DEBIT); mSplitsDbAdapter.addRecord(split); diff --git a/app/src/test/java/org/gnucash/android/test/unit/db/TransactionsDbAdapterTest.java b/app/src/test/java/org/gnucash/android/test/unit/db/TransactionsDbAdapterTest.java index de8fefc6c..6b5432c77 100644 --- a/app/src/test/java/org/gnucash/android/test/unit/db/TransactionsDbAdapterTest.java +++ b/app/src/test/java/org/gnucash/android/test/unit/db/TransactionsDbAdapterTest.java @@ -6,6 +6,7 @@ import org.gnucash.android.db.SplitsDbAdapter; import org.gnucash.android.db.TransactionsDbAdapter; import org.gnucash.android.model.Account; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.Split; import org.gnucash.android.model.Transaction; @@ -30,7 +31,7 @@ public class TransactionsDbAdapterTest { private static final String ALPHA_ACCOUNT_NAME = "Alpha"; private static final String BRAVO_ACCOUNT_NAME = "Bravo"; - private static final Currency DEFAULT_CURRENCY = Currency.getInstance(Money.DEFAULT_CURRENCY_CODE); + private static final Commodity DEFAULT_CURRENCY = Commodity.getInstance(Money.DEFAULT_CURRENCY_CODE); private AccountsDbAdapter mAccountsDbAdapter; private TransactionsDbAdapter mTransactionsDbAdapter; @@ -65,7 +66,7 @@ public void testTransactionsAreTimeSorted(){ Transaction t2 = new Transaction( "T1000"); t2.setTime(System.currentTimeMillis()); - Split split2 = new Split(new Money("23.50"), bravoAccount.getUID()); + Split split2 = new Split(new Money("23.50", DEFAULT_CURRENCY.getCurrencyCode()), bravoAccount.getUID()); t2.addSplit(split2); t2.addSplit(split2.createPair(alphaAccount.getUID())); @@ -93,7 +94,7 @@ public void deletingTransactionsShouldDeleteSplits(){ @Test public void shouldBalanceTransactionsOnSave(){ Transaction transaction = new Transaction("Auto balance"); - Split split = new Split(new Money(BigDecimal.TEN, Currency.getInstance(Money.DEFAULT_CURRENCY_CODE)), + Split split = new Split(new Money(BigDecimal.TEN, DEFAULT_CURRENCY), alphaAccount.getUID()); transaction.addSplit(split); diff --git a/app/src/test/java/org/gnucash/android/test/unit/model/MoneyTest.java b/app/src/test/java/org/gnucash/android/test/unit/model/MoneyTest.java index 1cf406d8b..6fca5b031 100644 --- a/app/src/test/java/org/gnucash/android/test/unit/model/MoneyTest.java +++ b/app/src/test/java/org/gnucash/android/test/unit/model/MoneyTest.java @@ -23,6 +23,7 @@ import static org.assertj.core.api.Assertions.assertThat; import org.gnucash.android.BuildConfig; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.test.unit.util.GnucashTestRunner; import org.gnucash.android.test.unit.util.ShadowCrashlytics; @@ -45,7 +46,7 @@ public class MoneyTest{ @Before public void setUp() throws Exception { - mMoneyInEur = new Money(new BigDecimal(amountString), Currency.getInstance(CURRENCY_CODE)); + mMoneyInEur = new Money(new BigDecimal(amountString), Commodity.getInstance(CURRENCY_CODE)); mHashcode = mMoneyInEur.hashCode(); } @@ -54,20 +55,19 @@ public void testCreation(){ Locale.setDefault(Locale.US); String amount = "12.25"; - Money temp = new Money(amount); + Money temp = new Money(amount, CURRENCY_CODE); assertThat("12.25").isEqualTo(temp.toPlainString()); - assertThat(Money.DEFAULT_CURRENCY_CODE).isEqualTo(temp.getCurrency().getCurrencyCode()); - Currency currency = Currency.getInstance(CURRENCY_CODE); - temp = new Money(BigDecimal.TEN, currency); + Commodity commodity = Commodity.getInstance(CURRENCY_CODE); + temp = new Money(BigDecimal.TEN, commodity); assertEquals("10", temp.asBigDecimal().toPlainString()); - assertEquals(currency, temp.getCurrency()); + assertEquals(commodity, temp.getCommodity()); //test only Locale.US parsing even under different locale Locale.setDefault(Locale.GERMANY); amount = "12,25"; - temp = new Money(amount); + temp = new Money(amount, CURRENCY_CODE); assertEquals("1225.00", temp.toPlainString()); } @@ -101,7 +101,7 @@ public void testSubtractionWithDifferentCurrency(){ @Test public void testMultiplication(){ - Money result = mMoneyInEur.multiply(new Money(BigDecimal.TEN, Currency.getInstance(CURRENCY_CODE))); + Money result = mMoneyInEur.multiply(new Money(BigDecimal.TEN, Commodity.getInstance(CURRENCY_CODE))); assertThat("157.50").isEqualTo(result.toPlainString()); assertThat(result).isNotEqualTo(mMoneyInEur); validateImmutability(); @@ -146,7 +146,7 @@ public void testPrinting(){ assertEquals("15.75 " + symbolUS, mMoneyInEur.formattedString(Locale.US)); //always prints with 2 decimal places only - Money some = new Money("9.7469"); + Money some = new Money("9.7469", CURRENCY_CODE); assertEquals("9.75", some.asString()); } diff --git a/app/src/test/java/org/gnucash/android/test/unit/model/SplitTest.java b/app/src/test/java/org/gnucash/android/test/unit/model/SplitTest.java index c6b88efac..35a0af487 100644 --- a/app/src/test/java/org/gnucash/android/test/unit/model/SplitTest.java +++ b/app/src/test/java/org/gnucash/android/test/unit/model/SplitTest.java @@ -1,6 +1,7 @@ package org.gnucash.android.test.unit.model; import org.gnucash.android.BuildConfig; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.Split; import org.gnucash.android.model.Transaction; @@ -40,7 +41,7 @@ public void testAddingSplitToTransaction(){ @Test public void testCloning(){ - Split split = new Split(new Money(BigDecimal.TEN, Currency.getInstance("EUR")), "random-account"); + Split split = new Split(new Money(BigDecimal.TEN, Commodity.getInstance("EUR")), "random-account"); split.setTransactionUID("terminator-trx"); split.setType(TransactionType.CREDIT); @@ -57,7 +58,7 @@ public void testCloning(){ */ @Test public void shouldCreateInversePair(){ - Split split = new Split(new Money("2"), "dummy"); + Split split = new Split(new Money("2", "USD"), "dummy"); split.setType(TransactionType.CREDIT); split.setTransactionUID("random-trx"); Split pair = split.createPair("test"); @@ -70,7 +71,7 @@ public void shouldCreateInversePair(){ @Test public void shouldGenerateValidCsv(){ - Split split = new Split(new Money(BigDecimal.TEN, Currency.getInstance("EUR")), "random-account"); + Split split = new Split(new Money(BigDecimal.TEN, Commodity.getInstance("EUR")), "random-account"); split.setTransactionUID("terminator-trx"); split.setType(TransactionType.CREDIT); From e54c048ed64c7c6525401ad94a8892efc9d36be2 Mon Sep 17 00:00:00 2001 From: Ngewi Fet Date: Tue, 3 Nov 2015 17:33:21 +0100 Subject: [PATCH 07/17] Use Commodity instead of Currency in Accounts and Transactions --- .../android/test/ui/AccountsActivityTest.java | 6 +- .../test/ui/TransactionsActivityTest.java | 7 ++- .../android/app/GnuCashApplication.java | 12 ++++ .../gnucash/android/db/AccountsDbAdapter.java | 17 +++--- .../android/db/CommoditiesDbAdapter.java | 12 +++- .../android/db/TransactionsDbAdapter.java | 13 ++-- .../android/importer/GncXmlHandler.java | 5 +- .../org/gnucash/android/model/Account.java | 60 +++++++++---------- .../org/gnucash/android/model/Commodity.java | 31 +++++----- .../java/org/gnucash/android/model/Money.java | 13 ++-- .../gnucash/android/model/Transaction.java | 21 ++++--- .../android/receivers/AccountCreator.java | 6 +- .../ui/account/AccountFormFragment.java | 6 +- .../transaction/TransactionFormFragment.java | 4 +- .../test/unit/db/AccountsDbAdapterTest.java | 4 +- .../android/test/unit/model/AccountTest.java | 28 ++++++++- .../android/test/unit/model/MoneyTest.java | 28 +++++---- .../test/unit/model/TransactionTest.java | 13 +++- 18 files changed, 173 insertions(+), 113 deletions(-) diff --git a/app/src/androidTest/java/org/gnucash/android/test/ui/AccountsActivityTest.java b/app/src/androidTest/java/org/gnucash/android/test/ui/AccountsActivityTest.java index ecae2fa06..3d2d8f97e 100644 --- a/app/src/androidTest/java/org/gnucash/android/test/ui/AccountsActivityTest.java +++ b/app/src/androidTest/java/org/gnucash/android/test/ui/AccountsActivityTest.java @@ -116,7 +116,7 @@ public void setUp() throws Exception { Account account = new Account(DUMMY_ACCOUNT_NAME); account.setUID(DUMMY_ACCOUNT_UID); - account.setCurrency(Currency.getInstance(DUMMY_ACCOUNT_CURRENCY_CODE)); + account.setCommodity(Commodity.getInstance(DUMMY_ACCOUNT_CURRENCY_CODE)); mAccountsDbAdapter.addRecord(account); refreshAccountsList(); } @@ -202,7 +202,7 @@ public void testCreateAccount(){ @Test public void testChangeParentAccount() { final String accountName = "Euro Account"; - Account account = new Account(accountName, Currency.getInstance("EUR")); + Account account = new Account(accountName, Commodity.EUR); mAccountsDbAdapter.addRecord(account); refreshAccountsList(); @@ -283,7 +283,7 @@ public void editingAccountShouldNotDeleteTransactions(){ .perform(click()); Account account = new Account("Transfer Account"); - account.setCurrency(Currency.getInstance(DUMMY_ACCOUNT_CURRENCY.getCurrencyCode())); + account.setCommodity(Commodity.getInstance(DUMMY_ACCOUNT_CURRENCY.getCurrencyCode())); Transaction transaction = new Transaction("Simple trxn"); transaction.setCurrencyCode(DUMMY_ACCOUNT_CURRENCY.getCurrencyCode()); Split split = new Split(new Money(BigDecimal.TEN, DUMMY_ACCOUNT_CURRENCY), account.getUID()); diff --git a/app/src/androidTest/java/org/gnucash/android/test/ui/TransactionsActivityTest.java b/app/src/androidTest/java/org/gnucash/android/test/ui/TransactionsActivityTest.java index 669660cc1..7b0ef4bff 100644 --- a/app/src/androidTest/java/org/gnucash/android/test/ui/TransactionsActivityTest.java +++ b/app/src/androidTest/java/org/gnucash/android/test/ui/TransactionsActivityTest.java @@ -36,6 +36,7 @@ import org.gnucash.android.db.SplitsDbAdapter; import org.gnucash.android.db.TransactionsDbAdapter; import org.gnucash.android.model.Account; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.Split; import org.gnucash.android.model.Transaction; @@ -121,11 +122,11 @@ public void setUp() throws Exception { mTransactionTimeMillis = System.currentTimeMillis(); Account account = new Account(DUMMY_ACCOUNT_NAME); account.setUID(DUMMY_ACCOUNT_UID); - account.setCurrency(Currency.getInstance(CURRENCY_CODE)); + account.setCommodity(Commodity.getInstance(CURRENCY_CODE)); Account account2 = new Account(TRANSFER_ACCOUNT_NAME); account2.setUID(TRANSFER_ACCOUNT_UID); - account2.setCurrency(Currency.getInstance(CURRENCY_CODE)); + account2.setCommodity(Commodity.getInstance(CURRENCY_CODE)); mAccountsDbAdapter.addRecord(account); mAccountsDbAdapter.addRecord(account2); @@ -478,7 +479,7 @@ public void testDeleteTransaction(){ @Test public void testMoveTransaction(){ Account account = new Account("Move account"); - account.setCurrency(Currency.getInstance(CURRENCY_CODE)); + account.setCommodity(Commodity.getInstance(CURRENCY_CODE)); mAccountsDbAdapter.addRecord(account); assertThat(mTransactionsDbAdapter.getAllTransactionsForAccount(account.getUID())).hasSize(0); diff --git a/app/src/main/java/org/gnucash/android/app/GnuCashApplication.java b/app/src/main/java/org/gnucash/android/app/GnuCashApplication.java index cadc03f7c..bc0ae2016 100644 --- a/app/src/main/java/org/gnucash/android/app/GnuCashApplication.java +++ b/app/src/main/java/org/gnucash/android/app/GnuCashApplication.java @@ -40,6 +40,7 @@ import org.gnucash.android.db.ScheduledActionDbAdapter; import org.gnucash.android.db.SplitsDbAdapter; import org.gnucash.android.db.TransactionsDbAdapter; +import org.gnucash.android.model.Commodity; import org.gnucash.android.service.SchedulerService; import java.util.Currency; @@ -122,6 +123,8 @@ public void onCreate(){ mScheduledActionDbAdapter = new ScheduledActionDbAdapter(mDb); mCommoditiesDbAdapter = new CommoditiesDbAdapter(mDb); mPricesDbAdapter = new PricesDbAdapter(mDb); + + Commodity.DEFAULT_COMMODITY = mCommoditiesDbAdapter.getCommodity(getDefaultCurrencyCode()); } public static AccountsDbAdapter getAccountsDbAdapter() { @@ -212,6 +215,15 @@ public static String getDefaultCurrencyCode(){ return currencyCode; } + /** + * Returns the default commodity + * @return Default commodity of application + * @see #getDefaultCurrencyCode() + */ + public static Commodity getDefaultCommodity(){ + return Commodity.DEFAULT_COMMODITY; + } + /** * Returns the default locale which is used for currencies, while handling special cases for * locales which are not supported for currency such as en_GB diff --git a/app/src/main/java/org/gnucash/android/db/AccountsDbAdapter.java b/app/src/main/java/org/gnucash/android/db/AccountsDbAdapter.java index 30fc1093d..7d1acfbb1 100644 --- a/app/src/main/java/org/gnucash/android/db/AccountsDbAdapter.java +++ b/app/src/main/java/org/gnucash/android/db/AccountsDbAdapter.java @@ -32,6 +32,7 @@ import org.gnucash.android.app.GnuCashApplication; import org.gnucash.android.model.Account; import org.gnucash.android.model.AccountType; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.Split; import org.gnucash.android.model.Transaction; @@ -108,9 +109,8 @@ public void addRecord(@NonNull Account account){ if (account.getAccountType() != AccountType.ROOT){ //update the fully qualified account name updateRecord(accountUID, AccountEntry.COLUMN_FULL_NAME, getFullyQualifiedAccountName(accountUID)); - String commodityUID = getCommodityUID(account.getCurrency().getCurrencyCode()); for (Transaction t : account.getTransactions()) { - t.setCommodityUID(commodityUID); + t.setCommodity(account.getCommodity()); mTransactionsAdapter.addRecord(t); } for (Transaction transaction : templateTransactions) { @@ -184,11 +184,11 @@ protected SQLiteStatement compileReplaceStatement(@NonNull final Account account mReplaceStatement.bindLong(9, account.isPlaceholderAccount() ? 1 : 0); mReplaceStatement.bindString(10, account.getCreatedTimestamp().toString()); mReplaceStatement.bindLong(11, account.isHidden() ? 1 : 0); - String commodityUID = account.getCommodityUID(); - if (commodityUID == null) - commodityUID = CommoditiesDbAdapter.getInstance().getCommodityUID(account.getCurrency().getCurrencyCode()); + Commodity commodity = account.getCommodity(); + if (commodity == null) + commodity = CommoditiesDbAdapter.getInstance().getCommodity(account.getCurrency().getCurrencyCode()); - mReplaceStatement.bindString(12, commodityUID); + mReplaceStatement.bindString(12, commodity.getUID()); String parentAccountUID = account.getParentUID(); if (parentAccountUID == null && account.getAccountType() != AccountType.ROOT) { @@ -398,7 +398,7 @@ private Account buildSimpleAccountInstance(Cursor c) { account.setParentUID(c.getString(c.getColumnIndexOrThrow(AccountEntry.COLUMN_PARENT_ACCOUNT_UID))); account.setAccountType(AccountType.valueOf(c.getString(c.getColumnIndexOrThrow(AccountEntry.COLUMN_TYPE)))); Currency currency = Currency.getInstance(c.getString(c.getColumnIndexOrThrow(AccountEntry.COLUMN_CURRENCY))); - account.setCurrency(currency); + account.setCommodity(CommoditiesDbAdapter.getInstance().getCommodity(currency.getCurrencyCode())); account.setPlaceHolderFlag(c.getInt(c.getColumnIndexOrThrow(AccountEntry.COLUMN_PLACEHOLDER)) == 1); account.setDefaultTransferAccountUID(c.getString(c.getColumnIndexOrThrow(AccountEntry.COLUMN_DEFAULT_TRANSFER_ACCOUNT_UID))); account.setColorCode(c.getString(c.getColumnIndexOrThrow(AccountEntry.COLUMN_COLOR_CODE))); @@ -542,9 +542,10 @@ public List getExportableAccounts(){ */ public String getOrCreateImbalanceAccountUID(Currency currency){ String imbalanceAccountName = getImbalanceAccountName(currency); + Commodity commodity = CommoditiesDbAdapter.getInstance().getCommodity(currency.getCurrencyCode()); String uid = findAccountUidByFullName(imbalanceAccountName); if (uid == null){ - Account account = new Account(imbalanceAccountName, currency); + Account account = new Account(imbalanceAccountName, commodity); account.setAccountType(AccountType.BANK); account.setParentUID(getOrCreateGnuCashRootAccountUID()); account.setHidden(!GnuCashApplication.isDoubleEntryEnabled()); diff --git a/app/src/main/java/org/gnucash/android/db/CommoditiesDbAdapter.java b/app/src/main/java/org/gnucash/android/db/CommoditiesDbAdapter.java index 043a8291a..b4e6d7583 100644 --- a/app/src/main/java/org/gnucash/android/db/CommoditiesDbAdapter.java +++ b/app/src/main/java/org/gnucash/android/db/CommoditiesDbAdapter.java @@ -21,6 +21,16 @@ public class CommoditiesDbAdapter extends DatabaseAdapter { */ public CommoditiesDbAdapter(SQLiteDatabase db) { super(db, CommodityEntry.TABLE_NAME); + /** + * initialize commonly used commodities + */ + Commodity.USD = getCommodity("USD"); + Commodity.EUR = getCommodity("EUR"); + Commodity.GBP = getCommodity("GBP"); + Commodity.CHF = getCommodity("CHF"); + Commodity.CAD = getCommodity("CAD"); + Commodity.JPY = getCommodity("JPY"); + Commodity.AUD = getCommodity("AUD"); } public static CommoditiesDbAdapter getInstance(){ @@ -49,7 +59,7 @@ protected SQLiteStatement compileReplaceStatement(@NonNull final Commodity commo mReplaceStatement.bindString(5, commodity.getLocalSymbol()); mReplaceStatement.bindString(6, commodity.getCusip()); mReplaceStatement.bindLong(7, commodity.getSmallestFraction()); - mReplaceStatement.bindLong(8, commodity.getQuoteFlag()); + mReplaceStatement.bindLong(8, commodity.getQuoteFlag()); return mReplaceStatement; } diff --git a/app/src/main/java/org/gnucash/android/db/TransactionsDbAdapter.java b/app/src/main/java/org/gnucash/android/db/TransactionsDbAdapter.java index c235b75b4..b522ea7f7 100644 --- a/app/src/main/java/org/gnucash/android/db/TransactionsDbAdapter.java +++ b/app/src/main/java/org/gnucash/android/db/TransactionsDbAdapter.java @@ -32,6 +32,7 @@ import org.gnucash.android.app.GnuCashApplication; import org.gnucash.android.model.AccountType; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.Split; import org.gnucash.android.model.Transaction; @@ -180,11 +181,11 @@ protected SQLiteStatement compileReplaceStatement(@NonNull final Transaction tra mReplaceStatement.bindLong(5, transaction.isExported() ? 1 : 0); mReplaceStatement.bindString(6, transaction.getCurrencyCode()); - String commodityUID = transaction.getCommodityUID(); - if (commodityUID == null) - commodityUID = getCommodityUID(transaction.getCurrency().getCurrencyCode()); + Commodity commodity = transaction.getCommodity(); + if (commodity == null) + commodity = CommoditiesDbAdapter.getInstance().getCommodity(transaction.getCurrencyCode()); - mReplaceStatement.bindString(7, commodityUID); + mReplaceStatement.bindString(7, commodity.getUID()); mReplaceStatement.bindString(8, transaction.getCreatedTimestamp().toString()); if (transaction.getScheduledActionUID() == null) @@ -412,7 +413,9 @@ public Transaction buildModelInstance(@NonNull final Cursor c){ transaction.setNote(c.getString(c.getColumnIndexOrThrow(TransactionEntry.COLUMN_NOTES))); transaction.setExported(c.getInt(c.getColumnIndexOrThrow(TransactionEntry.COLUMN_EXPORTED)) == 1); transaction.setTemplate(c.getInt(c.getColumnIndexOrThrow(TransactionEntry.COLUMN_TEMPLATE)) == 1); - transaction.setCurrencyCode(c.getString(c.getColumnIndexOrThrow(TransactionEntry.COLUMN_CURRENCY))); + String currencyCode = c.getString(c.getColumnIndexOrThrow(TransactionEntry.COLUMN_CURRENCY)); + transaction.setCurrencyCode(currencyCode); + transaction.setCommodity(CommoditiesDbAdapter.getInstance().getCommodity(currencyCode)); transaction.setScheduledActionUID(c.getString(c.getColumnIndexOrThrow(TransactionEntry.COLUMN_SCHEDX_ACTION_UID))); long transactionID = c.getLong(c.getColumnIndexOrThrow(TransactionEntry._ID)); transaction.setSplits(mSplitsDbAdapter.getSplitsForTransaction(transactionID)); diff --git a/app/src/main/java/org/gnucash/android/importer/GncXmlHandler.java b/app/src/main/java/org/gnucash/android/importer/GncXmlHandler.java index 9e12030de..40be52aac 100644 --- a/app/src/main/java/org/gnucash/android/importer/GncXmlHandler.java +++ b/app/src/main/java/org/gnucash/android/importer/GncXmlHandler.java @@ -49,7 +49,6 @@ import java.sql.Timestamp; import java.text.ParseException; import java.util.ArrayList; -import java.util.Currency; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -372,7 +371,7 @@ public void endElement(String uri, String localName, String qualifiedName) throw case GncXmlHelper.TAG_COMMODITY_ID: String currencyCode = mISO4217Currency ? characterString : NO_CURRENCY_CODE; if (mAccount != null) { - mAccount.setCurrency(Currency.getInstance(currencyCode)); + mAccount.setCurrencyCode(currencyCode); } if (mTransaction != null) { mTransaction.setCurrencyCode(currencyCode); @@ -767,7 +766,7 @@ public void endDocument() throws SAXException { String currencyCode = split.getAccountUID(); Account imbAccount = mapImbalanceAccount.get(currencyCode); if (imbAccount == null) { - imbAccount = new Account(imbalancePrefix + currencyCode, Currency.getInstance(currencyCode)); + imbAccount = new Account(imbalancePrefix + currencyCode, Commodity.getInstance(currencyCode)); imbAccount.setParentUID(mRootAccount.getUID()); imbAccount.setAccountType(AccountType.BANK); mapImbalanceAccount.put(currencyCode, imbAccount); diff --git a/app/src/main/java/org/gnucash/android/model/Account.java b/app/src/main/java/org/gnucash/android/model/Account.java index 2b1025b4a..84dc317eb 100644 --- a/app/src/main/java/org/gnucash/android/model/Account.java +++ b/app/src/main/java/org/gnucash/android/model/Account.java @@ -93,9 +93,13 @@ public enum OfxAccountType {CHECKING, SAVINGS, MONEYMRKT, CREDITLINE } /** * Currency used by transactions in this account */ - private Currency mCurrency; + private String mCurrencyCode; + + /** + * Commodity used by this account + */ + private Commodity mCommodity; - private String mCommodityUID; /** * Type of account @@ -159,18 +163,18 @@ public enum OfxAccountType {CHECKING, SAVINGS, MONEYMRKT, CREDITLINE } public Account(String name) { setName(name); this.mFullName = mName; - this.mCurrency = Currency.getInstance(Money.DEFAULT_CURRENCY_CODE); + setCommodity(Commodity.DEFAULT_COMMODITY); } /** * Overloaded constructor * @param name Name of the account - * @param currency {@link Currency} to be used by transactions in this account + * @param commodity {@link Commodity} to be used by transactions in this account */ - public Account(String name, Currency currency){ + public Account(String name, Commodity commodity){ setName(name); this.mFullName = mName; - this.mCurrency = currency; + setCommodity(commodity); } /** @@ -244,7 +248,7 @@ public void setAccountType(AccountType mAccountType) { * @param transaction {@link Transaction} to be added to the account */ public void addTransaction(Transaction transaction){ - transaction.setCurrencyCode(mCurrency.getCurrencyCode()); + transaction.setCommodity(mCommodity); mTransactionsList.add(transaction); } @@ -281,7 +285,7 @@ public int getTransactionCount(){ * @return {@link Money} aggregate amount of all transactions in account. */ public Money getBalance(){ - Money balance = Money.createZeroInstance(mCurrency.getCurrencyCode()); + Money balance = Money.createZeroInstance(mCurrencyCode); for (Transaction transaction : mTransactionsList) { balance.add(transaction.getBalance(getUID())); } @@ -331,41 +335,33 @@ public void setFavorite(boolean isFavorite) { * @return the mCurrency */ public Currency getCurrency() { - return mCurrency; + return Currency.getInstance(mCurrencyCode); } /** - * Return the commodity for this account - * @return + * Sets the currency code of this account + * @param currencyCode ISO 4217 3-letter currency code */ - public Commodity getCommodity(){ - return Commodity.getInstance(mCurrency.getCurrencyCode()); + public void setCurrencyCode(String currencyCode){ + this.mCurrencyCode = currencyCode; } /** - * Sets the currency to be used by this account - * @param currency the mCurrency to set - */ - public void setCurrency(Currency currency) { - this.mCurrency = currency; - //TODO: Maybe at some time t, this method should convert all - //transaction values to the corresponding value in the new currency - } - - /** - * Returns the commodity GUID for this account - * @return String GUID of commodity + * Return the commodity for this account + * @return */ - public String getCommodityUID() { - return mCommodityUID; + public Commodity getCommodity(){ + return mCommodity; } /** - * Sets the commodity GUID for this account - * @param commodityUID String commodity GUID + * Sets the commodity of this account + * @param commodity Commodity of the account */ - public void setCommodityUID(String commodityUID) { - this.mCommodityUID = commodityUID; + public void setCommodity(Commodity commodity){ + this.mCommodity = commodity; + this.mCurrencyCode = commodity.getCurrencyCode(); + //todo: should we also change commodity of transactions? Transactions can have splits from different accounts } /** @@ -479,7 +475,7 @@ public static OfxAccountType convertToOfxAccountType(AccountType accountType){ */ public void toOfx(Document doc, Element parent, boolean exportAllTransactions){ Element currency = doc.createElement(OfxHelper.TAG_CURRENCY_DEF); - currency.appendChild(doc.createTextNode(mCurrency.getCurrencyCode())); + currency.appendChild(doc.createTextNode(mCommodity.getCurrencyCode())); //================= BEGIN BANK ACCOUNT INFO (BANKACCTFROM) ================================= diff --git a/app/src/main/java/org/gnucash/android/model/Commodity.java b/app/src/main/java/org/gnucash/android/model/Commodity.java index 892325126..8169f4179 100644 --- a/app/src/main/java/org/gnucash/android/model/Commodity.java +++ b/app/src/main/java/org/gnucash/android/model/Commodity.java @@ -22,26 +22,23 @@ * At the moment only ISO4217 currencies are supported */ public class Commodity extends BaseModel { + public enum Namespace { ISO4217 } //Namespace for commodities private Namespace mNamespace = Namespace.ISO4217; -/* - public static final Commodity USD = CommoditiesDbAdapter.getInstance().getCommodity("USD"); - public static final Commodity EUR = CommoditiesDbAdapter.getInstance().getCommodity("EUR"); - public static final Commodity GBP = CommoditiesDbAdapter.getInstance().getCommodity("GBP"); - public static final Commodity CHF = CommoditiesDbAdapter.getInstance().getCommodity("CHF"); - public static final Commodity CAD = CommoditiesDbAdapter.getInstance().getCommodity("CAD"); - public static final Commodity JPY = CommoditiesDbAdapter.getInstance().getCommodity("JPY"); - public static final Commodity AUD = CommoditiesDbAdapter.getInstance().getCommodity("AUD"); -*/ - - public static final Commodity USD = new Commodity("", "USD", 100); - public static final Commodity EUR = new Commodity("", "EUR", 100); - public static final Commodity GBP = new Commodity("", "GBP", 100); - public static final Commodity CHF = new Commodity("", "CHF", 100); - public static final Commodity CAD = new Commodity("", "CAD", 100); - public static final Commodity JPY = new Commodity("", "JPY", 1); - public static final Commodity AUD = new Commodity("", "AUD", 100); + + /** + * Default commodity for device locale + */ + public static Commodity DEFAULT_COMMODITY = new Commodity("US Dollars", "USD", 100); //this value is a stub. Will be overwritten when the app is launched + + public static Commodity USD = new Commodity("", "USD", 100); + public static Commodity EUR = new Commodity("", "EUR", 100); + public static Commodity GBP = new Commodity("", "GBP", 100); + public static Commodity CHF = new Commodity("", "CHF", 100); + public static Commodity CAD = new Commodity("", "CAD", 100); + public static Commodity JPY = new Commodity("", "JPY", 1); + public static Commodity AUD = new Commodity("", "AUD", 100); /** * This is the currency code for ISO4217 currencies diff --git a/app/src/main/java/org/gnucash/android/model/Money.java b/app/src/main/java/org/gnucash/android/model/Money.java index 6e101b845..312a171b5 100644 --- a/app/src/main/java/org/gnucash/android/model/Money.java +++ b/app/src/main/java/org/gnucash/android/model/Money.java @@ -287,28 +287,33 @@ public String asString(){ * @return String containing formatted Money representation */ public String formattedString(Locale locale){ +/* +//todo: enable this code for 2.1 release. Test better too NumberFormat currencyFormat = NumberFormat.getCurrencyInstance(locale); Currency currency = Currency.getInstance(mCommodity.getCurrencyCode()); - currencyFormat.setCurrency(currency); String symbol; - if (mCommodity.getCurrencyCode().equalsIgnoreCase("USD") && !locale.equals(Locale.US)) { + if (mCommodity.equals(Commodity.USD) && !locale.equals(Locale.US)) { symbol = "US$"; + } else if (mCommodity.equals(Commodity.EUR) { + symbol = currency.getSymbol(Locale.GERMANY); //euro currency is pretty unique around the world } else { symbol = currency.getSymbol(Locale.US); // US locale has the best symbol formatting table. } DecimalFormatSymbols decimalFormatSymbols = ((DecimalFormat)currencyFormat).getDecimalFormatSymbols(); decimalFormatSymbols.setCurrencySymbol(symbol); ((DecimalFormat)currencyFormat).setDecimalFormatSymbols(decimalFormatSymbols); + currencyFormat.setMinimumFractionDigits(mCommodity.getSmallestFractionDigits()); + currencyFormat.setMaximumFractionDigits(mCommodity.getSmallestFractionDigits()); return currencyFormat.format(asDouble()); -/* +*/ + NumberFormat formatter = NumberFormat.getInstance(locale); formatter.setMinimumFractionDigits(mCommodity.getSmallestFractionDigits()); formatter.setMaximumFractionDigits(mCommodity.getSmallestFractionDigits()); Currency currency = Currency.getInstance(mCommodity.getCurrencyCode()); return formatter.format(asDouble()) + " " + currency.getSymbol(locale); -*/ } /** diff --git a/app/src/main/java/org/gnucash/android/model/Transaction.java b/app/src/main/java/org/gnucash/android/model/Transaction.java index f0e2586a1..fd7528e45 100644 --- a/app/src/main/java/org/gnucash/android/model/Transaction.java +++ b/app/src/main/java/org/gnucash/android/model/Transaction.java @@ -19,9 +19,7 @@ import android.content.Intent; import org.gnucash.android.BuildConfig; -import org.gnucash.android.app.GnuCashApplication; import org.gnucash.android.db.AccountsDbAdapter; -import org.gnucash.android.db.CommoditiesDbAdapter; import org.gnucash.android.export.ofx.OfxHelper; import org.gnucash.android.model.Account.OfxAccountType; import org.w3c.dom.Document; @@ -90,7 +88,7 @@ public class Transaction extends BaseModel{ /** * GUID of commodity associated with this transaction */ - private String mCommodityUID; + private Commodity mCommodity; /** * The splits making up this transaction @@ -168,7 +166,7 @@ public Transaction(Transaction transaction, boolean generateNewUID){ * Initializes the different fields to their default values. */ private void initDefaults(){ - mCurrencyCode = Money.DEFAULT_CURRENCY_CODE; + setCommodity(Commodity.DEFAULT_COMMODITY); this.mTimestamp = System.currentTimeMillis(); } @@ -345,19 +343,20 @@ public Currency getCurrency(){ } /** - * Returns the GUID of the commodity for this transaction - * @return GUID of commodity + * Returns the commodity for this transaction + * @return Commodity of the transaction */ - public String getCommodityUID() { - return mCommodityUID; + public Commodity getCommodity() { + return mCommodity; } /** * Sets the commodity for this transaction - * @param commodityUID GUID of commodity + * @param commodity Commodity instance */ - public void setCommodityUID(String commodityUID) { - this.mCommodityUID = commodityUID; + public void setCommodity(Commodity commodity) { + this.mCommodity = commodity; + this.mCurrencyCode = commodity.getCurrencyCode(); } /** diff --git a/app/src/main/java/org/gnucash/android/receivers/AccountCreator.java b/app/src/main/java/org/gnucash/android/receivers/AccountCreator.java index 3985e8504..100ae5891 100644 --- a/app/src/main/java/org/gnucash/android/receivers/AccountCreator.java +++ b/app/src/main/java/org/gnucash/android/receivers/AccountCreator.java @@ -24,8 +24,7 @@ import org.gnucash.android.db.AccountsDbAdapter; import org.gnucash.android.model.Account; - -import java.util.Currency; +import org.gnucash.android.model.Commodity; /** * Broadcast receiver responsible for creating {@link Account}s received through intents. @@ -49,8 +48,7 @@ public void onReceive(Context context, Intent intent) { String currencyCode = args.getString(Account.EXTRA_CURRENCY_CODE); if (currencyCode != null){ - Currency currency = Currency.getInstance(currencyCode); - account.setCurrency(currency); + account.setCommodity(Commodity.getInstance(currencyCode)); } String uid = args.getString(Intent.EXTRA_UID); diff --git a/app/src/main/java/org/gnucash/android/ui/account/AccountFormFragment.java b/app/src/main/java/org/gnucash/android/ui/account/AccountFormFragment.java index c5cca688a..0108312fc 100644 --- a/app/src/main/java/org/gnucash/android/ui/account/AccountFormFragment.java +++ b/app/src/main/java/org/gnucash/android/ui/account/AccountFormFragment.java @@ -61,16 +61,15 @@ import org.gnucash.android.model.AccountType; import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; -import org.gnucash.android.ui.common.UxArgument; import org.gnucash.android.ui.colorpicker.ColorPickerDialog; import org.gnucash.android.ui.colorpicker.ColorPickerSwatch; import org.gnucash.android.ui.colorpicker.ColorSquare; +import org.gnucash.android.ui.common.UxArgument; import org.gnucash.android.util.CommoditiesCursorAdapter; import org.gnucash.android.util.QualifiedAccountNameCursorAdapter; import java.util.ArrayList; import java.util.Arrays; -import java.util.Currency; import java.util.HashMap; import java.util.List; @@ -771,8 +770,7 @@ private void saveAccount() { long commodityId = mCurrencySpinner.getSelectedItemId(); Commodity commodity = CommoditiesDbAdapter.getInstance().getRecord(commodityId); - mAccount.setCommodityUID(commodity.getUID()); - mAccount.setCurrency(Currency.getInstance(commodity.getMnemonic())); + mAccount.setCommodity(commodity); AccountType selectedAccountType = getSelectedAccountType(); mAccount.setAccountType(selectedAccountType); 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 77d5222b7..500ed18ea 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 @@ -58,6 +58,7 @@ import org.gnucash.android.R; import org.gnucash.android.db.AccountsDbAdapter; +import org.gnucash.android.db.CommoditiesDbAdapter; import org.gnucash.android.db.DatabaseSchema; import org.gnucash.android.db.ScheduledActionDbAdapter; import org.gnucash.android.db.TransactionsDbAdapter; @@ -796,7 +797,8 @@ private void saveNewTransaction() { String currencyCode = mAccountsDbAdapter.getAccountCurrencyCode(mAccountUID); mTransaction.setCurrencyCode(currencyCode); - mTransaction.setCommodityUID(mAccountsDbAdapter.getCommodityUID(currencyCode)); + Commodity commodity = CommoditiesDbAdapter.getInstance().getCommodity(currencyCode); + mTransaction.setCommodity(commodity); mTransaction.setTime(cal.getTimeInMillis()); mTransaction.setNote(notes); diff --git a/app/src/test/java/org/gnucash/android/test/unit/db/AccountsDbAdapterTest.java b/app/src/test/java/org/gnucash/android/test/unit/db/AccountsDbAdapterTest.java index ba5bb7103..6ea614e30 100644 --- a/app/src/test/java/org/gnucash/android/test/unit/db/AccountsDbAdapterTest.java +++ b/app/src/test/java/org/gnucash/android/test/unit/db/AccountsDbAdapterTest.java @@ -253,7 +253,7 @@ public void simpleAccountListShouldNotContainTransactions(){ @Test public void shouldComputeAccountBalanceCorrectly(){ - Account account = new Account("Test", Currency.getInstance("USD")); + Account account = new Account("Test", Commodity.USD); account.setAccountType(AccountType.ASSET); //debit normal account balance Account transferAcct = new Account("Transfer"); @@ -262,7 +262,7 @@ public void shouldComputeAccountBalanceCorrectly(){ Transaction transaction = new Transaction("Test description"); mTransactionsDbAdapter.addRecord(transaction); - Split split = new Split(new Money(BigDecimal.TEN, Commodity.getInstance("USD")), account.getUID()); + Split split = new Split(new Money(BigDecimal.TEN, Commodity.USD), account.getUID()); split.setTransactionUID(transaction.getUID()); split.setType(TransactionType.DEBIT); mSplitsDbAdapter.addRecord(split); diff --git a/app/src/test/java/org/gnucash/android/test/unit/model/AccountTest.java b/app/src/test/java/org/gnucash/android/test/unit/model/AccountTest.java index ff14d1754..adbbbb11e 100644 --- a/app/src/test/java/org/gnucash/android/test/unit/model/AccountTest.java +++ b/app/src/test/java/org/gnucash/android/test/unit/model/AccountTest.java @@ -15,15 +15,24 @@ */ package org.gnucash.android.test.unit.model; +import org.gnucash.android.BuildConfig; import org.gnucash.android.model.Account; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.Transaction; +import org.gnucash.android.test.unit.util.GnucashTestRunner; +import org.gnucash.android.test.unit.util.ShadowCrashlytics; +import org.gnucash.android.test.unit.util.ShadowUserVoice; import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; import java.util.Currency; import static org.assertj.core.api.Assertions.assertThat; +@RunWith(GnucashTestRunner.class) +@Config(constants = BuildConfig.class, sdk = 21, packageName = "org.gnucash.android", shadows = {ShadowCrashlytics.class, ShadowUserVoice.class}) public class AccountTest{ @Test @@ -40,7 +49,7 @@ public void testAccountAlwaysHasUID(){ @Test public void testTransactionsHaveSameCurrencyAsAccount(){ - Account acc1 = new Account("Japanese", Currency.getInstance("JPY")); + Account acc1 = new Account("Japanese", Commodity.JPY); acc1.setUID("simile"); Transaction trx = new Transaction("Underground"); Transaction term = new Transaction( "Tube"); @@ -77,4 +86,21 @@ public void settingNameShouldNotChangeFullName(){ assertThat(account.getName()).isEqualTo("Name"); assertThat(account.getFullName()).isEqualTo(fullName); } + + @Test + public void settingCommodity_shouldSetCurrencyCode(){ + Account account = new Account("Test", Commodity.USD); + account.setCommodity(Commodity.JPY); + + assertThat(account.getCurrency()).isEqualTo(Currency.getInstance("JPY")); + } + + @Test + public void settingCurrencyCode_shouldNotSetCommodity(){ + Account account = new Account("Test EUR account", Commodity.EUR); + account.setCurrencyCode("USD"); + + assertThat(account.getCommodity()).isEqualTo(Commodity.EUR); + assertThat(account.getCurrency()).isEqualTo(Currency.getInstance("USD")); + } } diff --git a/app/src/test/java/org/gnucash/android/test/unit/model/MoneyTest.java b/app/src/test/java/org/gnucash/android/test/unit/model/MoneyTest.java index 6fca5b031..1340dc208 100644 --- a/app/src/test/java/org/gnucash/android/test/unit/model/MoneyTest.java +++ b/app/src/test/java/org/gnucash/android/test/unit/model/MoneyTest.java @@ -16,12 +16,6 @@ package org.gnucash.android.test.unit.model; -import java.math.BigDecimal; -import java.util.Currency; -import java.util.Locale; - -import static org.assertj.core.api.Assertions.assertThat; - import org.gnucash.android.BuildConfig; import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; @@ -33,7 +27,13 @@ import org.junit.runner.RunWith; import org.robolectric.annotation.Config; -import static org.junit.Assert.*; +import java.math.BigDecimal; +import java.util.Currency; +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; @RunWith(GnucashTestRunner.class) @Config(constants = BuildConfig.class, sdk = 21, packageName = "org.gnucash.android", shadows = {ShadowCrashlytics.class, ShadowUserVoice.class}) @@ -138,12 +138,16 @@ public void testNegation(){ public void testPrinting(){ assertEquals(mMoneyInEur.asString(), mMoneyInEur.toPlainString()); assertEquals(amountString, mMoneyInEur.asString()); - + // the unicode for Euro symbol is \u20AC - String symbol = Currency.getInstance("EUR").getSymbol(Locale.GERMAN); - String symbolUS = Currency.getInstance("EUR").getSymbol(Locale.US); - assertEquals("15,75 " + symbol, mMoneyInEur.formattedString(Locale.GERMAN)); - assertEquals("15.75 " + symbolUS, mMoneyInEur.formattedString(Locale.US)); + + String symbol = Currency.getInstance("EUR").getSymbol(Locale.GERMANY); + String actualOuputDE = mMoneyInEur.formattedString(Locale.GERMANY); + assertThat(actualOuputDE).isEqualTo("15,75 " + symbol); + + symbol = Currency.getInstance("EUR").getSymbol(Locale.US); + String actualOuputUS = mMoneyInEur.formattedString(Locale.US); + assertThat(actualOuputUS).isEqualTo("15.75 " + symbol); //always prints with 2 decimal places only Money some = new Money("9.7469", CURRENCY_CODE); diff --git a/app/src/test/java/org/gnucash/android/test/unit/model/TransactionTest.java b/app/src/test/java/org/gnucash/android/test/unit/model/TransactionTest.java index b781c7bd3..486f17931 100644 --- a/app/src/test/java/org/gnucash/android/test/unit/model/TransactionTest.java +++ b/app/src/test/java/org/gnucash/android/test/unit/model/TransactionTest.java @@ -1,19 +1,28 @@ package org.gnucash.android.test.unit.model; +import org.gnucash.android.BuildConfig; +import org.gnucash.android.model.Commodity; import org.gnucash.android.model.Money; import org.gnucash.android.model.Split; import org.gnucash.android.model.Transaction; +import org.gnucash.android.test.unit.util.GnucashTestRunner; +import org.gnucash.android.test.unit.util.ShadowCrashlytics; +import org.gnucash.android.test.unit.util.ShadowUserVoice; import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; import static org.assertj.core.api.Assertions.assertThat; +@RunWith(GnucashTestRunner.class) +@Config(constants = BuildConfig.class, sdk = 21, packageName = "org.gnucash.android", shadows = {ShadowCrashlytics.class, ShadowUserVoice.class}) public class TransactionTest { @Test public void testCloningTransaction(){ Transaction transaction = new Transaction("Bobba Fett"); assertThat(transaction.getUID()).isNotNull(); - assertThat(transaction.getCurrencyCode()).isEqualTo(Money.DEFAULT_CURRENCY_CODE); + assertThat(transaction.getCurrencyCode()).isEqualTo(Commodity.DEFAULT_COMMODITY.getCurrencyCode()); Transaction clone1 = new Transaction(transaction, false); assertThat(transaction.getUID()).isEqualTo(clone1.getUID()); @@ -34,7 +43,7 @@ public void testCloningTransaction(){ @Test public void addingSplitsShouldSetTransactionUID(){ Transaction transaction = new Transaction(""); - assertThat(transaction.getCurrencyCode()).isEqualTo(Money.DEFAULT_CURRENCY_CODE); + assertThat(transaction.getCurrencyCode()).isEqualTo(Commodity.DEFAULT_COMMODITY.getCurrencyCode()); Split split = new Split(Money.getZeroInstance(), "test-account"); assertThat(split.getTransactionUID()).isEmpty(); From c7e7a80289064baa842d69ef188d54de95ca51c3 Mon Sep 17 00:00:00 2001 From: Ngewi Fet Date: Tue, 3 Nov 2015 18:48:56 +0100 Subject: [PATCH 08/17] Fix moving transaction to another account through split editor sets the value to zero fixes #416 --- .../test/ui/TransactionsActivityTest.java | 42 +++++++++++++++++++ .../transaction/TransactionFormFragment.java | 4 +- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/app/src/androidTest/java/org/gnucash/android/test/ui/TransactionsActivityTest.java b/app/src/androidTest/java/org/gnucash/android/test/ui/TransactionsActivityTest.java index 7b0ef4bff..6ec47912b 100644 --- a/app/src/androidTest/java/org/gnucash/android/test/ui/TransactionsActivityTest.java +++ b/app/src/androidTest/java/org/gnucash/android/test/ui/TransactionsActivityTest.java @@ -57,6 +57,7 @@ import java.util.List; import java.util.Locale; +import static android.support.test.espresso.Espresso.onData; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.action.ViewActions.clearText; import static android.support.test.espresso.action.ViewActions.click; @@ -70,6 +71,7 @@ import static android.support.test.espresso.matcher.ViewMatchers.withText; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; @@ -495,6 +497,46 @@ public void testMoveTransaction(){ } +// @Test //// FIXME: 03.11.2015 fix and re-enable this test + public void editingSplit_shouldNotSetAmountToZero(){ + setDoubleEntryEnabled(true); + mTransactionsDbAdapter.deleteAllRecords(); + + Account account = new Account("Z Account", Commodity.getInstance(CURRENCY_CODE)); + mAccountsDbAdapter.addRecord(account); + + onView(withId(R.id.fab_create_transaction)).perform(click()); + + onView(withId(R.id.input_transaction_name)).perform(typeText("Test Split")); + onView(withId(R.id.input_transaction_amount)).perform(typeText("1024")); + + onView(withId(R.id.menu_save)).perform(click()); + + onView(withText("Test Split")).perform(click()); + onView(withId(R.id.fab_edit_transaction)).perform(click()); + + onView(withId(R.id.btn_split_editor)).perform(click()); + +// onView(withSpinnerText(DUMMY_ACCOUNT_NAME)).perform(click()); //// FIXME: 03.11.2015 properly select the spinner + onData(withId(R.id.input_accounts_spinner)) + .inAdapterView(withId(R.id.split_list_layout)) + .atPosition(1) + .perform(click()); + onData(allOf(is(instanceOf(String.class)), is(account.getFullName()))).perform(click()); +// onView(withText(account.getFullName())).perform(click()); + + onView(withId(R.id.menu_save)).perform(click()); + onView(withId(R.id.menu_save)).perform(click()); + + //split should have moved from account, it should now be empty + onView(withId(R.id.empty_view)).check(matches(isDisplayed())); + + assertThat(mAccountsDbAdapter.getAccountBalance(DUMMY_ACCOUNT_UID)).isEqualTo(Money.createZeroInstance(CURRENCY_CODE)); + + //split + assertThat(mAccountsDbAdapter.getAccountBalance(account.getUID())).isEqualTo(new Money("1024", CURRENCY_CODE)); + } + @Test public void testDuplicateTransaction(){ assertThat(mTransactionsDbAdapter.getAllTransactionsForAccount(DUMMY_ACCOUNT_UID)).hasSize(1); 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 500ed18ea..dd2520453 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 @@ -740,7 +740,9 @@ private void saveNewTransaction() { } //capture any edits which were done directly (not using split editor) - if (mSplitsList.size() == 2 && mSplitsList.get(0).isPairOf(mSplitsList.get(1))) { + if (mSplitsList.size() == 2 && mSplitsList.get(0).isPairOf(mSplitsList.get(1)) + //we also check that at least one of the splits belongs to this account, otherwise the account was changed in the splits and the value would be zero + && (mSplitsList.get(0).getAccountUID().equals(mAccountUID) || mSplitsList.get(1).getAccountUID().equals(mAccountUID))) { //if it is a simple transfer where the editor was not used, then respect the button for (Split split : mSplitsList) { if (split.getAccountUID().equals(mAccountUID)){ From 22b5327cdee19c3d3f71fd4e1cb2ac3f70328af0 Mon Sep 17 00:00:00 2001 From: Ngewi Fet Date: Wed, 4 Nov 2015 10:32:05 +0100 Subject: [PATCH 09/17] Fix delete account dialog only deletes splits and not whole transaction Fix display of transaction time in list (show full dates for times greater or less than a few days) Remove prettytime dependency --- app/build.gradle | 1 - .../ui/account/DeleteAccountDialogFragment.java | 8 +------- .../ui/transaction/TransactionsListFragment.java | 14 +++++++++++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 794cb4062..689e7c528 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -173,7 +173,6 @@ dependencies { 'org.jraf:android-switch-backport:2.0.1@aar', 'com.github.PhilJay:MPAndroidChart:v2.1.3', 'joda-time:joda-time:2.7', - 'org.ocpsoft.prettytime:prettytime:3.2.7.Final', 'com.google.android.gms:play-services-drive:7.0.0', 'com.jakewharton:butterknife:7.0.1', 'com.kobakei:ratethisapp:0.0.3', diff --git a/app/src/main/java/org/gnucash/android/ui/account/DeleteAccountDialogFragment.java b/app/src/main/java/org/gnucash/android/ui/account/DeleteAccountDialogFragment.java index 0fe8c70ea..c06d02823 100644 --- a/app/src/main/java/org/gnucash/android/ui/account/DeleteAccountDialogFragment.java +++ b/app/src/main/java/org/gnucash/android/ui/account/DeleteAccountDialogFragment.java @@ -228,13 +228,7 @@ public void onClick(View v) { } if (GnuCashApplication.isDoubleEntryEnabled()){ //reassign splits to imbalance - Currency accountCurrency = Currency.getInstance(accountsDbAdapter.getCurrencyCode(mOriginAccountUID)); - String imbalanceAccountUID = accountsDbAdapter.getOrCreateImbalanceAccountUID(accountCurrency); - SplitsDbAdapter.getInstance().updateRecords( - DatabaseSchema.SplitEntry.COLUMN_ACCOUNT_UID + "=?", - new String[]{mOriginAccountUID}, - DatabaseSchema.SplitEntry.COLUMN_ACCOUNT_UID, - imbalanceAccountUID); + TransactionsDbAdapter.getInstance().deleteTransactionsForAccount(mOriginAccountUID); } //now kill them all!! diff --git a/app/src/main/java/org/gnucash/android/ui/transaction/TransactionsListFragment.java b/app/src/main/java/org/gnucash/android/ui/transaction/TransactionsListFragment.java index 8015d8325..826adec6d 100644 --- a/app/src/main/java/org/gnucash/android/ui/transaction/TransactionsListFragment.java +++ b/app/src/main/java/org/gnucash/android/ui/transaction/TransactionsListFragment.java @@ -30,6 +30,7 @@ import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.PopupMenu; import android.support.v7.widget.RecyclerView; +import android.text.format.DateUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -56,8 +57,8 @@ import org.gnucash.android.ui.util.CursorRecyclerAdapter; import org.gnucash.android.ui.util.Refreshable; import org.gnucash.android.ui.util.widget.EmptyRecyclerView; -import org.ocpsoft.prettytime.PrettyTime; +import java.text.DateFormat; import java.util.Date; import java.util.List; @@ -220,7 +221,8 @@ public Cursor loadInBackground() { public class TransactionRecyclerAdapter extends CursorRecyclerAdapter{ - private final PrettyTime prettyTime = new PrettyTime(); + DateFormat simpleDateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM); + public TransactionRecyclerAdapter(Cursor cursor) { super(cursor); } @@ -262,7 +264,13 @@ public void onBindViewHolderCursor(ViewHolder holder, Cursor cursor) { holder.transactionNote.setText(text); long dateMillis = cursor.getLong(cursor.getColumnIndexOrThrow(DatabaseSchema.TransactionEntry.COLUMN_TIMESTAMP)); - holder.transactionDate.setText(prettyTime.format(new Date(dateMillis))); + String dateText; + if (dateMillis > System.currentTimeMillis()){ + dateText = simpleDateFormat.format(new Date(dateMillis)); + } else { + dateText = DateUtils.getRelativeTimeSpanString(dateMillis).toString(); + } + holder.transactionDate.setText(dateText); final long id = holder.transactionId; holder.itemView.setOnClickListener(new View.OnClickListener() { From e6dcef81cf22e4725e7a3ffdc47f348565de65f3 Mon Sep 17 00:00:00 2001 From: Ngewi Fet Date: Wed, 4 Nov 2015 11:19:04 +0100 Subject: [PATCH 10/17] Update Crashlytics dependency Fix crash when only negative sign is in calculatorEditText Fix crash during import due to unsupported amount denominator (now support up to 6) --- app/build.gradle | 2 +- .../java/org/gnucash/android/model/Money.java | 26 +++++++++---------- .../ui/util/widget/CalculatorEditText.java | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 689e7c528..af8b22281 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -187,7 +187,7 @@ dependencies { exclude module: 'httpclient' } - compile('com.crashlytics.sdk.android:crashlytics:2.5.0@aar') { + compile('com.crashlytics.sdk.android:crashlytics:2.5.2@aar') { transitive = true; } diff --git a/app/src/main/java/org/gnucash/android/model/Money.java b/app/src/main/java/org/gnucash/android/model/Money.java index 312a171b5..a30b5675b 100644 --- a/app/src/main/java/org/gnucash/android/model/Money.java +++ b/app/src/main/java/org/gnucash/android/model/Money.java @@ -84,7 +84,7 @@ public final class Money implements Comparable{ */ public static Money getZeroInstance(){ if (sDefaultZero == null) { - String currencyCode = Currency.getInstance(GnuCashApplication.getDefaultLocale()).getCurrencyCode(); + String currencyCode = GnuCashApplication.getDefaultCurrencyCode(); sDefaultZero = new Money(BigDecimal.ZERO, Commodity.getInstance(currencyCode)); } return sDefaultZero; @@ -211,9 +211,11 @@ public long getNumerator() { try { return mAmount.scaleByPowerOfTen(getScale()).longValueExact(); } catch (ArithmeticException e) { - Log.e(getClass().getName(), "Currency " + mCommodity.getCurrencyCode() + + String msg = "Currency " + mCommodity.getCurrencyCode() + " with scale " + getScale() + - " has amount " + mAmount.toString()); + " has amount " + mAmount.toString(); + Crashlytics.log(msg); + Log.e(getClass().getName(), msg); throw e; } } @@ -225,16 +227,14 @@ public long getNumerator() { */ public long getDenominator() { switch (getScale()) { - case 0: - return 1; - case 1: - return 10; - case 2: - return 100; - case 3: - return 1000; - case 4: - return 10000; + case 0: return 1; + case 1: return 10; + case 2: return 100; + case 3: return 1000; + case 4: return 10000; + case 5: return 100000; + case 6: return 1000000; //I think GnuCash XML can have gold and silver with this denom + } throw new RuntimeException("Unsupported number of fraction digits " + getScale()); } diff --git a/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorEditText.java b/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorEditText.java index c0ebf47eb..7d153a23b 100644 --- a/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorEditText.java +++ b/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorEditText.java @@ -317,7 +317,7 @@ public boolean isInputModified(){ public BigDecimal getValue(){ evaluate(); String amountString = getCleanString(); - if (amountString.isEmpty()) + if (amountString.isEmpty() || !amountString.matches("\\d+")) //value should contain atleast one digit return null; return new BigDecimal(amountString); } From a304308869cc5945a0b925a065916b058ee97a49 Mon Sep 17 00:00:00 2001 From: Ngewi Fet Date: Wed, 4 Nov 2015 12:13:41 +0100 Subject: [PATCH 11/17] Update version for v2.0.1-beta1 release Improve reliability of UI tests --- app/build.gradle | 4 +++- .../android/test/ui/ExportTransactionsTest.java | 10 +++++++--- .../android/ui/util/widget/CalculatorEditText.java | 12 ++++++++++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index af8b22281..17ec24dc7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,7 +6,7 @@ apply plugin: 'io.fabric' def versionMajor = 2 def versionMinor = 0 def versionPatch = 1 -def versionBuild = 0 +def versionBuild = 1 def buildTime() { def df = new SimpleDateFormat("yyyyMMdd HH:mm 'UTC'") @@ -138,11 +138,13 @@ afterEvaluate { output.eachLine { def serial = it.split("\\s")[0] commandLine "$adb -s $serial shell pm grant $android.productFlavors.development.applicationId android.permission.SET_ANIMATION_SCALE".split(' ') + commandLine "$adb -s $serial shell pm grant $android.productFlavors.development.applicationId android.permission.WRITE_EXTERNAL_STORAGE".split(' ') } } task grantAnimationPermissionProduction(type: Exec, dependsOn: 'installProductionDebug'){ commandLine "$adb -e shell pm grant $android.defaultConfig.applicationId android.permission.SET_ANIMATION_SCALE".split(' ') + commandLine "$adb -e shell pm grant $android.defaultConfig.applicationId android.permission.WRITE_EXTERNAL_STORAGE".split(' ') } // When launching individual tests from Android Studio, it seems that only the assemble tasks // get called directly, not the install* versions diff --git a/app/src/androidTest/java/org/gnucash/android/test/ui/ExportTransactionsTest.java b/app/src/androidTest/java/org/gnucash/android/test/ui/ExportTransactionsTest.java index 1e56a232b..5b51bdce7 100644 --- a/app/src/androidTest/java/org/gnucash/android/test/ui/ExportTransactionsTest.java +++ b/app/src/androidTest/java/org/gnucash/android/test/ui/ExportTransactionsTest.java @@ -17,6 +17,7 @@ package org.gnucash.android.test.ui; import android.Manifest; +import android.app.AlertDialog; import android.content.pm.PackageManager; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; @@ -48,8 +49,10 @@ import org.gnucash.android.ui.account.AccountsActivity; import org.junit.After; import org.junit.Before; +import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; import java.io.File; import java.util.Currency; @@ -68,6 +71,7 @@ import static org.hamcrest.Matchers.allOf; @RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ExportTransactionsTest extends ActivityInstrumentationTestCase2 { @@ -136,7 +140,7 @@ public void testOfxExport(){ } @Test - public void shouldNotOfferXmlExportInSingleEntryMode(){ + public void whenInSingleEntry_shouldHideXmlExportOption(){ PreferenceManager.getDefaultSharedPreferences(mAcccountsActivity) .edit().putBoolean(mAcccountsActivity.getString(R.string.key_use_double_entry), false) .commit(); @@ -174,7 +178,7 @@ public void testExport(ExportFormat format){ mAcccountsActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 0x23); - onView(withId(android.R.id.button1)).perform(click()); + onView(withId(AlertDialog.BUTTON_POSITIVE)).perform(click()); } } @@ -216,7 +220,7 @@ public void testDeleteTransactionsAfterExport(){ * Does not work on Travis yet */ @Test - public void shouldCreateExportSchedule(){ + public void testShouldCreateExportSchedule(){ DrawerActions.openDrawer(R.id.drawer_layout); onView(withText(R.string.nav_menu_export)).perform(click()); diff --git a/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorEditText.java b/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorEditText.java index 7d153a23b..d58de4a4a 100644 --- a/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorEditText.java +++ b/app/src/main/java/org/gnucash/android/ui/util/widget/CalculatorEditText.java @@ -317,9 +317,17 @@ public boolean isInputModified(){ public BigDecimal getValue(){ evaluate(); String amountString = getCleanString(); - if (amountString.isEmpty() || !amountString.matches("\\d+")) //value should contain atleast one digit + if (amountString.isEmpty()) + return null; + try { //catch any exceptions in the conversion e.g. if a string with only "-" is entered + return new BigDecimal(amountString); + } catch (Exception e){ + String msg = "Error parsing amount string " + amountString + " from CalculatorEditText"; + Log.i(getClass().getSimpleName(), msg, e); + Crashlytics.log(msg); + Crashlytics.logException(e); return null; - return new BigDecimal(amountString); + } } /** From 6d625ac6f6a6673485bf037d05de40b83292a890 Mon Sep 17 00:00:00 2001 From: Yongxin Wang Date: Wed, 4 Nov 2015 21:48:08 +0800 Subject: [PATCH 12/17] fix qif export to SDCard --- .../android/export/ExportAsyncTask.java | 22 +++++++++++-------- .../android/export/qif/QifExporter.java | 10 ++++++--- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/org/gnucash/android/export/ExportAsyncTask.java b/app/src/main/java/org/gnucash/android/export/ExportAsyncTask.java index 94391f824..1f07600eb 100644 --- a/app/src/main/java/org/gnucash/android/export/ExportAsyncTask.java +++ b/app/src/main/java/org/gnucash/android/export/ExportAsyncTask.java @@ -472,15 +472,19 @@ private void shareFile(String path) { * @throws IOException if the file could not be copied */ public void copyFile(File src, File dst) throws IOException { - //TODO: Make this asynchronous at some time, t in the future. - FileChannel inChannel = new FileInputStream(src).getChannel(); - FileChannel outChannel = new FileOutputStream(dst).getChannel(); - try { - inChannel.transferTo(0, inChannel.size(), outChannel); - } finally { - if (inChannel != null) - inChannel.close(); - outChannel.close(); + //TODO: Make this asynchronous at some time, t in the future + if (mExportParams.getExportFormat() == ExportFormat.QIF) { + QifExporter.splitQIF(src, dst); + } else { + FileChannel inChannel = new FileInputStream(src).getChannel(); + FileChannel outChannel = new FileOutputStream(dst).getChannel(); + try { + inChannel.transferTo(0, inChannel.size(), outChannel); + } finally { + if (inChannel != null) + inChannel.close(); + outChannel.close(); + } } } diff --git a/app/src/main/java/org/gnucash/android/export/qif/QifExporter.java b/app/src/main/java/org/gnucash/android/export/qif/QifExporter.java index 27f362719..ac5ca01cc 100644 --- a/app/src/main/java/org/gnucash/android/export/qif/QifExporter.java +++ b/app/src/main/java/org/gnucash/android/export/qif/QifExporter.java @@ -230,11 +230,15 @@ public void generateExport(Writer writer) throws ExporterException { * @throws IOException if something went wrong while splitting the file. */ public static List splitQIF(File file) throws IOException { + return splitQIF(file, file); + } + + public static List splitQIF(File src, File dst) throws IOException { // split only at the last dot - String[] pathParts = file.getPath().split("(?=\\.[^\\.]+$)"); + String[] pathParts = dst.getPath().split("(?=\\.[^\\.]+$)"); ArrayList splitFiles = new ArrayList<>(); String line; - BufferedReader in = new BufferedReader(new FileReader(file)); + BufferedReader in = new BufferedReader(new FileReader(src)); BufferedWriter out = null; try { while ((line = in.readLine()) != null) { @@ -248,7 +252,7 @@ public static List splitQIF(File file) throws IOException { out = new BufferedWriter(new FileWriter(newFileName)); } else { if (out == null) { - throw new IllegalArgumentException(file.getPath() + " format is not correct"); + throw new IllegalArgumentException(src.getPath() + " format is not correct"); } out.append(line).append('\n'); } From 2246cf176b6a5efa7da8118ca10eecc1a6d452b6 Mon Sep 17 00:00:00 2001 From: Ngewi Fet Date: Wed, 4 Nov 2015 16:12:47 +0100 Subject: [PATCH 13/17] Update version for v2.0.1-beta2 release --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 17ec24dc7..1cd91f875 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,7 +6,7 @@ apply plugin: 'io.fabric' def versionMajor = 2 def versionMinor = 0 def versionPatch = 1 -def versionBuild = 1 +def versionBuild = 2 def buildTime() { def df = new SimpleDateFormat("yyyyMMdd HH:mm 'UTC'") From 7bced89ccebcf88af6db32e3598bd6d2755c8758 Mon Sep 17 00:00:00 2001 From: Ngewi Fet Date: Wed, 4 Nov 2015 17:08:32 +0100 Subject: [PATCH 14/17] Remove Fabric API key from manifest --- app/src/main/AndroidManifest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 692c236fc..b35c4450d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -158,7 +158,6 @@ - \ No newline at end of file From ffdae9d9366951e6a1dd240e60b4650aefd9b78b Mon Sep 17 00:00:00 2001 From: Ngewi Fet Date: Thu, 5 Nov 2015 09:11:11 +0100 Subject: [PATCH 15/17] Update translations fixes #418 --- app/src/main/res/values-da-rDK/strings.xml | 539 +++++++++++---------- app/src/main/res/values-it-rIT/strings.xml | 14 +- app/src/main/res/values-ja-rJP/strings.xml | 8 +- app/src/main/res/values-pt-rBR/strings.xml | 6 +- app/src/main/res/values-pt-rPT/strings.xml | 14 +- app/src/main/res/values-zh-rCN/strings.xml | 2 +- 6 files changed, 296 insertions(+), 287 deletions(-) diff --git a/app/src/main/res/values-da-rDK/strings.xml b/app/src/main/res/values-da-rDK/strings.xml index 4a8c1c1b0..7cea47001 100644 --- a/app/src/main/res/values-da-rDK/strings.xml +++ b/app/src/main/res/values-da-rDK/strings.xml @@ -1,5 +1,4 @@ - + - Opprett konto - Rediger konto - Informasjon - Eksport OFX - Legg til ny kontotransaksjon - Ingen kontoer å vise - Kontonavn - Avbryt - Lagre - Skriv passkode - Feil passkode, prøv igjen - Passkode satt + Create Account + Edit Account + Info + Export… + Add a new transaction to an account + No accounts to display + Account name + Cancel + Save + Enter Passcode + Wrong passcode, please try again + Passcode set Please confirm your passcode - Ugyldig passkode ved verifisering. Prøv igjen. - Beskrivelse - Beløp - Ny transaksjon - Ingen transaksjoner å vise - DATO & TID - Konto - DEBET - KREDIT - Kontoer - Transaksjoner - SLETT - Slett - Avbryt - Konto slettet - Bekreft sletting - Alle transaksjoner tilhørende denne kontoen vil også bli slettet - Rediger transaksjon - Notat - FLYTT - %1$d valgt - Saldo: + Invalid passcode confirmation. Please try again + Description + Amount + New transaction + No transactions to display + DATE & TIME + Account + DEBIT + CREDIT + Accounts + Transactions + Delete + Delete + Cancel + Account deleted + Confirm delete + All transactions in this account will also be deleted + Edit Transaction + Add note + MOVE + %1$d selected + Balance: Export To: - Eksporter transaksjoner - Eksporter alle transaksjoner - Vanligvis vil kun nye transaksjoner bli eksportert. Merk dette valget for å eksportere alle transaksjonene - Feil ved eksportering av %1$s-data - Eksporter - Slett etter eksportering - Alle eksporterte transaksjoner vil bli slettet etter eksportering - Innstillinger + Export Transactions + Export all transactions + By default, only new transactions since last export will be exported. Check this option to export all transactions + Error exporting %1$s file + Export + Delete after export + All exported transactions will be deleted when exporting is completed + Settings - SD-kort + SD Card DropBox Google Drive - Delt fil… + Send to… - Flytt - Flytt %1$d transaksjoner - Til konto - Tilgang til minnekort - Kan ikke flytte transaksjonen(e).\nMottakerkonto har en annen valuta - Generelt - Om - Velg standardvaluta - Standardvaluta - Standardvaluta for nye kontoer - Aktiverer innspilling av transaksjoner i Gnucash for Android - Aktiverer oppretting av konti i Gnucash for Android - Dine GnuCash-data - Lese og endre Gnucash-data + Move + Move %1$d transaction(s) + Destination Account + Access SD Card + Cannot move transactions.\nThe destination account uses a different currency from origin account + General + About + Choose default currency + Default currency + Default currency to assign to new accounts + Enables recording transactions in GnuCash for Android + Enables creation of accounts in GnuCash for Android + Your GnuCash data + Read and modify GnuCash data Record transactions in GnuCash Create accounts in GnuCash - Vis konto - Opprette kontoer - Velg kontoer som skal opprettes + Display account + Create Accounts + Select accounts to create Afghani Algerian Dinar @@ -126,7 +126,7 @@ Cuban Peso Czech Koruna Dalasi - Danske kroner + Danish Krone Denar Djibouti Franc Dobra @@ -193,7 +193,7 @@ New Zealand Dollar Ngultrum North Korean Won - Norske kroner + Norwegian Krone Nuevo Sol Ouguiya Pa’anga @@ -202,7 +202,7 @@ Pataca Philippine Peso Platinum - Engelske pund + Pound Sterling Pula Qatari Rial Quetzal @@ -229,14 +229,14 @@ Sucre Sudanese Pound Surinam Dollar - Svenske kroner + Swedish Krona Swiss Franc Syrian Pound Taka Tala Tanzanian Shilling Tenge - Uten valuta + No currency Trinidad and Tobago Dollar Tugrik Tunisian Dinar @@ -248,8 +248,8 @@ Unidad de Valor Real Unidades de fomento Uruguay Peso en Unidades Indexadas (URUIURUI) - Uruguayan Peso - Amerikanske dollar + Uruguayan peso + US Dollar Uzbekistan Sum Vatu WIR Euro @@ -262,51 +262,51 @@ Zimbabwe Dollar Zloty - Ingen kontoer funnet.\nOpprett en konto før du legger til en modul - Byggversion - Lisens - Apache Lisens v2.0. Klikk for detaljer. - Generelt - Velg konto - Ingen transaksjoner å eksportere - Passkode - Passkode preferanser - Passkode på - Passkode av - Bytt Passkode - Om Gnucash + No accounts exist in GnuCash.\nCreate an account before adding a widget + Build version + License + Apache License v2.0. Click for details + General Preferences + Select Account + There are no transactions available to export + Passcode + Passcode Preferences + Passcode Turned On + Passcode Turned Off + Change Passcode + About GnuCash A mobile finance management and expense-tracker designed for Android - Om - %1$s-fil eksportert til:\n - Gnucash Android %1$s-eksportering - Gnucash Android-eksportering til - Transaksjoner - Transaksjonsinnstillinger - Kontoinnstillinger - Standard transaksjonstype - Transaksjonstypen som skal brukes som standard, KREDIT eller DEBET + About + %1$s file exported to:\n + GnuCash Android %1$s export + GnuCash Android Export from + Transactions + Transaction Preferences + Account Preferences + Default Transaction Type + The type of transaction to use by default, CREDIT or DEBIT - KREDIT - DEBET + CREDIT + DEBIT - Er du sikker at du vil slette ALLE transaksjonene? - Er du sikker at du vil slette denne transaksjonen? - Eksport - Eksportere alle transaksjoner - Slette eksporterte transaksjoner - E-post for eksportering - E-post for eksport. Du kan endre denne ved eksportering. - Overføringskonto - Alle transaksjoner vil bli overført til en annen konto - Aktiver dobbel bokføring - Balanse - Navngi kontoen for å opprette den - Valuta - Hovedkonto - Bruk XML OFX header - Velg denne hvis du skal eksportere til annen programvare enn GnuCash for PC. - Hva er nytt - + Are you sure you want to delete ALL transactions? + Are you sure you want to delete this transaction? + Export + Export all transactions + Delete exported transactions + Default export email + The default email address to send exports to. You can still change this when you export. + Transfer Account + All transactions will be a transfer from one account to another + Activate Double Entry + Balance + Enter an account name to create an account + Currency + Parent account + Use XML OFX header + Enable this option when exporting to third-party application other than GnuCash for desktop + What\'s New + - New Material app design \n - Multi-currency transactions\n - Calculator to transaction amounts\n @@ -314,59 +314,62 @@ - New help & feedback section\n - Multiple bug fixes and improvements\n - Ferdig - Oppgi et beløp for å lagre transaksjonen - Flervaluta transaksjoner kan ikke endres - Importere GnuCash Kontoer - Importere Kontoer - En feil oppstod ved importering fra GnuCash - GnuCash kontoer importert - Importere kontostruktur eksportert fra GnuCash (PC) - Importere GnuCash kontoer - Slette alle kontoer i databasen. Alle transaksjoner vil også bli slettet. + Dismiss + Enter an amount to save the transaction + Multi-currency transactions cannot be modified + Import GnuCash Accounts + Import Accounts + An error occurred while importing the GnuCash accounts + GnuCash Accounts successfully imported + Import account structure exported from GnuCash desktop + Import GnuCash XML + Delete all accounts in the database. All transactions will be deleted as + well. - Slette alle kontoer - Kontoer - Alle kontoer ble slettet. - Er du sikkert at du vil slette alle transaksjoner og kontoer? \nDenne operasjonen kan ikke bli omgjort! + Delete all accounts + Accounts + All accounts have been successfully deleted + Are you sure you want to delete all accounts and transactions?\n\nThis + operation cannot be undone! - Konto Type - Alle transaksjoner i alle kontoer vil bli slettet! - Slette alle transaksjoner - Alle transaksjoner slettet! - Importerer kontoer - Trykk igjen for å bekrefte. ALLE oppføringer vil bli slettet!! - Transaksjoner - Underkontoer - Søk - Standard eksportformat - Standard filformat ved eksport av transaksjoner - Eksportere transaksjoner… - Planlagte - Ubalanse - Eksporter transaksjoner - Ingen planlagte transaksjoner å vise. - Slettet alle planlagte transaksjoner - Plassholder konto - Standard overføringskonto + Account Type + All transactions in all accounts will be deleted! + Delete all transactions + All transactions successfully deleted! + Importing accounts + Tap again to confirm. ALL entries will be deleted!! + Transactions + Sub-Accounts + Search + Default Export Format + File format to use by default when exporting transactions + Export transactions… + Recurrence + + Imbalance + Exporting transactions + No recurring transactions to display. + Successfully deleted recurring transaction + Placeholder account + Default Transfer Account - %d under-konto - %d under-kontoer + %d sub-account + %d sub-accounts - KONTANTER + CASH BANK - KREDITTKORT - EIENDEL - GJELD - INNTEKT - UTGIFT - LEVERANDØRGJELD - FORDRING - EGENKAPITAL - VALUTA - AKSJE - AKSJEFOND + CREDIT CARD + ASSET + LIABILITY + INCOME + EXPENSE + PAYABLE + RECEIVABLE + EQUITY + CURRENCY + STOCK + MUTUAL FUND TRADING @@ -374,135 +377,141 @@ OFX XML - Velg en farge - Konto Farge & Type - Slett underkontoer - Nylige - Favoritter - Alle - Oppretter standard GnuCash kontostruktur - Opprette standard kontoer + + Select a Color + + Color %1$d + + Color %1$d selected + Account Color & Type + Delete sub-accounts + Recent + Favorites + All + Creates default GnuCash commonly-used account structure + Create default accounts All existing accounts and transactions on the device will be deleted.\n\nAre you sure you want to proceed? - Planlagte Transaksjoner - Velkommen til GnuCash Android! \nDu kan enten opprette et hieraki av de mest brukte kontoene, eller importere din egen GnuCash kontostruktur. \n\nBegge valgene er også tilgjengelige under Instillinger, så du kan velge senere. + Scheduled Transactions + Welcome to GnuCash Android! \nYou can either create + a hierarchy of commonly-used accounts, or import your own GnuCash account structure. \n\nBoth options are also + available in app Settings so you can decide later. - Planlagte Transaksjoner + Transactions Select destination for export - Notat - Forbruk - Motta - Uttak - Innskudd - Betaling - Belast - Reduser - Øk - Inntekt - Rabatt - Utgift - Regning - Faktura - Kjøp - Salg - Gjentas - Ingen nylig sikkerhetskopi funnet - Inngående balanse - Egenkapital - Merk for å lagre gjeldende konto balanse (før sletting) som ny inngående balanse (etter sletting av transaksjoner). - Lagre inngående balanser - OFX støtter ikke dobbel bokføring - Oppretter separate QIF filer for hver valuta - Transaksjonssplitt - Ubalance: - Legg til splitt - Favoritt - Navigasjonsskuff åpnet - Navigasjonsskuff lukket - Rapporter - Kakediagram - Linjediagram - Søylediagram - Innstillinger for rapporter - Velg valuta - Kontofarge i rapportene - Bruk kontofarge i kakediagrammet - Rapporter - Sorter etter størrelse + Memo + Spend + Receive + Withdrawal + Deposit + Payment + Charge + Decrease + Increase + Income + Rebate + Expense + Bill + Invoice + Buy + Sell + Repeats + No recent backup found + Opening Balances + Equity + Enable to save the current account balance (before deleting transactions) as new opening balance after deleting transactions + + Save account opening balances + OFX does not support double-entry transactions + Generates separate QIF files per currency + Transaction splits + Imbalance: + Add split + Favorite + Navigation drawer opened + Navigation drawer closed + Reports + Pie Chart + Line Chart + Bar Chart + Report Preferences + Select currency + Account color in reports + Use account color in the bar/pie chart + Reports + Order by size Show legend Show labels Show percentage Show average lines - Grupper små stykker - Ingen diagramdata er tilgjengelige - Generell + Group Smaller Slices + No chart data available + Overall Total - Andre - Prosent av valgt verdi kalkulert ut ifra totalen - Prosent av valgt verdi kalkulert ut ifra gjeldene søyle - Lagre som mal - Denne kontoen inneholder transaksjoner. \nHva vil du gjøre med disse - Denne kontoen inneholder underkontoer. \nHva vil du gjøre med disse - Slett tranaksjoner - Opprett og spesifiser en overføringskonto ELLER skru av dobbel bokføring under innstillinger for å lagre transaksjonene - Trykk for å opprette tidsplan - Tilbakefør sikkerhetskopi - Sikkerhetskopier & eksport - DropBox Synk - Sikkerhetskopi - Skru på synkronisering til DropBox - Velg GnuCash XML fil - Innstillinger for sikkerhetskopi - Lag sikkerhetskopi - Standard blir sikkerhetskopier lagret til SD minnekort - Velg en sikkerhetskopi for tilbakeføring - Sikkerhetskopiering ferdig - Feil ved sikkerhetskopiering - Eksporteret alle kontoer og transaksjoner + Other + The percentage of selected value calculated from the total amount + The percentage of selected value calculated from the current stacked bar amount + Save as template + This account contains transactions. \nWhat would you like to do with these transactions + This account contains sub-accounts. \nWhat would you like to do with these sub-accounts + Delete transactions + Create and specify a transfer account OR disable double-entry in settings to save the transaction + Tap to create schedule + Restore Backup… + Backup & export + DropBox Sync + Backup + Enable to sync to DropBox + Select GnuCash XML file + Backup Preferences + Create Backup + By default backups are saved to the SDCARD + Select a specific backup to restore + Backup successful + Backup failed + Exports all accounts and transactions Google Drive Sync - Skru på synk til Google Disk - Installer en filbehandler for å velge filer - Velg sikkerhetskopi som skal tilbakeføres - Favoritter - Åpne... - Rapporter - Planlagte transaksjoner - Eksporter... - Instillinger + Enable to sync to Google Drive + Install a file manager to select files + Select backup to restore + Favorites + Open… + Reports + Scheduled Transactions + Export… + Settings - Daglig - Hver %d dag + Daily + Every %d days - Ukentlig - Hver %d uke + Weekly + Every %d weeks - Månedlig - Hver %d måned + Monthly + Every %d months - Årlig - Hvert %d år + Yearly + Every %d years - Skru på feillogging - Skru på feilrapportering til utviklerene for utbedring (anbefalt). -Ingen brukerinformasjon vil bli delt i denne prosessen! - - Format - Mappe for sikkerhetskopier ikke funnet. Sjekk at SD kortet er montert! + Enable Crash Logging + Automatically send information about app malfunction to the developers. + Format + Backup folder cannot be found. Make sure the SD Card is mounted! Enter your old passcode Enter your new passcode - Planlagte sikkerhetskopier - Planlagte eksporteringer - Ingen å vise - Opprett exporteringsplan - Eksportert til: %1$s + Scheduled Exports + Exports + No scheduled exports to display + Create export schedule + Exported to: %1$s The legend is too long Account description No recent accounts No favorite accounts Scheduled Actions - "Ended, last executed on " + "Ended, last executed on %1$s" Select a bar to view details Next Done @@ -513,7 +522,7 @@ Ingen brukerinformasjon vil bli delt i denne prosessen! Create default accounts Import my accounts Let me handle it - Other... + Other… Automatically send crash reports Disable crash reports Back @@ -565,6 +574,6 @@ Ingen brukerinformasjon vil bli delt i denne prosessen! Last 6 months Last 12 months All time - Custom range… + Custom range…
diff --git a/app/src/main/res/values-it-rIT/strings.xml b/app/src/main/res/values-it-rIT/strings.xml index d6df017c2..93f5e8086 100644 --- a/app/src/main/res/values-it-rIT/strings.xml +++ b/app/src/main/res/values-it-rIT/strings.xml @@ -25,11 +25,11 @@ Nome conto Annulla Salva - Enter Passcode - Wrong passcode, please try again + Inserire codice di accesso + Codice di accesso errato, ritentare Passcode set - Please confirm your passcode - Invalid passcode confirmation. Please try again + Conferma del codice di accesso + Conferma del codice di accesso errata. Ritentare Descrizione Importo Nuova transazione @@ -51,7 +51,7 @@ SPOSTA %1$d selezionate Somma totale: - Export To: + Esporta in: Esporta transazioni Esporta tutte le transazioni Di default, verranno esportate solo le transazioni dall\'ultima esportazione. Selezionare questa opzione per esportare tutte le transazioni @@ -316,7 +316,7 @@ Chiudi Inserire un importo per salvare la transazione - Multi-currency transactions cannot be modified + Non è possibile modificare le transazioni multi-valuta Importa conti di GnuCash Importa conti Si è verificato un errore nell\'importare i conti di GnuCash @@ -383,7 +383,7 @@ Tutti Crea la struttura predefinita dei conti comuni di GnuCash Crea conti predefiniti - All existing accounts and transactions on the device will be deleted.\n\nAre you sure you want to proceed? + Tutti i conti e le transazioni nel dispositivo verranno cancellate.\n\nContinuare? Transazioni pianificate Benvenuti in GnuCash per Android! \nÈ possibile creare una struttura dei conti più comunemente utilizzati o importare la propria struttura da GnuCash. \n\nEntrambe le diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index 462514032..f57b1ddae 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -16,10 +16,10 @@ limitations under the License. --> - Create Account - Edit Account - Info - Export… + 勘定を作成 + 勘定の編集 + 情報 + エクスポート… Add a new transaction to an account No accounts to display Account name diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index e4462c438..b65554aea 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -554,9 +554,9 @@ Neste processo não serão recolhidas informações do utilizador! Traduzir GnuCash Compartilhe ideias, discuta alterações ou reporte problemas Traduza ou corrija as traduções no Crowdln - No compatible apps to receive the exported transactions! - Move... - Duplicate + Não existem apps compatíveis para receber as transações exportadas! + Mover... + Duplicar Mês atual Last 3 meses diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 41a4bd963..8a053eaf4 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -303,7 +303,7 @@ Introduza o nome da conta a criar Moeda Conta progenitora - -use um cabeçalho XML OFX + Use um cabeçalho XML OFX Active esta opção quando fizer exportações para outras aplicações que não seja o GnuCash para Desktop O que há de novo @@ -340,10 +340,10 @@ Formato de Exportação padrão Formato de ficheiro usado por defeito quando é feita uma exportação de transações Exportar transações - Recorrente + Agendadas Desequilíbrio Exportando transações - Não existem transações recorrentes para mostrar + Não existem transações agendadas para mostrar. Transações recorrentes apagadas com sucesso Conta não editável Conta para transferências padrão @@ -527,7 +527,7 @@ Neste processo não serão recolhidas informações do utilizador! Transferências Escolha uma secção para ver os detalhes - Perडodo: + Período: De: Para: Forneça o montante convertido ou a taxa de câmbio para a transferência @@ -554,9 +554,9 @@ Neste processo não serão recolhidas informações do utilizador! Traduza o GnuCash Partilhe ideias, discuta alterações ou reporte problemas Traduza ou reveja em Crowdin - No compatible apps to receive the exported transactions! - Move... - Duplicate + Não existem aplicações compatíveis para receber as transações exportadas! + Mover... + Duplicar Mês actual Últimos 3 meses diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 61b7b55ec..f5010cc0e 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -19,7 +19,7 @@ 创建科目 修改科目 信息 - 导出OFX + 导出... 为科目增加交易 没有要显示的科目 科目名称 From 68ed2709e387c8e518cbd9160f3fa720cf409832 Mon Sep 17 00:00:00 2001 From: Ngewi Fet Date: Thu, 5 Nov 2015 09:52:02 +0100 Subject: [PATCH 16/17] Fix broken Travis CI build Generate a fabric.properties for crashlytics if one doesn't exist --- app/build.gradle | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 1cd91f875..11902153d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -127,9 +127,26 @@ android { } } +/** + * Create the Crashlytics properties file when building on CI + * @return + */ +def initCrashlyticsPropertiesIfNeeded() { + def propertiesFile = file('fabric.properties') + if (!propertiesFile.exists()) { + def commentMessage = "This is autogenerated crashlytics property from system environment to prevent key to be committed to source control." + ant.propertyfile(file: "fabric.properties", comment: commentMessage) { //the keys added here are invalid, just placeholders to make builds pass + entry(key: "apiSecret", value: "bd4e83a9a4c35fbf1fbe8d9ccce9443eebb9d5835605f9d06767850e0f1e5b22") + entry(key: "apiKey", value: "46fe045d00d4ad8a71014c53567be3368e10bd64") + } + } +} + def adb = android.getAdbExe().toString() afterEvaluate { + initCrashlyticsPropertiesIfNeeded() + task grantAnimationPermissionDevel(type: Exec, dependsOn: 'installDevelopmentDebug') { // or install{productFlavour}{buildType} commandLine "$adb", 'devices' standardOutput = new ByteArrayOutputStream() From c593851370e03e00b8a84667cec0ba69266a02b2 Mon Sep 17 00:00:00 2001 From: Ngewi Fet Date: Thu, 5 Nov 2015 10:11:11 +0100 Subject: [PATCH 17/17] Update version for v2.0.1 release Improve time display in transaction list Update CHANGELOG --- CHANGELOG.md | 8 ++++++++ app/build.gradle | 2 +- .../android/ui/transaction/TransactionsListFragment.java | 7 +------ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9874ab9f0..a5ff4a675 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ Change Log =============================================================================== +Version 2.0.1 *(2015-11-05)* +---------------------------- +* Feature: Menu options for moving/duplicating transactions +* Fixed: Invalid QIF exported, causing crashes when importing on desktop +* Fixed: Account delete dialog not displaying properly / only partially deleting transactions +* Fixed: Moving transaction to another account from within the split editor sets the amount to zero +* Improved: Amounts now use standard commodities & fraction digit on all devices + Version 2.0.0 *(2015-11-01)* ---------------------------- * Feature: Updated app design to use Material Design guidelines diff --git a/app/build.gradle b/app/build.gradle index 11902153d..402207ba2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,7 +6,7 @@ apply plugin: 'io.fabric' def versionMajor = 2 def versionMinor = 0 def versionPatch = 1 -def versionBuild = 2 +def versionBuild = 3 def buildTime() { def df = new SimpleDateFormat("yyyyMMdd HH:mm 'UTC'") diff --git a/app/src/main/java/org/gnucash/android/ui/transaction/TransactionsListFragment.java b/app/src/main/java/org/gnucash/android/ui/transaction/TransactionsListFragment.java index 826adec6d..e59155ea3 100644 --- a/app/src/main/java/org/gnucash/android/ui/transaction/TransactionsListFragment.java +++ b/app/src/main/java/org/gnucash/android/ui/transaction/TransactionsListFragment.java @@ -264,12 +264,7 @@ public void onBindViewHolderCursor(ViewHolder holder, Cursor cursor) { holder.transactionNote.setText(text); long dateMillis = cursor.getLong(cursor.getColumnIndexOrThrow(DatabaseSchema.TransactionEntry.COLUMN_TIMESTAMP)); - String dateText; - if (dateMillis > System.currentTimeMillis()){ - dateText = simpleDateFormat.format(new Date(dateMillis)); - } else { - dateText = DateUtils.getRelativeTimeSpanString(dateMillis).toString(); - } + String dateText = DateUtils.getRelativeTimeSpanString(dateMillis, System.currentTimeMillis(), DateUtils.DAY_IN_MILLIS).toString(); holder.transactionDate.setText(dateText); final long id = holder.transactionId;