[balsheet-pnl] accumulate column data report-dates

Previous would call gnc:account-get-balances-at-dates and
gnc:account-accumulate-at-dates to retrieve balances and
last-split. This commit reduces the O(2*N) operation to O(N) which
becomes significant with accounts with large number of splits.

Maybe we can reduce other account splitlist scans in the future; these
will be easier and would only require augmenting the record.
This commit is contained in:
Christopher Lam 2019-11-24 21:38:42 +08:00
parent a261c8aadb
commit d6a5c8ba54

View File

@ -31,9 +31,18 @@
(use-modules (gnucash gettext))
(use-modules (srfi srfi-1))
(use-modules (srfi srfi-2))
(use-modules (srfi srfi-9))
(gnc:module-load "gnucash/report/report-system" 0)
;; the column-data record. the gnc:account-accumulate-at-dates will
;; create a record for each report-date with split-data as follows:
(define-record-type :col-datum
(make-datum last-split split-balance)
col-datum?
(last-split col-datum-get-last-split)
(split-balance col-datum-get-split-balance))
(define FOOTER-TEXT
(gnc:make-html-text
(_ "WARNING: Foreign currency conversions, and unrealized gains
@ -770,12 +779,31 @@ also show overall period profit & loss."))
((eq? report-type 'pnl) (list startdate enddate))
(else (list enddate))))
(accounts-balances (map
(lambda (acc)
(cons acc
(gnc:account-get-balances-at-dates
acc report-dates)))
accounts))
;; an alist of (cons account account-cols-data) whereby
;; account-cols-data is a list of col-datum records
(accounts-cols-data
(map
(lambda (acc)
(let* ((comm (xaccAccountGetCommodity acc))
(amt->monetary (lambda (amt) (gnc:make-gnc-monetary comm amt))))
(cons acc
(gnc:account-accumulate-at-dates
acc report-dates
#:nosplit->elt (make-datum #f (amt->monetary 0))
#:split->elt
(lambda (s)
(make-datum s (amt->monetary (xaccSplitGetBalance s))))))))
accounts))
;; an alist of (cons account account-balances) whereby
;; account-balances is a list of monetary amounts
(accounts-balances
(map
(lambda (acc)
(cons acc (let ((cols-data (assoc-ref accounts-cols-data acc)))
(map col-datum-get-split-balance cols-data))))
accounts))
(exchange-fn (and common-currency
(gnc:case-exchange-time-fn
price-source common-currency
@ -906,13 +934,14 @@ also show overall period profit & loss."))
(and account-balance-list
(list-ref account-balance-list col-idx)))))
;; an alist of account->last-split at date boundary
;; an alist of (cons account vector-of-splits) where each
;; split is the last one at date boundary
(accounts-splits-dates
(map
(lambda (acc)
(cons acc (list->vector
(gnc:account-accumulate-at-dates
acc report-dates #:split->elt identity))))
(cons acc (let ((cols-data (assoc-ref accounts-cols-data acc)))
(list->vector
(map col-datum-get-last-split cols-data)))))
accounts))
(get-cell-anchor-fn