crap bad diffs file there, please disregard and use the attached.
A On Fri, 17 Feb 2006 16:33:43 -0800 Andrew Sackville-West <[EMAIL PROTECTED]> wrote: > Okay, the advanced portfolio report was broken in a number of ways. I've > masssaged it pretty well I think, but made some assumptions about how it > should behave. Essentially, there are three cases we encounter, listed below: > > 1). a normal, properly formed stock account with pricedb entries etc. In this > case, the report should work as expected, handling multiple currencies etc. I > do not use multiple currencies and don't really grok them so if someone could > test this properly, that would be great > > 2) a stock account with no shares in it. In this case, the report just spews > a bunch of zeros for the particular stock, as expected. It no longer crashes > which should solve Eildert's problem > > 3) a stock account with shares in it but with no pricedb entry. In this case, > I made the assumption that the file was broken. There should always be a > pricedb entry if there are any shares in an account, IMO. Probably the code > should be fixed so that any buy or sell or similar action automatically > creates a pricedb entry. Still we have to account for 1.8 files that might be > broken in this regard. phew. What it does: flags the particular stock as > being "dirty" and tries to make a reasonable guess at what the current value > and gain is based on data pulled from the actual transactions. I am not > convinced however that this data is properly exchanged across multiple > currencies. So the report spews what it can on this stock, but sticks a * in > the price column and places a warning at the bottom of the report explaining > the situation. Also, any stocks that don't have a pricedb entry are EXCLUDED > from the totals at the bottom of the report as the information is not > reliable. > > please give me feedback on this monster and my assumptions. I would like to > make it behave appropriately and I don't know if my assumptions are correct. > > thanks > > A >
Index: src/report/standard-reports/advanced-portfolio.scm
===================================================================
--- src/report/standard-reports/advanced-portfolio.scm (revision 13285)
+++ src/report/standard-reports/advanced-portfolio.scm (working copy)
@@ -46,6 +46,7 @@
(define optname-show-listing (N_ "Show listings"))
(define optname-show-price (N_ "Show prices"))
(define optname-show-shares (N_ "Show number of shares"))
+(define price-is-dirty #f) ;;keep track of whether we're using good price data
(define (options-generator)
(let* ((options (gnc:new-options))
@@ -151,7 +152,8 @@
(define (advanced-portfolio-renderer report-obj)
(let ((work-done 0)
- (work-to-do 0))
+ (work-to-do 0)
+ (warn-price-dirty #f))
;; These are some helper functions for looking up option values.
(define (get-op section name)
@@ -201,15 +203,23 @@
(moneyincoll (gnc:make-commodity-collector))
(moneyoutcoll (gnc:make-commodity-collector))
(gaincoll (gnc:make-commodity-collector))
+ (dirty-value (gnc:numeric-zero))
+ (dirty-amount (gnc:numeric-zero))
(price-list (price-fn commodity to-date))
(price (if (> (length price-list) 0)
(car price-list) #f))
- (commod-currency (gnc:price-get-currency price))
+ ;; if there is no price, set a sane commod-currency for those
zero-share
+ ;; accounts. if its a no price account with shares, we'll get
a currency later.
+ (commod-currency (if (not price) (gnc:price-get-currency
price) currency))
(value (exchange-fn (gnc:make-gnc-monetary commodity units)
currency))
+ ;;if we have shares but no price in pricedb, we'll make a
dirty price guess at things
+ (price-is-dirty (if (and (not price) (< 0
(gnc:numeric-to-double units))) #t #f))
)
+ (if price-is-dirty (set! warn-price-dirty #t))
+
;; (gnc:debug "---" name "---")
(for-each
(lambda (split)
@@ -217,47 +227,69 @@
(gnc:report-percent-done (* 100 (/ work-done work-to-do)))
(let ((parent (gnc:split-get-parent split)))
(if (gnc:timepair-le (gnc:transaction-get-date-posted parent)
to-date)
- (for-each
- (lambda (s)
- (cond
- ((same-split? s split)
+ (begin
+ (for-each
+ (lambda (s)
+ ;; if price-is dirty and this is an asset type
account for buy or sell, then grab a
+ ;; currency and a dirty-value for later computation
+ (if (and price-is-dirty (not (or (split-account-type?
s 'stock)
+ (split-account-type?
s 'mutualfund)
+ (split-account-type?
s 'expense)
+ (split-account-type?
s 'income))))
+ (begin
+ (set! commod-currency
(gnc:account-get-commodity (gnc:split-get-account s)))
+ (set! dirty-value (gnc:split-get-value s))
+ (if (gnc:numeric-negative-p dirty-value)
+ (set! dirty-value (gnc:numeric-sub
(gnc:numeric-zero) dirty-value
+ 10000
GNC-RND-ROUND)))))
+ )
+
+ (gnc:transaction-get-splits parent))
+
+ (for-each
+ (lambda (s)
+ (cond
+ ((same-split? s split)
;; (gnc:debug "amount " (gnc:numeric-to-double
(gnc:split-get-amount s))
;; " acct " (gnc:account-get-name
(gnc:split-get-account s)) )
;; (gnc:debug "value " (gnc:numeric-to-double
(gnc:split-get-value s))
;; " in " (gnc:commodity-get-printname
commod-currency)
;; " from " (gnc:transaction-get-description
(gnc:split-get-parent s)))
- (cond
- ((or include-gains (not (gnc:numeric-zero-p
(gnc:split-get-amount s))))
- (unitscoll 'add commodity (gnc:split-get-amount s))
;; Is the stock transaction?
- (if (< 0 (gnc:numeric-to-double
- (gnc:split-get-amount s)))
- (set! totalunits
- (+ totalunits
- (gnc:numeric-to-double
(gnc:split-get-amount s)))))
- (set! totalunityears
- (+ totalunityears
- (* (gnc:numeric-to-double
(gnc:split-get-amount s))
- (gnc:date-year-delta
- (car (gnc:transaction-get-date-posted
parent))
- (current-time)))))
- (cond
- ((gnc:numeric-negative-p (gnc:split-get-value s))
- (moneyoutcoll
- 'add commod-currency
- (gnc:numeric-neg (gnc:split-get-value s))))
- (else (moneyincoll
- 'add commod-currency
- (gnc:numeric-neg (gnc:split-get-value
s))))))))
+ (cond
+ ((or include-gains (not (gnc:numeric-zero-p
(gnc:split-get-amount s))))
+ (unitscoll 'add commodity (gnc:split-get-amount
s)) ;; Is the stock transaction?
+ (set! dirty-amount (gnc:split-get-amount s))
+ (if (< 0 (gnc:numeric-to-double
+ (gnc:split-get-amount s)))
+ (set! totalunits
+ (+ totalunits
+ (gnc:numeric-to-double
(gnc:split-get-amount s)))))
+
+ (set! totalunityears
+ (+ totalunityears
+ (* (gnc:numeric-to-double
(gnc:split-get-amount s))
+ (gnc:date-year-delta
+ (car
(gnc:transaction-get-date-posted parent))
+ (current-time)))))
+ (cond
+ ((gnc:numeric-negative-p (gnc:split-get-value s))
+ (moneyoutcoll
+ 'add commod-currency
+ (gnc:numeric-neg (gnc:split-get-value s))))
+ (else (moneyincoll
+ 'add commod-currency
+ (gnc:numeric-neg (gnc:split-get-value
s))))))))
- ((split-account-type? s 'expense)
- (brokeragecoll 'add commod-currency
(gnc:split-get-value s)))
-
- ((split-account-type? s 'income)
- (dividendcoll 'add commod-currency
(gnc:split-get-value s)))
- )
+ ((split-account-type? s 'expense)
+ (brokeragecoll 'add commod-currency
(gnc:split-get-value s)))
+
+ ((split-account-type? s 'income)
+ (dividendcoll 'add commod-currency
(gnc:split-get-value s)))
+ )
+ )
+ (gnc:transaction-get-splits parent)
)
- (gnc:transaction-get-splits parent)
- )
+ )
)
)
)
@@ -266,25 +298,41 @@
;; (gnc:debug "totalunits" totalunits)
;; (gnc:debug "totalunityears" totalunityears)
- (moneyincoll 'minusmerge dividendcoll #f)
+
+ (if price-is-dirty
+ (set! value (gnc:make-gnc-monetary commod-currency
+ (gnc:numeric-mul units
+
(gnc:numeric-div dirty-value
+
dirty-amount
+
10000 GNC-RND-ROUND)
+ 10000
GNC-RND-ROUND))))
+ (moneyincoll 'minusmerge dividendcoll #f)
(moneyoutcoll 'minusmerge brokeragecoll #f)
(gaincoll 'merge moneyoutcoll #f)
(gaincoll 'add (gnc:gnc-monetary-commodity value)
(gnc:gnc-monetary-amount value))
(gaincoll 'merge moneyincoll #f)
(if (or include-empty (not (gnc:numeric-zero-p units)))
- (let ((moneyin (gnc:monetary-neg
+ (let* ((moneyin (gnc:monetary-neg
(gnc:sum-collector-commodity moneyincoll currency
exchange-fn)))
(moneyout (gnc:sum-collector-commodity moneyoutcoll currency
exchange-fn))
- (gain (gnc:sum-collector-commodity gaincoll currency
exchange-fn))
+ (gain (if price-is-dirty
+ (gnc:make-gnc-monetary commod-currency
+ (gnc:numeric-sub
(gnc:gnc-monetary-amount value)
+
(gnc:gnc-monetary-amount moneyin)
+ 10000
GNC-RND-ROUND))
+ (gnc:sum-collector-commodity gaincoll currency
exchange-fn)))
(activecols (list (gnc:html-account-anchor current)))
)
- (total-value 'add (gnc:gnc-monetary-commodity value)
(gnc:gnc-monetary-amount value))
- (total-moneyin 'merge moneyincoll #f)
- (total-moneyout 'merge moneyoutcoll #f)
- (total-gain 'merge gaincoll #f)
+ (if (not price-is-dirty)
+ (begin
+ (total-value 'add (gnc:gnc-monetary-commodity value)
(gnc:gnc-monetary-amount value))
+ (total-moneyin 'merge moneyincoll #f)
+ (total-moneyout 'merge moneyoutcoll #f)
+ (total-gain 'merge gaincoll #f)))
+
;; build a list for the row based on user selections
(if show-symbol (append! activecols (list ticker-symbol)))
(if show-listing (append! activecols (list listing)))
@@ -298,14 +346,14 @@
(gnc:make-gnc-monetary
(gnc:price-get-currency price)
(gnc:price-get-value price)))
- #f)))))
+ (if price-is-dirty "*" #f))))))
(append! activecols (list (gnc:make-html-table-header-cell/markup
"number-cell" value)
(gnc:make-html-table-header-cell/markup
"number-cell"
- (gnc:monetary-neg
(gnc:sum-collector-commodity moneyincoll currency exchange-fn)))
+ moneyin)
(gnc:make-html-table-header-cell/markup
"number-cell"
- (gnc:sum-collector-commodity
moneyoutcoll currency exchange-fn))
+ moneyout)
(gnc:make-html-table-header-cell/markup
"number-cell"
- (gnc:sum-collector-commodity
gaincoll currency exchange-fn))
+ gain)
(gnc:make-html-table-header-cell/markup
"number-cell"
(let ((moneyinvalue
(gnc:numeric-to-double
(cadr
(moneyincoll 'getpair currency #t)))))
@@ -423,9 +471,9 @@
(table-add-stock-rows
table accounts to-date currency price-fn exchange-fn
- include-empty include-gains show-symbol show-listing show-shares
show-price
+ include-empty include-gains show-symbol show-listing show-shares
show-price
total-value total-moneyin total-moneyout total-gain)
-
+
(gnc:html-table-append-row/markup!
table
"grand-total"
@@ -459,10 +507,15 @@
table
"grand-total"
totalscols
- )
-
- (gnc:html-document-add-object! document table))
+ )
+ (gnc:html-document-add-object! document table)
+ (if warn-price-dirty
+ (gnc:html-document-append-objects! document
+ (list (gnc:make-html-text (_
"* no valid price data for this commodity. It has been exluded from totals
and<BR>"))
+ (gnc:make-html-text (_
"may not be properly exchanged. Please enter a price in the Price Editor.")))))
+)
+
;if no accounts selected.
(gnc:html-document-add-object!
document
pgpDyUEzwKWHR.pgp
Description: PGP signature
_______________________________________________ gnucash-devel mailing list [email protected] https://lists.gnucash.org/mailman/listinfo/gnucash-devel
