gnucash unstable: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Fri Oct 27 15:16:47 EDT 2017


Updated	 via  https://github.com/Gnucash/gnucash/commit/5157d8b5 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/a9fab360 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/dfa25e8c (commit)
	 via  https://github.com/Gnucash/gnucash/commit/cdb67763 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/3475a894 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/885272a1 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/d077400b (commit)
	 via  https://github.com/Gnucash/gnucash/commit/b74c0bed (commit)
	 via  https://github.com/Gnucash/gnucash/commit/51a0a55e (commit)
	from  https://github.com/Gnucash/gnucash/commit/e64e73b6 (commit)



commit 5157d8b50ae3985e5f0e32746cb23c4a0a3cb90c
Merge: e64e73b a9fab36
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri Oct 27 12:06:52 2017 -0700

    Merge branch Christopher Lam's Transaction Report Improvements into unstable.


commit a9fab360401a7a859a304ba4033cbf8c189278ac
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Fri Oct 27 16:01:45 2017 +0800

    transaction.scm upgrade complete
    
    It now has account and transaction substring/regex matcher.
    Verified working in 2.7.0

diff --git a/gnucash/report/standard-reports/income-gst-statement.scm b/gnucash/report/standard-reports/income-gst-statement.scm
index 6784755..8d327c8 100644
--- a/gnucash/report/standard-reports/income-gst-statement.scm
+++ b/gnucash/report/standard-reports/income-gst-statement.scm
@@ -1587,7 +1587,7 @@ for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
         ;; in guile code
         ((= splitcount 2)
          (is-in-account-list? other-account))
-        
+
         ;; A multi-split transaction - run over all splits
         ((> splitcount 2)
          (or-map is-in-account-list? other-accounts))
diff --git a/gnucash/report/standard-reports/transaction.scm b/gnucash/report/standard-reports/transaction.scm
index dab69e8..bd3445c 100644
--- a/gnucash/report/standard-reports/transaction.scm
+++ b/gnucash/report/standard-reports/transaction.scm
@@ -64,6 +64,10 @@
 (define optname-table-export (N_ "Table for Exporting"))
 (define optname-common-currency (N_ "Common Currency"))
 (define optname-currency (N_ "Report's currency"))
+(define optname-account-matcher (N_ "Account Matcher"))
+(define optname-account-matcher-regex (N_ "Account Matcher uses regular expressions for extended matching"))
+(define optname-transaction-matcher (N_ "Transaction Matcher"))
+(define optname-transaction-matcher-regex (N_ "Transaction Matcher uses regular expressions for extended matching"))
 (define def:grand-total-style "grand-total")
 (define def:normal-row-style "normal-row")
 (define def:alternate-row-style "alternate-row")
