X-Git-Url: https://git.ktnx.net/?a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fnet%2Fktnx%2Fmobileledger%2Fasync%2FRetrieveTransactionsTask.java;h=0bf763a981656a3812941186d797d67474ddc6b1;hb=983c6b875b4b3336b1c70bdf363e39b1ca5657ea;hp=57a2739f70e066997907f6f1ed1935602b601540;hpb=025fe22c621f5977742198becce9cc4b9d9a018c;p=mobile-ledger.git diff --git a/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java b/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java index 57a2739f..0bf763a9 100644 --- a/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java +++ b/app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java @@ -57,7 +57,7 @@ import java.util.regex.Pattern; public class RetrieveTransactionsTask extends AsyncTask { - private static final int MATCHING_TRANSACTIONS_LIMIT = 50; + private static final int MATCHING_TRANSACTIONS_LIMIT = 150; private static final Pattern reComment = Pattern.compile("^\\s*;"); private static final Pattern reTransactionStart = Pattern.compile("([\\d.-]+)"); @@ -112,6 +112,7 @@ public class RetrieveTransactionsTask int maxTransactionId = Progress.INDETERMINATE; ArrayList accountList = new ArrayList<>(); HashMap accountNames = new HashMap<>(); + HashMap syntheticAccounts = new HashMap<>(); LedgerAccount lastAccount = null, prevAccount = null; boolean onlyStarred = Data.optShowOnlyStarred.get(); @@ -186,6 +187,9 @@ public class RetrieveTransactionsTask .setHasSubAccounts(prevAccount.isParentOf(lastAccount)); // make sure the parent account(s) are present, // synthesising them if necessary + // this happens when the (missing-in-HTML) parent account has + // only one child so we create a synthetic parent account record, + // copying the amounts when child's amounts are parsed String parentName = lastAccount.getParentName(); if (parentName != null) { Stack toAppend = new Stack<>(); @@ -195,16 +199,24 @@ public class RetrieveTransactionsTask parentName = new LedgerAccount(parentName).getParentName(); } + syntheticAccounts.clear(); while (!toAppend.isEmpty()) { String aName = toAppend.pop(); - LedgerAccount acc = new LedgerAccount(aName); - acc.setHiddenByStar(lastAccount.isHiddenByStar()); + LedgerAccount acc = profile.tryLoadAccount(db, aName); + if (acc == null) { + acc = new LedgerAccount(aName); + acc.setHiddenByStar(lastAccount.isHiddenByStar()); + acc.setExpanded(!lastAccount.hasSubAccounts() || + lastAccount.isExpanded()); + } acc.setHasSubAccounts(true); + acc.removeAmounts(); // filled below when amounts are parsed if ((!onlyStarred || !acc.isHiddenByStar()) && acc.isVisible(accountList)) accountList.add(acc); L(String.format("gap-filling with %s", aName)); accountNames.put(aName, null); profile.storeAccount(db, acc); + syntheticAccounts.put(aName, acc); } } @@ -230,9 +242,14 @@ public class RetrieveTransactionsTask if (currency == null) currency = ""; value = value.replace(',', '.'); L("curr=" + currency + ", value=" + value); + final float val = Float.parseFloat(value); profile.storeAccountValue(db, lastAccount.getName(), currency, - Float.valueOf(value)); - lastAccount.addAmount(Float.parseFloat(value), currency); + val); + lastAccount.addAmount(val, currency); + for (LedgerAccount syn : syntheticAccounts.values()) { + syn.addAmount(val, currency); + profile.storeAccountValue(db, syn.getName(), currency, val); + } } if (match_found) { @@ -492,17 +509,43 @@ public class RetrieveTransactionsTask int processedTransactionCount = 0; + DetectedTransactionOrder transactionOrder = DetectedTransactionOrder.UNKNOWN; + int orderAccumulator = 0; + int lastTransactionId = 0; + while (true) { throwIfCancelled(); ParsedLedgerTransaction parsedTransaction = parser.nextTransaction(); throwIfCancelled(); if (parsedTransaction == null) break; + LedgerTransaction transaction = parsedTransaction.asLedgerTransaction(); + if (transaction.getId() > lastTransactionId) orderAccumulator++; + else orderAccumulator--; + lastTransactionId = transaction.getId(); + if (transactionOrder == DetectedTransactionOrder.UNKNOWN) { + if (orderAccumulator > 30) { + transactionOrder = DetectedTransactionOrder.FILE; + Log.d("rtt", String.format( + "Detected native file order after %d transactions (factor %d)", + processedTransactionCount, orderAccumulator)); + progress.setTotal(Data.transactions.size()); + } + else if (orderAccumulator < -30) { + transactionOrder = DetectedTransactionOrder.REVERSE_CHRONOLOGICAL; + Log.d("rtt", String.format( + "Detected reverse chronological order after %d transactions (factor %d)", + processedTransactionCount, orderAccumulator)); + } + } + if (transaction.existsInDb(db)) { profile.markTransactionAsPresent(db, transaction); matchedTransactionsCount++; - if (matchedTransactionsCount == MATCHING_TRANSACTIONS_LIMIT) { + if ((transactionOrder == DetectedTransactionOrder.REVERSE_CHRONOLOGICAL) && + (matchedTransactionsCount == MATCHING_TRANSACTIONS_LIMIT)) + { profile.markTransactionsBeforeTransactionAsPresent(db, transaction); progress.setTotal(progress.getProgress()); publishProgress(progress); @@ -517,8 +560,10 @@ public class RetrieveTransactionsTask progress.setTotal(maxTransactionId); } - if ((progress.getTotal() == Progress.INDETERMINATE) || - (progress.getTotal() < transaction.getId())) + + if ((transactionOrder != DetectedTransactionOrder.UNKNOWN) && + ((progress.getTotal() == Progress.INDETERMINATE) || + (progress.getTotal() < transaction.getId()))) progress.setTotal(transaction.getId()); progress.setProgress(++processedTransactionCount); @@ -538,6 +583,7 @@ public class RetrieveTransactionsTask return true; } + @SuppressLint("DefaultLocale") @Override protected String doInBackground(Void... params) { @@ -578,6 +624,7 @@ public class RetrieveTransactionsTask private void throwIfCancelled() { if (isCancelled()) throw new OperationCanceledException(null); } + enum DetectedTransactionOrder {UNKNOWN, REVERSE_CHRONOLOGICAL, FILE} private enum ParserState { EXPECTING_ACCOUNT, EXPECTING_ACCOUNT_AMOUNT, EXPECTING_JOURNAL, EXPECTING_TRANSACTION,