]> git.ktnx.net Git - mobile-ledger.git/blobdiff - app/src/main/java/net/ktnx/mobileledger/async/RetrieveTransactionsTask.java
HTML transaction parser: handle posting status flags
[mobile-ledger.git] / app / src / main / java / net / ktnx / mobileledger / async / RetrieveTransactionsTask.java
index 465977b32e2c97e16235b49ffffaf2c55cbed201..6afe539b2ba242ac5e405e5a2624bb3dc530e678 100644 (file)
@@ -22,13 +22,15 @@ import android.database.sqlite.SQLiteDatabase;
 import android.os.AsyncTask;
 import android.os.OperationCanceledException;
 
+import androidx.annotation.NonNull;
+
 import net.ktnx.mobileledger.App;
 import net.ktnx.mobileledger.err.HTTPException;
-import net.ktnx.mobileledger.json.AccountListParser;
-import net.ktnx.mobileledger.json.ParsedBalance;
-import net.ktnx.mobileledger.json.ParsedLedgerAccount;
-import net.ktnx.mobileledger.json.ParsedLedgerTransaction;
-import net.ktnx.mobileledger.json.TransactionListParser;
+import net.ktnx.mobileledger.json.v1_15.AccountListParser;
+import net.ktnx.mobileledger.json.v1_15.ParsedBalance;
+import net.ktnx.mobileledger.json.v1_15.ParsedLedgerAccount;
+import net.ktnx.mobileledger.json.v1_15.ParsedLedgerTransaction;
+import net.ktnx.mobileledger.json.v1_15.TransactionListParser;
 import net.ktnx.mobileledger.model.Data;
 import net.ktnx.mobileledger.model.LedgerAccount;
 import net.ktnx.mobileledger.model.LedgerTransaction;
@@ -66,8 +68,10 @@ public class RetrieveTransactionsTask
     private static final Pattern reTransactionDescription =
             Pattern.compile("<tr class=\"posting\" title=\"(\\S+)\\s(.+)");
     private static final Pattern reTransactionDetails =
-            Pattern.compile("^\\s+(\\S[\\S\\s]+\\S)\\s\\s+([-+]?\\d[\\d,.]*)(?:\\s+(\\S+)$)?");
+            Pattern.compile("^\\s+([!*]\\s+)?(\\S[\\S\\s]+\\S)\\s\\s+([-+]?\\d[\\d,.]*)(?:\\s+(\\S+)$)?");
     private static final Pattern reEnd = Pattern.compile("\\bid=\"addmodal\"");
+    private static final Pattern reDecimalPoint = Pattern.compile("\\.\\d\\d?$");
+    private static final Pattern reDecimalComma = Pattern.compile(",\\d\\d?$");
     private WeakReference<MainActivity> contextRef;
     // %3A is '='
     private Pattern reAccountName = Pattern.compile("/register\\?q=inacct%3A([a-zA-Z0-9%]+)\"");
@@ -75,7 +79,7 @@ public class RetrieveTransactionsTask
             "<span class=\"[^\"]*\\bamount\\b[^\"]*\">\\s*([-+]?[\\d.,]+)(?:\\s+(\\S+))?</span>");
     private MobileLedgerProfile profile;
     public RetrieveTransactionsTask(WeakReference<MainActivity> contextRef,
-                                    MobileLedgerProfile profile) {
+                                    @NonNull MobileLedgerProfile profile) {
         this.contextRef = contextRef;
         this.profile = profile;
     }
@@ -118,7 +122,6 @@ public class RetrieveTransactionsTask
         HashMap<String, Void> accountNames = new HashMap<>();
         HashMap<String, LedgerAccount> syntheticAccounts = new HashMap<>();
         LedgerAccount lastAccount = null, prevAccount = null;
-        boolean onlyStarred = Data.optShowOnlyStarred.get();
 
         HttpURLConnection http = NetworkUtil.prepareConnection(profile, "journal");
         http.setAllowUserInteraction(false);