@@ -639,7 +643,24 @@
    (gnc:make-simple-boolean-option
     gnc:pagename-general optname-table-export
     "g" (N_ "Formats the table suitable for cut & paste exporting with extra cells.") #f))  
-  
+
+  (gnc:register-trep-option
+   (gnc:make-string-option
+    gnc:pagename-general optname-transaction-matcher
+    "i1" (N_ "Match only transactions whose substring is matched e.g. '#gift' \
+will find all transactions with #gift in description, notes or memo. It can be left \
+blank, which will disable the matcher.")
+    ""))
+
+  (gnc:register-trep-option
+   (gnc:make-simple-boolean-option
+    gnc:pagename-general optname-transaction-matcher-regex
+    "i2"
+    (N_ "By default the transaction matcher will search substring only. Set this to true to \
+enable full POSIX regular expressions capabilities. '#work|#family' will match both \
+tags within description, notes or memo. ")
+    #f))
+
   ;; Accounts options
   
   ;; account to do report on
@@ -658,14 +679,22 @@
 
   (gnc:register-trep-option
    (gnc:make-string-option
-    gnc:pagename-accounts (N_ "Account Matcher")
-    "a5" (N_ "Match only above accounts whose fullname is matched by regex \
-e.g. ':Travel' will match Expenses:Travel:Holiday and Expenses:Business:Travel. \
-'Car|Flights' will match both Expenses:Car and Expenses:Business:Flights. It \
-can be left blank, which will disable the matcher")
+    gnc:pagename-accounts optname-account-matcher
+    "a5" (N_ "Match only above accounts whose fullname is matched e.g. ':Travel' will match \
+Expenses:Travel:Holiday and Expenses:Business:Travel. It can be left blank, which will disable \
+the matcher.")
     ""))
 
   (gnc:register-trep-option
+   (gnc:make-simple-boolean-option
+    gnc:pagename-accounts optname-account-matcher-regex
+    "a6"
+    (N_ "By default the account matcher will search substring only. Set this to true to enable full \
+POSIX regular expressions capabilities. 'Car|Flights' will match both Expenses:Car and Expenses:Flights. \
+Use a period (.) to match a single character e.g. '20../.' will match 'Travel 2017/1 London'. ")
+    #f))
+
+  (gnc:register-trep-option
    (gnc:make-account-list-option
     gnc:pagename-accounts (N_ "Filter By...")
     "b" (N_ "Filter on these accounts.")
@@ -1530,10 +1559,19 @@ Credit Card, and Income accounts."))))))
 
 
   (gnc:report-starting reportname)
-  (let ((document (gnc:make-html-document))
-	(c_account_1 (opt-val gnc:pagename-accounts "Accounts"))
-	(c_account_matcher (opt-val gnc:pagename-accounts "Account Matcher"))
-	(c_account_2 (opt-val gnc:pagename-accounts "Filter By..."))
+  (let* ((document (gnc:make-html-document))
+        (c_account_0 (opt-val gnc:pagename-accounts "Accounts"))
+        (account-matcher (opt-val gnc:pagename-accounts optname-account-matcher))
+        (account-matcher-regexp (if (opt-val gnc:pagename-accounts optname-account-matcher-regex)
+                                    (make-regexp account-matcher)
+                                    #f))
+        (c_account_1 (filter
+                      (lambda (acc)
+                        (if account-matcher-regexp
+                            (regexp-exec account-matcher-regexp (gnc-account-get-full-name acc))
+                            (string-contains (gnc-account-get-full-name acc) account-matcher)))
+                     c_account_0))
+        (c_account_2 (opt-val gnc:pagename-accounts "Filter By..."))
 	(filter-mode (opt-val gnc:pagename-accounts "Filter Type"))
         (begindate (gnc:timepair-start-day-time
                     (gnc:date-option-absolute-time
@@ -1541,6 +1579,10 @@ Credit Card, and Income accounts."))))))
         (enddate (gnc:timepair-end-day-time
                   (gnc:date-option-absolute-time
                    (opt-val gnc:pagename-general "End Date"))))
+        (transaction-matcher (opt-val gnc:pagename-general optname-transaction-matcher))
+        (transaction-matcher-regexp (if (opt-val gnc:pagename-general optname-transaction-matcher-regex)
+                                        (make-regexp transaction-matcher)
+                                        #f))
         (report-title (opt-val 
                        gnc:pagename-general
                        gnc:optname-reportname))
@@ -1548,18 +1590,13 @@ Credit Card, and Income accounts."))))))
         (primary-order (opt-val pagename-sorting "Primary Sort Order"))
         (secondary-key (opt-val pagename-sorting optname-sec-sortkey))
         (secondary-order (opt-val pagename-sorting "Secondary Sort Order"))
-	(void-status (opt-val gnc:pagename-accounts optname-void-transactions))
+        (void-status (opt-val gnc:pagename-accounts optname-void-transactions))
         (splits '())
         (query (qof-query-create-for-splits)))
 
     ;;(gnc:warn "accts in trep-renderer:" c_account_1)
     ;;(gnc:warn "Report Account names:" (get-other-account-names c_account_1))
 
-    (set! c_account_1
-          (filter (lambda (acc)
-                    (string-match c_account_matcher (gnc-account-get-full-name acc)))
-                  c_account_1))
-    
     (if (not (or (null? c_account_1) (and-map not c_account_1)))
         (begin
           (qof-query-set-book query (gnc-get-current-book))
@@ -1590,28 +1627,23 @@ Credit Card, and Income accounts."))))))
 
           ;;(gnc:warn "Splits in trep-renderer:" splits)
 
-	  ;;(gnc:warn "Filter account names:" (get-other-account-names c_account_2))
-
-	  ;;This should probably a cond or a case to allow for different filter types.
-	  ;;(gnc:warn "Filter Mode: " filter-mode)
-	  (if (eq? filter-mode 'include)
-	      (begin
-		;;(gnc:warn "Including Filter Accounts")
-		(set! splits (filter (lambda (split) 
-				       (is-filter-member split c_account_2))
-				     splits))
-		)
-	      )
-
-	  (if (eq? filter-mode 'exclude)
-	      (begin
-		;;(gnc:warn "Excluding Filter Accounts")
-		(set! splits (filter (lambda (split) 
-				       (not (is-filter-member split c_account_2)))
-				     splits))
-		)
-	      )
-	
+          ; Combined Filter:
+          ; - include/exclude splits to/from selected accounts
+          ; - substring/regex matcher for Transaction Description/Notes/Memo
+          (set! splits (filter
+                        (lambda (split)
+                          (let* ((trans (xaccSplitGetParent split))
+                                 (match? (lambda (str)
+                                           (if transaction-matcher-regexp
+                                               (regexp-exec transaction-matcher-regexp str)
+                                               (string-contains str transaction-matcher)))))
+                            (and (if (eq? filter-mode 'include) (is-filter-member split c_account_2) #t)
+                                 (if (eq? filter-mode 'exclude) (not (is-filter-member split c_account_2)) #t)
+                                 (or (match? (xaccTransGetDescription trans))
+                                     (match? (xaccTransGetNotes trans))
+                                     (match? (xaccSplitGetMemo split))))))
+                        splits))
+
           (if (not (null? splits))
               (let ((table 
                      (make-split-table 
@@ -1659,12 +1691,22 @@ match the time interval and account selection specified \
 in the Options panel.")))
                 (gnc:html-document-add-object! document p))))
 
-        ;; error condition: no accounts specified
-        
-        (gnc:html-document-add-object!
-         document 
-	 (gnc:html-make-no-account-warning 
-	  report-title (gnc:report-id report-obj))))
+        (if (null? c_account_0)
+            
+            ;; error condition: no accounts specified
+            (gnc:html-document-add-object!
+             document 
+             (gnc:html-make-no-account-warning 
+              report-title (gnc:report-id report-obj)))
+
+            ;; error condition: accounts were specified but none matcher string/regex
+            (gnc:html-document-add-object!
+             document
+             (gnc:make-html-text
+              (gnc:html-markup-h2
+               (N_ "No accounts were matched"))
+              (gnc:html-markup-p
+               (N_ "The account matcher specified in the report options did not match any accounts."))))))
 
     (gnc:report-finished)
     document))

commit dfa25e8cbd17ec420b84e9180a098501d9155e3e
Author: christopherlam <christopher.lck at gmail.com>
Date:   Fri Oct 27 15:10:49 2017 +0800

    refactor old is-filter-member to use srfi-1
    
    This has better readability

diff --git a/gnucash/report/standard-reports/income-gst-statement.scm b/gnucash/report/standard-reports/income-gst-statement.scm
index 64c7aa0..6784755 100644
--- a/gnucash/report/standard-reports/income-gst-statement.scm
+++ b/gnucash/report/standard-reports/income-gst-statement.scm
@@ -228,7 +228,8 @@ accounts must be of type ASSET for taxes paid on expenses, and type LIABILITY fo
                           subtotal-style export?)
   (let* ((row-contents '())
          (columns (map (lambda (coll) (coll 'format gnc:make-gnc-monetary #f)) subtotal-collectors))
-         (list-of-commodities (delete-duplicates (map gnc:gnc-monetary-commodity (apply append columns)))))
+         (list-of-commodities (delete-duplicates (map gnc:gnc-monetary-commodity (apply append columns))
+                                                 gnc-commodity-equal)))
 
     (define (retrieve-commodity list-of-monetary commodity)
       (if (null? list-of-monetary)
@@ -1574,37 +1575,22 @@ for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
 
   (define (is-filter-member split account-list)
     (let* ((txn (xaccSplitGetParent split))
-           (splitcount (xaccTransCountSplits txn)))
-
+           (splitcount (xaccTransCountSplits txn))
+           (other-account (xaccSplitGetAccount (xaccSplitGetOtherSplit split)))
+           (splits-equal? (lambda (s1 s2) (xaccSplitEqual s1 s2 #t #f #f)))
+           (other-splits (delete split (xaccTransGetSplitList txn) splits-equal?))
+           (other-accounts (map xaccSplitGetAccount other-splits))
+           (is-in-account-list? (lambda (acc) (member acc account-list))))
       (cond
         ;; A 2-split transaction - test separately so it can be optimized
         ;; to significantly reduce the number of splits to traverse
         ;; in guile code
         ((= splitcount 2)
-         (let* ((other      (xaccSplitGetOtherSplit split))
-                (other-acct (xaccSplitGetAccount other)))
-           (member other-acct account-list)))
-
+         (is-in-account-list? other-account))
+        
         ;; A multi-split transaction - run over all splits
         ((> splitcount 2)
-         (let ((splits (xaccTransGetSplitList txn)))
-
-           ;; Walk through the list of splits.
-           ;; if we reach the end, return #f
-           ;; if the 'this' != 'split' and the split->account is a member
-           ;; of the account-list, then return #t, else recurse
-           (define (is-member splits)
-             (if (null? splits)
-                 #f
-                 (let* ((this (car splits))
-                        (rest (cdr splits))
-                        (acct (xaccSplitGetAccount this)))
-                   (if (and (not (eq? this split))
-                            (member acct account-list))
-                       #t
-                       (is-member rest)))))
-
-           (is-member splits)))
+         (or-map is-in-account-list? other-accounts))
 
         ;; Single transaction splits
         (else #f))))

commit cdb677633ca78d6ed94a36a6ba1a3e93649b79dd
Author: christopherlam <christopher.lck at gmail.com>
Date:   Thu Oct 26 22:16:24 2017 +0800

    improve split-remove-duplicates, combine filters
    
    To use inbuilt list functions

diff --git a/gnucash/report/standard-reports/income-gst-statement.scm b/gnucash/report/standard-reports/income-gst-statement.scm
index 1027658..64c7aa0 100644
--- a/gnucash/report/standard-reports/income-gst-statement.scm
+++ b/gnucash/report/standard-reports/income-gst-statement.scm
@@ -1566,16 +1566,11 @@ for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
   ;;  ( map (lambda (acct)  (gnc-account-get-full-name acct)) account-list))
 
   (define (splits-filter-unique-transactions splits)
-    (let ((have-trans-hash (make-hash-table)))
-      (define (only-one-copy? split)
-        (let* ((parent (xaccSplitGetParent split))
-               (trans-guid (gncTransGetGUID parent)))
-          (if (hash-ref have-trans-hash trans-guid #f)
-              #f  ; already have a copy of this transaction
-              (begin
-                (hash-set! have-trans-hash trans-guid #t)
-                #t))))
-      (filter only-one-copy? splits)))
+    (define (same-txn? s1 s2)
+      (define txn1 (xaccSplitGetParent s1))
+      (define txn2 (xaccSplitGetParent s2))
+      (xaccTransEqual txn1 txn2 #t #t #t #f))
+    (delete-duplicates! splits same-txn?))
 
   (define (is-filter-member split account-list)
     (let* ((txn (xaccSplitGetParent split))
@@ -1690,26 +1685,11 @@ for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
 
           ;;(gnc:warn "Splits in trep-renderer:" splits)
 
-          ;;(gnc:warn "Filter account names:" (get-other-account-names c_account_2))
-
-          ;;This should probably a cond or a case to allow for different filter types.
-          ;;(gnc:warn "Filter Mode: " filter-mode)
-          (if (eq? filter-mode 'include)
-              (begin
-                ;;(gnc:warn "Including Filter Accounts")
-                (set! splits (filter (lambda (split)
-                                       (is-filter-member split c_account_2))
-                                     splits))))
-
-          (if (eq? filter-mode 'exclude)
-              (begin
-                ;;(gnc:warn "Excluding Filter Accounts")
-                (set! splits (filter (lambda (split)
-                                       (not (is-filter-member split c_account_2)))
-                                     splits))))
-
-          ; Combines: Transaction Description/Notes/Memo matcher, include only
-          ; invoices & regular transactions, and disallow closing txns.
+          ; Combined Filter:
+          ; - include/exclude splits to/from selected accounts
+          ; - include only Invoices & Regular Transactions (i.e. remove Link & Payments)
+          ; - disallow Closing Transactions, and
+          ; - substring/regex matcher for Description/Notes/Memo 
           (set! splits (filter
                         (lambda (split)
                           (let* ((trans (xaccSplitGetParent split))
@@ -1718,7 +1698,9 @@ for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
                                            (if transaction-matcher-regexp
                                                (regexp-exec transaction-matcher-regexp str)
                                                (string-contains str transaction-matcher)))))
-                            (and (member txn-type (list TXN-TYPE-NONE TXN-TYPE-INVOICE))
+                            (and (if (eq? filter-mode 'include) (is-filter-member split c_account_2) #t)
+                                 (if (eq? filter-mode 'exclude) (not (is-filter-member split c_account_2)) #t)
+                                 (member txn-type (list TXN-TYPE-NONE TXN-TYPE-INVOICE))
                                  (not (xaccTransGetIsClosingTxn trans))
                                  (or (match? (xaccTransGetDescription trans))
                                      (match? (xaccTransGetNotes trans))

commit 3475a894f9f463cd36b1dc19817e07ea2a4e0f02
Author: christopherlam <christopher.lck at gmail.com>
Date:   Wed Oct 25 14:09:28 2017 +0800

    Regex is optional, and add transaction matcher
    
    This commit will reinstate substring matcher, with optional regex matching.
    
    Will also add a Transaction Matcher - will include splits whose description/notes/memo is substring/regex matched. Will be usable for #category matching, especially when backported to transaction.scm
    
    Also strings are defined centrally which will aid localization and reduce typos.

diff --git a/gnucash/report/standard-reports/income-gst-statement.scm b/gnucash/report/standard-reports/income-gst-statement.scm
index 20885eb..1027658 100644
--- a/gnucash/report/standard-reports/income-gst-statement.scm
+++ b/gnucash/report/standard-reports/income-gst-statement.scm
@@ -63,11 +63,15 @@
 (define optname-void-transactions (N_ "Void Transactions"))
 (define optname-table-export (N_ "Table for Exporting"))
 (define optname-common-currency (N_ "Common Currency"))
-(define TAX-SETUP-DESC "From the Report Options, you will need to select the accounts which will \
+(define TAX-SETUP-DESC (N_ "From the Report Options, you will need to select the accounts which will \
 hold the GST/VAT taxes collected or paid. These accounts must contain splits which document the \
 monies which are wholly sent or claimed from tax authorities during periodic GST/VAT returns. These \
-accounts must be of type ASSET for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
+accounts must be of type ASSET for taxes paid on expenses, and type LIABILITY for taxes collected on sales."))
 (define optname-currency (N_ "Report's currency"))
+(define optname-account-matcher (N_ "Account Matcher"))
+(define optname-account-matcher-regex (N_ "Account Matcher uses regular expressions for extended matching"))
+(define optname-transaction-matcher (N_ "Transaction Matcher"))
+(define optname-transaction-matcher-regex (N_ "Transaction Matcher uses regular expressions for extended matching"))
 (define def:grand-total-style "grand-total")
 (define def:normal-row-style "normal-row")
 (define def:alternate-row-style "alternate-row")
@@ -676,6 +680,23 @@ accounts must be of type ASSET for taxes paid on expenses, and type LIABILITY fo
     gnc:pagename-general optname-table-export
     "g" (N_ "Formats the table suitable for cut & paste exporting with extra cells.") #f))
 
+  (gnc:register-trep-option
+   (gnc:make-string-option
+    gnc:pagename-general optname-transaction-matcher
+    "i1" (N_ "Match only transactions whose substring is matched e.g. '#gift' \
+will find all transactions with #gift in memo, description or notes. It can be left \
+blank, which will disable the matcher.")
+    ""))
+
+  (gnc:register-trep-option
+   (gnc:make-simple-boolean-option
+    gnc:pagename-general optname-transaction-matcher-regex
+    "i2"
+    (N_ "By default the transaction matcher will search substring only. Set this to true to \
+enable full POSIX regular expressions capabilities. '#work|#family' will match both \
+tags within description, notes or memo. ")
+    #f))
+
   ;; Accounts options
 
   ;; account to do report on
@@ -696,13 +717,22 @@ accounts must be of type ASSET for taxes paid on expenses, and type LIABILITY fo
 
   (gnc:register-trep-option
    (gnc:make-string-option
-    gnc:pagename-accounts (N_ "Account Matcher")
-    "b15" (N_ "Match only above accounts whose fullname matches regex e.g. ':Travel' will \
-match Expenses:Travel:Holiday and Expenses:Business:Travel. 'Car|Flights' will match both \
-Expenses:Car and Expenses:Flights. It can be left blank, which will disable the matcher.")
+    gnc:pagename-accounts optname-account-matcher
+    "b15" (N_ "Match only above accounts whose fullname is matched e.g. ':Travel' will match \
+Expenses:Travel:Holiday and Expenses:Business:Travel. It can be left blank, which will disable \
+the matcher.")
     ""))
 
   (gnc:register-trep-option
+   (gnc:make-simple-boolean-option
+    gnc:pagename-accounts optname-account-matcher-regex
+    "b16"
+    (N_ "By default the account matcher will search substring only. Set this to true to enable full \
+POSIX regular expressions capabilities. 'Car|Flights' will match both Expenses:Car and Expenses:Flights. \
+Use a period (.) to match a single character e.g. '20../.' will match 'Travel 2017/1 London'. ")
+    #f))
+
+  (gnc:register-trep-option
    (gnc:make-account-list-limited-option
     gnc:pagename-accounts (N_ "Tax Accounts")
     "b17" (N_ "Please find and select the accounts which will hold the tax collected or paid. \
@@ -1588,10 +1618,15 @@ for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
 
   (let* ((document (gnc:make-html-document))
          (c_account_0 (opt-val gnc:pagename-accounts "Accounts"))
-         (c_account_matcher (opt-val gnc:pagename-accounts "Account Matcher"))
+         (account-matcher (opt-val gnc:pagename-accounts optname-account-matcher))
+         (account-matcher-regexp (if (opt-val gnc:pagename-accounts optname-account-matcher-regex)
+                                     (make-regexp account-matcher)
+                                     #f))
          (c_account_1 (filter
                        (lambda (acc)
-                         (string-match c_account_matcher (gnc-account-get-full-name acc)))
+                         (if account-matcher-regexp
+                             (regexp-exec account-matcher-regexp (gnc-account-get-full-name acc))
+                             (string-contains (gnc-account-get-full-name acc) account-matcher)))
                        c_account_0))
          (c_account_2 (opt-val gnc:pagename-accounts "Filter By..."))
          (tax-accounts (opt-val gnc:pagename-accounts "Tax Accounts"))
@@ -1606,6 +1641,10 @@ for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
          (enddate (gnc:timepair-end-day-time
                    (gnc:date-option-absolute-time
                     (opt-val gnc:pagename-general "End Date"))))
+         (transaction-matcher (opt-val gnc:pagename-general optname-transaction-matcher))
+         (transaction-matcher-regexp (if (opt-val gnc:pagename-general optname-transaction-matcher-regex)
+                                         (make-regexp transaction-matcher)
+                                         #f))
          (report-title (opt-val
                         gnc:pagename-general
                         gnc:optname-reportname))
@@ -1669,20 +1708,27 @@ for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
                                        (not (is-filter-member split c_account_2)))
                                      splits))))
 
-          ; We have to remove duplicates because the report will *sum* amounts in a transaction
-          ; otherwise it will double count where transaction contains 2 splits in same account
-          (set! splits (splits-filter-unique-transactions splits))
-
-          ; For each split, we will only keep those which contain useful data
-          ; e.g. show invoices & regular transactions. We will also disallow closing txns.
+          ; Combines: Transaction Description/Notes/Memo matcher, include only
+          ; invoices & regular transactions, and disallow closing txns.
           (set! splits (filter
                         (lambda (split)
                           (let* ((trans (xaccSplitGetParent split))
-                                 (txn-type (xaccTransGetTxnType trans)))
+                                 (txn-type (xaccTransGetTxnType trans))
+                                 (match? (lambda (str)
+                                           (if transaction-matcher-regexp
+                                               (regexp-exec transaction-matcher-regexp str)
+                                               (string-contains str transaction-matcher)))))
                             (and (member txn-type (list TXN-TYPE-NONE TXN-TYPE-INVOICE))
-                                 (not (xaccTransGetIsClosingTxn trans)))))
+                                 (not (xaccTransGetIsClosingTxn trans))
+                                 (or (match? (xaccTransGetDescription trans))
+                                     (match? (xaccTransGetNotes trans))
+                                     (match? (xaccSplitGetMemo split))))))
                         splits))
 
+          ; We have to remove duplicates because the report will *sum* amounts in a transaction
+          ; otherwise it will double count where transaction contains 2 splits in same account
+          (set! splits (splits-filter-unique-transactions splits))
+
           (if (not (null? splits))
               (let ((table
                      (make-split-table
@@ -1762,28 +1808,38 @@ for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
 
         ;; error condition: no accounts specified
 
-        (begin
-          (gnc:html-document-add-object!
-           document
-           (gnc:html-make-no-account-warning
-            report-title (gnc:report-id report-obj)))
-
-          (gnc:html-document-add-object!
-           document
-           (gnc:make-html-text
-            (gnc:html-markup-p
-             "This report is useful to calculate periodic business tax payable/receivable from"
-             " authorities. From <i>Edit report options</i> above, choose your Business Income and Business Expense accounts."
-             " Each transaction may contain, in addition to the accounts payable/receivable or bank accounts,"
-             " a split to a tax account, e.g. Income:Sales -$1000, Liability:GST on Sales -$100, Asset:Bank $1100.")
-            (gnc:html-markup-p
-             " These tax accounts can either be populated using the standard register, or from Business Invoices and Bills "
-             " which will require Business > Sales Tax Tables to be set up correctly. Please see the documentation.")))
-
-          (gnc:html-document-add-object!
-           document
-           (gnc:make-html-text
-            (gnc:html-markup-p TAX-SETUP-DESC)))))
+          (if (null? c_account_0)
+              (begin
+                (gnc:html-document-add-object!
+                 document
+                 (gnc:html-make-no-account-warning
+                  report-title (gnc:report-id report-obj)))
+                
+                (gnc:html-document-add-object!
+                 document
+                 (gnc:make-html-text
+                  (gnc:html-markup-p
+                   "This report is useful to calculate periodic business tax payable/receivable from"
+                   " authorities. From <i>Edit report options</i> above, choose your Business Income and Business Expense accounts."
+                   " Each transaction may contain, in addition to the accounts payable/receivable or bank accounts,"
+                   " a split to a tax account, e.g. Income:Sales -$1000, Liability:GST on Sales -$100, Asset:Bank $1100.")
+                  (gnc:html-markup-p
+                   " These tax accounts can either be populated using the standard register, or from Business Invoices and Bills "
+                   " which will require Business > Sales Tax Tables to be set up correctly. Please see the documentation.")))
+                
+                (gnc:html-document-add-object!
+                 document
+                 (gnc:make-html-text
+                  (gnc:html-markup-p TAX-SETUP-DESC))))
+            
+              (begin
+                (gnc:html-document-add-object!
+                 document
+                 (gnc:make-html-text
+                  (gnc:html-markup-h2
+                   (N_ "No accounts were matched"))
+                  (gnc:html-markup-p
+                   (N_ "The account matcher specified in the report options did not match any accounts.")))))))
 
     (gnc:report-finished)
     document))

commit 885272a150bb138bd2d4a01c098caa3eae77ba80
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Tue Oct 24 19:18:40 2017 +0800

    Enhance transaction.scm account filter to regex
    
    This commit will enhance the account fullname filter to full regex matching capabilities. Will allow complex account fullname queries e.g. 'Car|Flights'

diff --git a/gnucash/report/standard-reports/transaction.scm b/gnucash/report/standard-reports/transaction.scm
index 4fbab7d..dab69e8 100644
--- a/gnucash/report/standard-reports/transaction.scm
+++ b/gnucash/report/standard-reports/transaction.scm
@@ -34,6 +34,7 @@
 (use-modules (gnucash main)) ;; FIXME: delete after we finish modularizing.
 (use-modules (srfi srfi-1))
 (use-modules (srfi srfi-13))
+(use-modules (ice-9 regex))
 (use-modules (gnucash gnc-module))
 (use-modules (gnucash gettext))
 
@@ -657,10 +658,11 @@
 
   (gnc:register-trep-option
    (gnc:make-string-option
-    gnc:pagename-accounts (N_ "Account Substring")
-    "a5" (N_ "Match only above accounts whose fullname contains substring e.g. ':Travel' will \
-match Expenses:Travel:Holiday and Expenses:Business:Travel. Can be left blank, which will \
-disable the substring filter. This filter is case-sensitive.")
+    gnc:pagename-accounts (N_ "Account Matcher")
+    "a5" (N_ "Match only above accounts whose fullname is matched by regex \
+e.g. ':Travel' will match Expenses:Travel:Holiday and Expenses:Business:Travel. \
+'Car|Flights' will match both Expenses:Car and Expenses:Business:Flights. It \
+can be left blank, which will disable the matcher")
     ""))
 
   (gnc:register-trep-option
@@ -1530,7 +1532,7 @@ Credit Card, and Income accounts."))))))
   (gnc:report-starting reportname)
   (let ((document (gnc:make-html-document))
 	(c_account_1 (opt-val gnc:pagename-accounts "Accounts"))
-	(c_account_substring (opt-val gnc:pagename-accounts "Account Substring"))
+	(c_account_matcher (opt-val gnc:pagename-accounts "Account Matcher"))
 	(c_account_2 (opt-val gnc:pagename-accounts "Filter By..."))
 	(filter-mode (opt-val gnc:pagename-accounts "Filter Type"))
         (begindate (gnc:timepair-start-day-time
@@ -1555,7 +1557,7 @@ Credit Card, and Income accounts."))))))
 
     (set! c_account_1
           (filter (lambda (acc)
-                    (string-contains (gnc-account-get-full-name acc) c_account_substring))
+                    (string-match c_account_matcher (gnc-account-get-full-name acc)))
                   c_account_1))
     
     (if (not (or (null? c_account_1) (and-map not c_account_1)))

commit d077400ba87b44af75c1c3b97661d035028e9aca
Author: christopherlam <christopher.lck at gmail.com>
Date:   Tue Oct 24 12:59:25 2017 +0800

    Enhance account filter to a regex
    
    This commit will enhance the account fullname filter to full regex matching capabilities. Will allow complex account fullname queries e.g. "Car|Flights|Travel"

diff --git a/gnucash/report/standard-reports/income-gst-statement.scm b/gnucash/report/standard-reports/income-gst-statement.scm
index 92d0476..20885eb 100644
--- a/gnucash/report/standard-reports/income-gst-statement.scm
+++ b/gnucash/report/standard-reports/income-gst-statement.scm
@@ -37,6 +37,7 @@
 (use-modules (gnucash main)) ;; FIXME: delete after we finish modularizing.
 (use-modules (srfi srfi-1))
 (use-modules (srfi srfi-13))
+(use-modules (ice-9 regex))
 (use-modules (gnucash gnc-module))
 (use-modules (gnucash gettext))
 (use-modules (gnucash printf))
@@ -695,10 +696,10 @@ accounts must be of type ASSET for taxes paid on expenses, and type LIABILITY fo
 
   (gnc:register-trep-option
    (gnc:make-string-option
-    gnc:pagename-accounts (N_ "Account Substring")
-    "b15" (N_ "Match only above accounts whose fullname contains substring e.g. ':Travel' will \
-match Expenses:Travel:Holiday and Expenses:Business:Travel. Can be left blank, which will \
-disable the substring filter. This filter is case-sensitive.")
+    gnc:pagename-accounts (N_ "Account Matcher")
+    "b15" (N_ "Match only above accounts whose fullname matches regex e.g. ':Travel' will \
+match Expenses:Travel:Holiday and Expenses:Business:Travel. 'Car|Flights' will match both \
+Expenses:Car and Expenses:Flights. It can be left blank, which will disable the matcher.")
     ""))
 
   (gnc:register-trep-option
@@ -1587,10 +1588,10 @@ for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
 
   (let* ((document (gnc:make-html-document))
          (c_account_0 (opt-val gnc:pagename-accounts "Accounts"))
-         (c_account_substring (opt-val gnc:pagename-accounts "Account Substring"))
+         (c_account_matcher (opt-val gnc:pagename-accounts "Account Matcher"))
          (c_account_1 (filter
                        (lambda (acc)
-                         (string-contains (gnc-account-get-full-name acc) c_account_substring))
+                         (string-match c_account_matcher (gnc-account-get-full-name acc)))
                        c_account_0))
          (c_account_2 (opt-val gnc:pagename-accounts "Filter By..."))
          (tax-accounts (opt-val gnc:pagename-accounts "Tax Accounts"))

commit b74c0bedfd56b6b772abd325a41910e6511f90d9
Author: christopherlam <christopher.lck at gmail.com>
Date:   Tue Oct 24 08:06:56 2017 +0800

    Amend some strings for improved visibility
    
    Enhance visibility of total-sales and total-purchases (all caps) and amend input/output tax accounts display.

diff --git a/gnucash/report/standard-reports/income-gst-statement.scm b/gnucash/report/standard-reports/income-gst-statement.scm
index f820d3f..92d0476 100644
--- a/gnucash/report/standard-reports/income-gst-statement.scm
+++ b/gnucash/report/standard-reports/income-gst-statement.scm
@@ -1197,7 +1197,7 @@ for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
         (append
          ; each column will be a vector
          ; (vector heading calculator-function reverse-column?)
-         (list (vector "Total Sales" total-sales #t))
+         (list (vector "TOTAL SALES" total-sales #t))
          (if (gnc:option-value (gnc:lookup-option options gnc:pagename-display (N_ "Individual income columns")))
              (map (lambda (acc) (vector (xaccAccountGetName acc) (account-adder acc) #t))
                   accounts-sales)
@@ -1206,7 +1206,7 @@ for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
              (map (lambda (acc) (vector (xaccAccountGetName acc) (account-adder acc) #t))
                   accounts-tax-collected)
              (list (vector "Tax on Sales" tax-on-sales #t)))
-         (list (vector "Total Purchases" total-purchases #f))
+         (list (vector "TOTAL PURCHASES" total-purchases #f))
          (if (gnc:option-value (gnc:lookup-option options gnc:pagename-display (N_ "Individual expense columns")))
              (map (lambda (acc) (vector (xaccAccountGetName acc) (account-adder acc) #f))
                   accounts-purchases)
@@ -1723,14 +1723,18 @@ for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
                  (gnc:make-html-text
                   (gnc:html-markup-p
                    "Input Tax accounts: "
-                   (string-join (map gnc-account-get-full-name accounts-tax-paid) ", "))))
+                   (if (null? accounts-tax-paid)
+                       (N_ "None")
+                       (string-join (map gnc-account-get-full-name accounts-tax-paid) ", ")))))
 
                 (gnc:html-document-add-object!
                  document
                  (gnc:make-html-text
                   (gnc:html-markup-p
                    "Output Tax accounts: "
-                   (string-join (map gnc-account-get-full-name accounts-tax-collected) ", "))))
+                   (if (null? accounts-tax-collected)
+                       (N_ "None")
+                       (string-join (map gnc-account-get-full-name accounts-tax-collected) ", ")))))
 
                 (if (null? (append accounts-tax-collected accounts-tax-paid))
                     (gnc:html-document-add-object!

commit 51a0a55e43c742cbdb58440dce479e4e348e0a29
Author: christopherlam <christopher.lck at gmail.com>
Date:   Tue Oct 24 08:04:27 2017 +0800

    Change critical code to pure FP
    
    The function split-adder is the most crucial code  in this report. This commit changes it to pure functional programming.

diff --git a/gnucash/report/standard-reports/income-gst-statement.scm b/gnucash/report/standard-reports/income-gst-statement.scm
index a74092f..f820d3f 100644
--- a/gnucash/report/standard-reports/income-gst-statement.scm
+++ b/gnucash/report/standard-reports/income-gst-statement.scm
@@ -1173,33 +1173,22 @@ for taxes paid on expenses, and type LIABILITY for taxes collected on sales.")
       (letrec
           ((myadd (lambda (X Y) (if X (if Y (gnc-numeric-add X Y GNC-DENOM-AUTO GNC-RND-ROUND) X) Y)))
            (myneg (lambda (X) (if X (gnc-numeric-neg X) #f)))
-           (split-adder (lambda (split accountlist typefilter)
+           (split-adder (lambda (split accountlist)
                           (let* ((transaction (xaccSplitGetParent split))
                                  (splits-in-transaction (xaccTransGetSplitList transaction))
-                                 (sum #f))
-                            (for-each (lambda (s)
-                                        (let* ((splitAcc (xaccSplitGetAccount s))
-                                               (splitVal (if (xaccTransGetVoidStatus transaction)
-                                                             (xaccSplitVoidFormerValue s)
-                                                             (xaccSplitGetValue s)))
-                                               (splitCommodity (xaccAccountGetCommodity splitAcc))
-                                               (splitAccType (xaccAccountGetType splitAcc))
-                                               (splitAccName (xaccAccountGetName splitAcc)))
-                                          (if accountlist
-                                              (if (member splitAcc accountlist)
-                                                  (set! sum (myadd sum splitVal))))
-                                          (if typefilter
-                                              (if (eq? typefilter splitAccType)
-                                                  (set! sum (myadd sum splitVal))))))
-                                      splits-in-transaction)
-                            sum)))
-           ;(sales-without-tax (lambda (s) (split-adder s #f ACCT-TYPE-INCOME)))
-           ;(purchases-without-tax (lambda (s) (split-adder s #f ACCT-TYPE-EXPENSE)))
-           (tax-on-sales (lambda (s) (split-adder s accounts-tax-collected #f)))
-           (tax-on-purchases (lambda (s) (split-adder s accounts-tax-paid #f)))
-           (sales-without-tax (lambda (s) (split-adder s accounts-sales #f)))
-           (purchases-without-tax (lambda (s) (split-adder s accounts-purchases #f)))
-           (account-adder (lambda (acc) (lambda (s) (split-adder s (list acc) #f))))
+                                 (split-get-value (lambda (s)
+                                                    (if (xaccTransGetVoidStatus transaction)
+                                                        (xaccSplitVoidFormerValue s)
+                                                        (xaccSplitGetValue s))))
+                                 (include-split? (lambda (s) (member (xaccSplitGetAccount s) accountlist)))
+                                 (filtered-splits (filter include-split? splits-in-transaction))
+                                 (list-of-values (map split-get-value filtered-splits)))
+                            (fold myadd #f list-of-values))))
+           (tax-on-sales (lambda (s) (split-adder s accounts-tax-collected)))
+           (tax-on-purchases (lambda (s) (split-adder s accounts-tax-paid)))
+           (sales-without-tax (lambda (s) (split-adder s accounts-sales)))
+           (purchases-without-tax (lambda (s) (split-adder s accounts-purchases)))
+           (account-adder (lambda (acc) (lambda (s) (split-adder s (list acc)))))
            (total-sales (lambda (s) (myadd (tax-on-sales s) (sales-without-tax s))))
            (total-purchases (lambda (s) (myadd (tax-on-purchases s) (purchases-without-tax s))))
            (bank-remittance (lambda (s) (myneg (myadd (total-sales s) (total-purchases s)))))



Summary of changes:
 .../standard-reports/income-gst-statement.scm      | 258 +++++++++++----------
 gnucash/report/standard-reports/transaction.scm    | 130 +++++++----
 2 files changed, 225 insertions(+), 163 deletions(-)



More information about the gnucash-changes mailing list