Merge Chris Lam's 'maint-fix-796614' into maint.

This commit is contained in:
John Ralls 2018-06-23 17:46:25 -07:00
commit 22fb85113a
2 changed files with 127 additions and 22 deletions

View File

@ -39,6 +39,7 @@
;; copied from transaction.scm
(define trep-uuid "2fe3b9833af044abb929a88d5a59620f")
(define reconcile-uuid "e45218c6d76f11e7b5ef0800277ef320")
;; Explicitly set locale to make the report output predictable
(setlocale LC_ALL "C")
@ -64,6 +65,7 @@
(test-begin "transaction.scm")
(null-test)
(trep-tests)
(reconcile-tests)
;; (test-end) must be run as the last function, it will
;; return #f if any of the tests have failed.
(test-end "transaction.scm"))
@ -860,3 +862,52 @@
(get-row-col sxml #f 6))))
(test-end "subtotal table")
))
(define (reconcile-tests)
(let* ((env (create-test-env))
(account-alist (env-create-account-structure-alist env structure))
(bank (cdr (assoc "Bank" account-alist)))
(income (cdr (assoc "Income" account-alist)))
(liability (cdr (assoc "Liabilities" account-alist)))
(expense (cdr (assoc "Expenses" account-alist)))
(YEAR (gnc:time64-get-year (gnc:get-today)))
)
(define (options->sxml options test-title)
(gnc:options->sxml reconcile-uuid options "test-reconcile" test-title))
(define (default-testing-options)
(let ((options (gnc:make-report-options reconcile-uuid)))
(set-option! options "Accounts" "Accounts" (list bank liability))
options))
;; old transactions for testing reconcile date options
(env-transfer env 01 01 1970 bank expense 5 #:description "desc-1" #:num "trn1" #:memo "memo-3")
(env-transfer env 31 12 1969 income bank 10 #:description "desc-2" #:num "trn2" #:void-reason "void" #:notes "notes3")
(env-transfer env 31 12 1969 income bank 29 #:description "desc-3" #:num "trn3"
#:reconcile (cons #\c (gnc-dmy2time64 01 03 1970)))
(env-transfer env 01 02 1970 bank expense 15 #:description "desc-4" #:num "trn4" #:notes "notes2" #:memo "memo-1")
(env-transfer env 10 01 1970 liability expense 10 #:description "desc-5" #:num "trn5" #:void-reason "any")
(env-transfer env 10 01 1970 liability expense 11 #:description "desc-6" #:num "trn6" #:notes "notes1")
(env-transfer env 10 02 1970 bank expense 8 #:description "desc-7" #:num "trn7" #:notes "notes1" #:memo "memo-2"
#:reconcile (cons #\y (gnc-dmy2time64 01 03 1970)))
(let* ((options (default-testing-options)))
(let ((sxml (options->sxml options "null test")))
(test-assert "sxml"
sxml))
(set-option! options "General" "Start Date" (cons 'absolute (gnc-dmy2time64 01 03 1970)))
(set-option! options "General" "End Date" (cons 'absolute (gnc-dmy2time64 31 03 1970)))
(let ((sxml (options->sxml options "filter reconcile date")))
(test-equal "test reconciled amounts = $8"
(list "Total For Reconciled" "$8.00")
(get-row-col sxml 3 #f))
(test-equal "test cleared amounts = $29"
(list "Total For Cleared" "$29.00")
(get-row-col sxml 6 #f))
(test-equal "test unreconciled amounts = $31"
(list "Total For Unreconciled" "$31.00")
(get-row-col sxml 11 #f))
sxml)
)))

View File

@ -16,6 +16,7 @@
;; and enable multiple data columns
;; - add support for indenting for better grouping
;; - add defaults suitable for a reconciliation report
;; including alternative date filtering strategy
;; - add subtotal summary grid
;; - by default, exclude closing transactions from the report
;;
@ -446,10 +447,44 @@ Credit Card, and Income accounts."))
(gnc:option-set-value (gnc:lookup-option options gnc:pagename-general optname-startdate) (cons 'relative 'start-prev-quarter))
(gnc:option-set-value (gnc:lookup-option options gnc:pagename-general optname-enddate) (cons 'relative 'today))
(gnc:option-set-value (gnc:lookup-option options gnc:pagename-display (N_ "Reconciled Date")) #t)
(gnc:option-set-value (gnc:lookup-option options gnc:pagename-display (N_ "Running Balance")) #t)
(gnc:option-set-value (gnc:lookup-option options gnc:pagename-display (N_ "Running Balance")) #f)
(gnc:option-set-value (gnc:lookup-option options gnc:pagename-display (N_ "Memo")) #f)
(gnc:option-make-internal! options gnc:pagename-display "Running Balance")
options)
(define reconcile-report-instructions
(gnc:make-html-text
(_ "The reconcile report is designed to be similar to the formal reconciliation tool.
Please select the account from Report Options. Please note the dates specified in the options
will apply to the Reconciliation Date.")
(gnc:html-markup-br)
(gnc:html-markup-br)))
;; if split is reconciled, retrieve its reconciled date; if not yet reconciled, return #f
(define (split->reconcile-date split)
(and (char=? (xaccSplitGetReconcile split) #\y)
(xaccSplitGetDateReconciled split)))
(define (reconcile-report-calculated-cells options)
(define (opt-val section name)
(gnc:option-value (gnc:lookup-option options section name)))
(letrec
((split-amount (lambda (s) (if (gnc:split-voided? s)
(xaccSplitVoidFormerAmount s)
(xaccSplitGetAmount s))))
(split-currency (lambda (s) (xaccAccountGetCommodity (xaccSplitGetAccount s))))
(amount (lambda (s) (gnc:make-gnc-monetary (split-currency s) (split-amount s))))
(debit-amount (lambda (s) (and (positive? (split-amount s))
(amount s))))
(credit-amount (lambda (s) (and (not (positive? (split-amount s)))
(gnc:monetary-neg (amount s))))))
;; similar to default-calculated-cells but disable dual-subtotals.
(list (vector (_ "Funds In")
debit-amount #f #t #f
(const ""))
(vector (_ "Funds Out")
credit-amount #f #t #f
(const "")))))
;;
;; Default Transaction Report
;;
@ -1047,11 +1082,11 @@ be excluded from periodic reporting.")
(add-if (column-uses? 'reconciled-date)
(vector (_ "Reconciled Date")
(lambda (split transaction-row?)
(gnc:make-html-table-cell/markup
"date-cell"
(if (eqv? (xaccSplitGetReconcile split) #\y)
(qof-print-date (xaccSplitGetDateReconciled split))
"")))))
(let ((reconcile-date (split->reconcile-date split)))
(and reconcile-date
(gnc:make-html-table-cell/markup
"date-cell"
(qof-print-date reconcile-date)))))))
(add-if (column-uses? 'num)
(vector (if (and BOOK-SPLIT-ACTION
@ -1764,13 +1799,20 @@ be excluded from periodic reporting.")
;; Here comes the renderer function for this report.
(define* (trep-renderer report-obj #:key custom-calculated-cells empty-report-message custom-split-filter)
(define* (trep-renderer report-obj #:key custom-calculated-cells empty-report-message
custom-split-filter split->date split->date-include-false?)
;; the trep-renderer is a define* function which, at minimum, takes the report object
;;
;; the optional arguments are:
;; #:custom-calculated-cells - a list of vectors to define customized data columns
;; #:empty-report-message - a str which is displayed at the initial report opening
;; #:empty-report-message - a str or html-object which is displayed at the initial report opening
;; #:custom-split-filter - a split->bool function to add to the split filter
;; #:split->date - a split->time64 which overrides the default posted date filter
;; (see reconcile report)
;; #:split->date-include-false? - addendum to above, specifies filter behaviour if
;; split->date returns #f. useful to include unreconciled splits in reconcile
;; report. it can be useful for alternative date filtering, e.g. filter by
;; transaction->invoice->payment date.
(define options (gnc:report-options report-obj))
(define (opt-val section name) (gnc:option-value (gnc:lookup-option options section name)))
@ -1908,7 +1950,8 @@ be excluded from periodic reporting.")
(qof-query-set-book query (gnc-get-current-book))
(xaccQueryAddAccountMatch query c_account_1 QOF-GUID-MATCH-ANY QOF-QUERY-AND)
(xaccQueryAddDateMatchTT query #t begindate #t enddate QOF-QUERY-AND)
(if (not split->date)
(xaccQueryAddDateMatchTT query #t begindate #t enddate QOF-QUERY-AND))
(case void-status
((non-void-only) (gnc:query-set-match-non-voids-only! query (gnc-get-current-book)))
((void-only) (gnc:query-set-match-voids-only! query (gnc-get-current-book)))
@ -1934,13 +1977,8 @@ be excluded from periodic reporting.")
(qof-query-destroy query)
(if custom-sort?
(begin
(set! splits (stable-sort! splits date-comparator?))
(set! splits (stable-sort! splits secondary-comparator?))
(set! splits (stable-sort! splits primary-comparator?))))
;; Combined Filter:
;; - include/exclude using split->date according to date options
;; - include/exclude splits to/from selected accounts
;; - substring/regex matcher for Transaction Description/Notes/Memo
;; - custom-split-filter, a split->bool function for derived reports
@ -1951,7 +1989,12 @@ be excluded from periodic reporting.")
(if transaction-matcher-regexp
(regexp-exec transaction-matcher-regexp str)
(string-contains str transaction-matcher)))))
(and (case filter-mode
(and (or (not split->date) ; #f = ignore custom date filter
(let ((date (split->date split))) ; cache split->date time64 or #f.
(if date ; if a split->date exists,
(<= begindate date enddate) ; then check for inclusion;
split->date-include-false?))); else behave according to parameter
(case filter-mode
((none) #t)
((include) (is-filter-member split c_account_2))
((exclude) (not (is-filter-member split c_account_2))))
@ -1964,6 +2007,11 @@ be excluded from periodic reporting.")
)))
splits))
(when custom-sort?
(set! splits (stable-sort! splits date-comparator?))
(set! splits (stable-sort! splits secondary-comparator?))
(set! splits (stable-sort! splits primary-comparator?)))
(if (null? splits)
;; error condition: no splits found
@ -1993,6 +2041,11 @@ be excluded from periodic reporting.")
(qof-print-date begindate)
(qof-print-date enddate)))))
(if (eq? infobox-display 'always)
(gnc:html-document-add-object!
document
(gnc:html-render-options-changed options)))
(if (and (opt-val gnc:pagename-display optname-grid)
(if (memq primary-key DATE-SORTING-TYPES)
(keylist-get-info date-subtotal-list primary-date-subtotal 'renderer-fn)
@ -2007,11 +2060,6 @@ be excluded from periodic reporting.")
(gnc:html-document-add-object!
document (grid->html-table grid list-of-rows list-of-cols))))
(if (eq? infobox-display 'always)
(gnc:html-document-add-object!
document
(gnc:html-render-options-changed options)))
(gnc:html-document-add-object! document table)))))
(gnc:report-finished)
@ -2029,7 +2077,13 @@ be excluded from periodic reporting.")
'name (_ "Reconciliation Report")
'report-guid "e45218c6d76f11e7b5ef0800277ef320"
'options-generator reconcile-report-options-generator
'renderer trep-renderer)
;; the renderer is the same as trep, however we're using a different split-date strategy.
;; we're comparing reconcile date for inclusion, and if split is unreconciled, include it anyway.
'renderer (lambda (rpt) (trep-renderer rpt
#:custom-calculated-cells reconcile-report-calculated-cells
#:split->date split->reconcile-date
#:split->date-include-false? #t
#:empty-report-message reconcile-report-instructions)))
;; Define the report.
(gnc:define-report