@@ -214,8 +217,8 @@ public class RetrieveTransactionsTask
                                         }
                                         acc.setHasSubAccounts(true);
                                         acc.removeAmounts();    // filled below when amounts are parsed
-                                        if ((!onlyStarred || !acc.isHiddenByStar()) &&
-                                            acc.isVisible(accountList)) accountList.add(acc);
+                                        if (acc.isVisible(accountList))
+                                            accountList.add(acc);
                                         L(String.format("gap-filling with %s", aName));
                                         accountNames.put(aName, null);
                                         profile.storeAccount(db, acc);
@@ -223,8 +226,7 @@ public class RetrieveTransactionsTask
                                     }
                                 }
 
-                                if ((!onlyStarred || !lastAccount.isHiddenByStar()) &&
-                                    lastAccount.isVisible(accountList))
+                                if (lastAccount.isVisible(accountList))
                                     accountList.add(lastAccount);
                                 accountNames.put(acct_name, null);
 
@@ -243,18 +245,34 @@ public class RetrieveTransactionsTask
                                 String value = m.group(1);
                                 String currency = m.group(2);
                                 if (currency == null) currency = "";
-                                value = value.replace(',', '.');
+
+                                {
+                                    Matcher tmpM = reDecimalComma.matcher(value);
+                                    if (tmpM.find()) {
+                                        value = value.replace(".", "");
+                                        value = value.replace(',', '.');
+                                    }
+
+                                    tmpM = reDecimalPoint.matcher(value);
+                                    if (tmpM.find()) {
+                                        value = value.replace(",", "");
+                                        value = value.replace(" ", "");
+                                    }
+                                }
                                 L("curr=" + currency + ", value=" + value);
                                 final float val = Float.parseFloat(value);
                                 profile.storeAccountValue(db, lastAccount.getName(), currency, val);
                                 lastAccount.addAmount(val, currency);
                                 for (LedgerAccount syn : syntheticAccounts.values()) {
+                                    L(String.format(Locale.ENGLISH, "propagating %s %1.2f to %s",
+                                            currency, val, syn.getName()));
                                     syn.addAmount(val, currency);
                                     profile.storeAccountValue(db, syn.getName(), currency, val);
                                 }
                             }
 
                             if (match_found) {
+                                syntheticAccounts.clear();
                                 state = ParserState.EXPECTING_ACCOUNT;
                                 L("→ expecting account");
                             }
@@ -347,13 +365,14 @@ public class RetrieveTransactionsTask
                             else {
                                 m = reTransactionDetails.matcher(line);
                                 if (m.find()) {
-                                    String acc_name = m.group(1);
-                                    String amount = m.group(2);
-                                    String currency = m.group(3);
+                                    String postingStatus = m.group(1);
+                                    String acc_name = m.group(2);
+                                    String amount = m.group(3);
+                                    String currency = m.group(4);
                                     if (currency == null) currency = "";
                                     amount = amount.replace(',', '.');
                                     transaction.addAccount(new LedgerTransactionAccount(acc_name,
-                                            Float.valueOf(amount), currency));
+                                            Float.valueOf(amount), currency, null));
                                     L(String.format(Locale.ENGLISH, "%d: %s = %s",
                                             transaction.getId(), acc_name, amount));
                                 }
@@ -389,8 +408,7 @@ public class RetrieveTransactionsTask
                 new String[]{profile.getUuid()});
         db.execSQL("update accounts set keep=0 where profile=?;", new String[]{profile.getUuid()});
     }
-    private boolean retrieveAccountList()
-            throws IOException, HTTPException {
+    private boolean retrieveAccountList() throws IOException, HTTPException {
         Progress progress = new Progress();
 
         HttpURLConnection http = NetworkUtil.prepareConnection(profile, "accounts");
@@ -477,8 +495,7 @@ public class RetrieveTransactionsTask
 
         return true;
     }
-    private boolean retrieveTransactionList()
-            throws IOException, ParseException, HTTPException {
+    private boolean retrieveTransactionList() throws IOException, ParseException, HTTPException {
         Progress progress = new Progress();
         int maxTransactionId = Progress.INDETERMINATE;