New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Category charts upgrade to chart allocation ratios instead of absolute values. #1272
Changes from 3 commits
db3bd37
e82ecab
0074307
4e950e6
9df126b
b93d2b2
c05a26e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,12 @@ | |
(use-modules (gnucash app-utils)) | ||
(use-modules (gnucash report)) | ||
|
||
;; useful functions | ||
(define (safe-/ x y) | ||
(if (and (zero? x) (zero? y)) 0 (/ x y))) | ||
(define (l1norm . numbers) | ||
(fold (lambda (a b) (+ (abs a) b)) 0 numbers)) | ||
|
||
;; The option names are defined here to 1. save typing and 2. avoid | ||
;; spelling errors. The *reportnames* are defined here (and not only | ||
;; once at the very end) because I need them to define the "other" | ||
|
@@ -175,6 +181,13 @@ developing over time")) | |
(N_ "Show table") | ||
"e" (N_ "Display a table of the selected data.") | ||
#f)) | ||
|
||
(add-option | ||
(gnc:make-simple-boolean-option | ||
gnc:pagename-display | ||
(N_ "Replace amounts with percentage ratios.") | ||
"e1" (N_ "Display percentage contribution of each account to the Gand Total instead of amounts.") | ||
#f)) | ||
|
||
(gnc:options-add-plot-size! | ||
options gnc:pagename-display | ||
|
@@ -246,6 +259,7 @@ developing over time")) | |
(work-to-do 0) | ||
(all-data #f) | ||
(show-table? (get-option gnc:pagename-display (N_ "Show table"))) | ||
(ratio-chart? (get-option gnc:pagename-display (N_ "Replace amounts with percentage ratios."))) | ||
(document (gnc:make-html-document)) | ||
(chart (gnc:make-html-chart)) | ||
(topl-accounts (gnc:filter-accountlist-type | ||
|
@@ -494,7 +508,10 @@ developing over time")) | |
(let* ((dates-list (if do-intervals? | ||
(list-head dates-list (1- (length dates-list))) | ||
dates-list)) | ||
(date-string-list (map qof-print-date dates-list))) | ||
(date-string-list (map qof-print-date dates-list)) | ||
|
||
; total amount with l1norm, so that assest and debts add up | ||
(grandts (map (lambda (row) (apply l1norm (map gnc:gnc-monetary-amount row))) (apply zip (map cadr all-data))))) | ||
christopherlam marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
;; Set chart title, subtitle etc. | ||
(gnc:html-chart-set-type! | ||
|
@@ -514,7 +531,7 @@ developing over time")) | |
|
||
(gnc:html-chart-set-data-labels! chart date-string-list) | ||
(gnc:html-chart-set-y-axis-label! | ||
chart (gnc-commodity-get-mnemonic report-currency)) | ||
chart (if ratio-chart? "Ratio" (gnc-commodity-get-mnemonic report-currency))) | ||
|
||
;; If we have too many categories, we sum them into a new | ||
;; 'other' category and add a link to a new report with just | ||
|
@@ -552,6 +569,7 @@ developing over time")) | |
(show-fullname? (gnc-account-get-full-name acct)) | ||
(else (xaccAccountGetName acct)))) | ||
(amounts (map gnc:gnc-monetary-amount (cadr series))) | ||
(percentage (map (lambda (x grandt) (safe-/ x grandt)) amounts grandts)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line is ok for readability, but because
|
||
(stack (if stacked? "default" (number->string stack))) | ||
(fill (eq? chart-type 'barchart)) | ||
(urls (cond | ||
|
@@ -578,7 +596,7 @@ developing over time")) | |
(gnc-account-get-full-name acct) | ||
(xaccAccountGetName acct))))))))) | ||
(gnc:html-chart-add-data-series! | ||
chart label amounts color | ||
chart label (if ratio-chart? percentage amounts) color | ||
'stack stack 'fill fill 'urls urls))) | ||
all-data | ||
(gnc:assign-colors (length all-data)) | ||
|
@@ -589,6 +607,8 @@ developing over time")) | |
chart (gnc-commodity-get-mnemonic report-currency)) | ||
(gnc:html-chart-set-currency-symbol! | ||
chart (gnc-commodity-get-nice-symbol report-currency)) | ||
(gnc:html-chart-set-format-style! | ||
chart (if ratio-chart? "percent" "currency")) | ||
|
||
(gnc:report-percent-done 98) | ||
(gnc:html-document-add-object! document chart) | ||
|
@@ -600,17 +620,23 @@ developing over time")) | |
|
||
(define (make-cell contents) | ||
(gnc:make-html-table-cell/markup "number-cell" contents)) | ||
|
||
(define (make-cell-percent contents) | ||
(gnc:make-html-table-cell/markup "number-cell" contents " %")) | ||
|
||
(for-each | ||
(lambda (date row) | ||
(gnc:html-table-append-row! | ||
table | ||
(append (list (make-cell date)) | ||
(map make-cell row) | ||
(if cols>1? | ||
(list | ||
(make-cell (apply gnc:monetary+ row))) | ||
'())))) | ||
(let ((grandt (apply l1norm (map gnc:gnc-monetary-amount row)))) | ||
(append (list (make-cell date)) | ||
(if ratio-chart? | ||
(map (lambda (x) (make-cell-percent (* (safe-/ (gnc:gnc-monetary-amount x) grandt) 100))) row) | ||
(map make-cell row)) | ||
(if cols>1? | ||
(list | ||
(make-cell (apply gnc:monetary+ row))) | ||
'()))))) | ||
date-string-list | ||
(apply zip (map cadr all-data))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of recreating grandt for each row, it'll be much more clever to reuse the (for-each
(lambda (date row grandt)
(gnc:html-table-append-row! ...etc...and use grandt now available for use))
date-string-list
(apply zip (map cadr all-data))
grandts) |
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure both x and y being 0 is the only div/0? What if the assets have only two accounts: cash $400 and loan -$400?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the part where the abs value will make y 800. In this case it makes no difference. Since if x=0, y will also always be 0. We can also stick with
(if (zero? y) 0 (/ x y)))
. I just added the check for x, because for x not 0, a divide by 0 error in this case would show that something is wrong.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is nothing in this function definition that guarantees this so your statement must be based on how this function is used. That's slightly risky because that opens doors to mistakes in future changes of the code.
The added check adds nothing. The function will return 0 in both implementations so there's no way your calling code can tell the difference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is true, only in my use case if y=0, also x will be 0.
Sorry, that was is mistake. In my usecase: y=abs(x_1)+...+abs(x_N). So if y=0, all x must have been 0.
Consider the case y=0, x=1.
(if (zero? y) 0 (/ x y)))
will return 0(if (and (zero? x) (zero? y)) 0 (/ x y)))
will fail due to division by 0: (/ 1 0).In my implementation the case y=0, x=1 can't happen. So if it still occurs, something is wrong and the report will fail.