- /*
- A transaction is submittable if:
- 0) has description
- 1) has at least two account names
- 2) each amount has account name
- 3) amounts must balance to 0, or
- 3a) there must be exactly one empty amount (with account)
- 4) empty accounts with empty amounts are ignored
- 5) a row with an empty account name or empty amount is guaranteed to exist
- */
- @SuppressLint("DefaultLocale")
- public void checkTransactionSubmittable(NewTransactionItemsAdapter adapter) {
- int accounts = 0;
- int amounts = 0;
- int empty_rows = 0;
- float balance = 0f;
- final String descriptionText = getDescription();
- boolean submittable = true;
- List<Item> itemsWithEmptyAmount = new ArrayList<>();
- List<Item> itemsWithAccountAndEmptyAmount = new ArrayList<>();
-
- try {
- if ((descriptionText == null) || descriptionText.trim()
- .isEmpty())
- {
- Logger.debug("submittable", "Transaction not submittable: missing description");
- submittable = false;
- }
-
- for (int i = 0; i < this.items.size(); i++) {
- Item item = this.items.get(i);
-
- LedgerTransactionAccount acc = item.getAccount();
- String acc_name = acc.getAccountName()
- .trim();
- if (acc_name.isEmpty()) {
- empty_rows++;
-
- if (acc.isAmountSet()) {
- // 2) each amount has account name
- Logger.debug("submittable", String.format(
- "Transaction not submittable: row %d has no account name, but has" +
- " amount %1.2f", i + 1, acc.getAmount()));
- submittable = false;
- }
- }
- else {
- accounts++;
- }
-
- if (acc.isAmountSet()) {
- amounts++;
- balance += acc.getAmount();
- }
- else {
- itemsWithEmptyAmount.add(item);
-
- if (!acc_name.isEmpty()) {
- itemsWithAccountAndEmptyAmount.add(item);
- }
- }
- }
-
- // 1) has at least two account names
- if (accounts < 2) {
- Logger.debug("submittable",
- String.format("Transaction not submittable: only %d account names",
- accounts));
- submittable = false;
- }
-
- // 3) amount must balance to 0, or
- // 3a) there must be exactly one empty amount (with account)
- if (Misc.isZero(balance)) {
- for (Item item : items) {
- item.setAmountHint(null);
- }
- }
- else {
- int balanceReceiversCount = itemsWithAccountAndEmptyAmount.size();
- if (balanceReceiversCount != 1) {
- Logger.debug("submittable", (balanceReceiversCount == 0) ?
- "Transaction not submittable: non-zero balance " +
- "with no empty amounts with accounts" :
- "Transaction not submittable: non-zero balance " +
- "with multiple empty amounts with accounts");
- submittable = false;
- }
-
- // suggest off-balance amount to a row and remove hints on other rows
- Item receiver = null;
- if (!itemsWithAccountAndEmptyAmount.isEmpty())
- receiver = itemsWithAccountAndEmptyAmount.get(0);
- else if (!itemsWithEmptyAmount.isEmpty())
- receiver = itemsWithEmptyAmount.get(0);
-
- for (Item item : items) {
- if (item.equals(receiver)) {
- Logger.debug("submittable",
- String.format("Setting amount hint to %1.2f", -balance));
- item.setAmountHint(String.format("%1.2f", -balance));
- }
- else
- item.setAmountHint(null);
- }
- }
-
- // 5) a row with an empty account name or empty amount is guaranteed to exist
- if ((empty_rows == 0) &&
- ((this.items.size() == accounts) || (this.items.size() == amounts)))
- {
- adapter.addRow();
- }
-
-
- debug("submittable", submittable ? "YES" : "NO");
- isSubmittable.setValue(submittable);
-
- if (BuildConfig.DEBUG) {
- debug("submittable", "== Dump of all items");
- for (int i = 0; i < items.size(); i++) {
- Item item = items.get(i);
- LedgerTransactionAccount acc = item.getAccount();
- debug("submittable", String.format("Item %2d: [%4.2f] %s", i,
- acc.isAmountSet() ? acc.getAmount() : 0, acc.getAccountName()));
- }
- }
- }
- catch (NumberFormatException e) {
- debug("submittable", "NO (because of NumberFormatException)");
- isSubmittable.setValue(false);
- }
- catch (Exception e) {
- e.printStackTrace();
- debug("submittable", "NO (because of an Exception)");
- isSubmittable.setValue(false);