gnucash stable: Multiple changes pushed
Christopher Lam
clam at code.gnucash.org
Sat May 10 02:33:52 EDT 2025
Updated via https://github.com/Gnucash/gnucash/commit/ff759c26 (commit)
via https://github.com/Gnucash/gnucash/commit/c01cccbd (commit)
from https://github.com/Gnucash/gnucash/commit/b219744d (commit)
commit ff759c26bcebef18f0327d3eef80a21d0d20e252
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Sun Apr 20 23:21:13 2025 +0800
[engine.i] convert gnc_account_accumulate_at_dates to c++
traversal of account->splits through std::vector instead of scm_list
diff --git a/bindings/engine.i b/bindings/engine.i
index 4b7adbafe7..bdc4d1abac 100644
--- a/bindings/engine.i
+++ b/bindings/engine.i
@@ -66,6 +66,22 @@ using AccountVec = std::vector<Account*>;
SplitsVec gnc_get_match_commodity_splits (AccountVec accounts, bool use_end_date,
time64 end_date, gnc_commodity *comm, bool sort);
+/* scans account splits, in posted date order, calling split_fn(split)
+ at each split and accumulate the result at each date in the SCM
+ list dates into a new SCM list. Parameters are:
+
+ acc the account
+ dates the SCM list of posted dates, assumed to be in chronological order
+ init the result to be pushed into the result for dates prior to first split date
+ split_fn the split->elt procedure whose result of (split_fn split) will be pushed
+ into the returned SCM list */
+SCM gnc_account_accumulate_to_dates (const Account *acc, SCM dates,
+ SCM split_fn, SCM init);
+
+/* as above, but the split_to_date function to use a different date order. */
+SCM gnc_account_accumulate_to_dates (const Account *acc, SCM dates,
+ SCM split_fn, SCM init, SCM split_to_date);
+
AccountVec gnc_accounts_and_all_descendants (AccountVec accounts);
extern "C"
@@ -160,6 +176,51 @@ SplitsVec gnc_get_match_commodity_splits (AccountVec accounts, bool use_end_date
return rv;
}
+static SCM
+accumulate_splits_by_dates (const SplitsVec& splits, SCM dates, SCM result,
+ std::function<bool(Split*,SCM)> no_later_than_date,
+ std::function<SCM(Split*)> get_result)
+{
+ SCM rv = SCM_EOL;
+ auto splits_it = splits.begin();
+ for (; !scm_is_null(dates); dates = scm_cdr (dates))
+ {
+ while (splits_it != splits.end() && no_later_than_date (*splits_it, scm_car (dates)))
+ result = get_result (*splits_it++);
+
+ rv = scm_cons (result, rv);
+ }
+ return scm_reverse_x (rv, SCM_EOL);
+}
+
+SCM
+gnc_account_accumulate_to_dates (const Account *acc, SCM dates,
+ SCM split_fn, SCM init)
+{
+ const auto& splits = xaccAccountGetSplits(acc);
+ auto get_result = [&](Split* s) -> SCM { return scm_call_1(split_fn, gnc_split_to_scm(s)); };
+ auto no_later_than_date = [&](Split* s, SCM date) -> bool
+ { return xaccTransGetDate (xaccSplitGetParent (s)) <= scm_to_int64 (date); };
+
+ return accumulate_splits_by_dates (splits, dates, init, no_later_than_date, get_result);
+}
+
+SCM
+gnc_account_accumulate_to_dates (const Account *acc, SCM dates,
+ SCM split_fn, SCM init, SCM split_to_date)
+{
+ auto splits = xaccAccountGetSplits(acc);
+ auto less_scm = [](SCM a, SCM b) -> bool { return scm_is_true(scm_less_p(a, b)); };
+ auto get_date = [&](Split* s) -> SCM { return scm_call_1(split_to_date, gnc_split_to_scm(s)); };
+ auto get_result = [&](Split* s) -> SCM { return scm_call_1(split_fn, gnc_split_to_scm(s)); };
+ auto no_later_than_date = [&](auto s, SCM date) -> bool { return !less_scm(date, get_date(s)); };
+ std::sort(splits.begin(), splits.end(), [&](auto a, auto b) -> bool
+ { return less_scm(get_date(a), get_date(b)); });
+
+ return accumulate_splits_by_dates (splits, dates, init, no_later_than_date, get_result);
+}
+
+
using AccountSet = std::unordered_set<Account*>;
static void maybe_add_descendants (Account* acc, AccountSet* accset)
{
diff --git a/gnucash/report/report-utilities.scm b/gnucash/report/report-utilities.scm
index a1b90ff5e5..7a39221f59 100644
--- a/gnucash/report/report-utilities.scm
+++ b/gnucash/report/report-utilities.scm
@@ -476,41 +476,9 @@
(nosplit->elt #f)
(split->date #f)
(split->elt xaccSplitGetBalance))
- (define to-date (or split->date (compose xaccTransGetDate xaccSplitGetParent)))
- (define (less? a b) (< (to-date a) (to-date b)))
-
- (let lp ((splits (if split->date
- (sort (xaccAccountGetSplits acc) less?)
- (xaccAccountGetSplits acc)))
- (dates (sort dates <))
- (result '())
- (last-result nosplit->elt))
- (match dates
-
- ;; end of dates. job done!
- (() (reverse result))
-
- ((date . rest)
- (define (before-date? s) (<= (to-date s) date))
- (define (after-date? s) (< date (to-date s)))
- (cond
-
- ;; end of splits, but still has dates. pad with last-result
- ;; until end of dates.
- ((null? splits) (lp '() rest (cons last-result result) last-result))
-
- ;; the next split is still before date.
- ((and (pair? (cdr splits)) (before-date? (cadr splits)))
- (lp (cdr splits) dates result (split->elt (car splits))))
-
- ;; head split after date, accumulate previous result
- ((after-date? (car splits))
- (lp splits rest (cons last-result result) last-result))
-
- ;; head split before date, next split after date, or end.
- (else
- (let ((head-result (split->elt (car splits))))
- (lp (cdr splits) rest (cons head-result result) head-result))))))))
+ (if split->date
+ (gnc-account-accumulate-to-dates acc dates split->elt nosplit->elt split->date)
+ (gnc-account-accumulate-to-dates acc dates split->elt nosplit->elt)))
;; This works similar as above but returns a commodity-collector,
;; thus takes care of children accounts with different currencies.
commit c01cccbddc6049632ccfcc254c32cc419e3b40fb
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Sun Apr 20 23:20:54 2025 +0800
[gnc-engine-guile.cpp] helper gnc_split_to_scm function
diff --git a/bindings/guile/gnc-engine-guile.cpp b/bindings/guile/gnc-engine-guile.cpp
index fd6426d1bc..2c3f5be575 100644
--- a/bindings/guile/gnc-engine-guile.cpp
+++ b/bindings/guile/gnc-engine-guile.cpp
@@ -1781,6 +1781,13 @@ gnc_book_to_scm (const QofBook *book)
return gnc_generic_to_scm (book, stype);
}
+SCM
+gnc_split_to_scm (const Split *split)
+{
+ static auto stype = get_swig_type ("_p_Split");
+ return gnc_generic_to_scm (split, stype);
+}
+
GncAccountValue * gnc_scm_to_account_value_ptr (SCM valuearg)
{
GncAccountValue *res;
diff --git a/bindings/guile/gnc-engine-guile.h b/bindings/guile/gnc-engine-guile.h
index 2795e8e287..07687928d6 100644
--- a/bindings/guile/gnc-engine-guile.h
+++ b/bindings/guile/gnc-engine-guile.h
@@ -66,6 +66,8 @@ SCM gnc_commodity_to_scm(const gnc_commodity* commodity);
SCM gnc_book_to_scm(const QofBook* book);
+SCM gnc_split_to_scm (const Split *split);
+
/* Conversion routines used with tax tables */
GncAccountValue* gnc_scm_to_account_value_ptr(SCM valuearg);
Summary of changes:
bindings/engine.i | 61 +++++++++++++++++++++++++++++++++++++
bindings/guile/gnc-engine-guile.cpp | 7 +++++
bindings/guile/gnc-engine-guile.h | 2 ++
gnucash/report/report-utilities.scm | 38 ++---------------------
4 files changed, 73 insertions(+), 35 deletions(-)
More information about the gnucash-changes
mailing list