r16663 - gnucash/branches/2.2/src/report/standard-reports - [r16620, r16632, r16631] Merge advanced portfolio fixes up to r16631.

Andreas Köhler andi5 at cvs.gnucash.org
Sun Dec 16 07:14:11 EST 2007


Author: andi5
Date: 2007-12-16 07:14:11 -0500 (Sun, 16 Dec 2007)
New Revision: 16663
Trac: http://svn.gnucash.org/trac/changeset/16663

Modified:
   gnucash/branches/2.2/src/report/standard-reports/advanced-portfolio.scm
Log:
[r16620,r16632,r16631] Merge advanced portfolio fixes up to r16631.

Create a branch for advanced portfolio work
Begin major overhaul to advanced-portfolio report. Fixes #343245,
#347739, #460232. Implement stock splits/mergers code in basis
calculations. Fix handling of directly "expensed" shares.

Remove some cruft from advanced portfolio.

Reintroduce some rounding into basis calculations to prevent overflow on
particularly large accounts.


Modified: gnucash/branches/2.2/src/report/standard-reports/advanced-portfolio.scm
===================================================================
--- gnucash/branches/2.2/src/report/standard-reports/advanced-portfolio.scm	2007-12-16 02:30:54 UTC (rev 16662)
+++ gnucash/branches/2.2/src/report/standard-reports/advanced-portfolio.scm	2007-12-16 12:14:11 UTC (rev 16663)
@@ -41,7 +41,6 @@
 (define optname-price-source (N_ "Price Source"))
 (define optname-shares-digits (N_ "Share decimal places"))
 (define optname-zero-shares (N_ "Include accounts with no shares"))
-(define optname-include-gains (N_ "Include gains and losses"))
 (define optname-show-symbol (N_ "Show ticker symbols"))
 (define optname-show-listing (N_ "Show listings"))
 (define optname-show-price (N_ "Show prices"))
@@ -102,14 +101,6 @@
       (N_ "Prefer use of price editor pricing over transactions, where applicable.")
       #t))
 
-
-    (gnc:register-option 
-     options 
-     (gnc:make-simple-boolean-option
-      gnc:pagename-general optname-include-gains "g" 
-      (N_ "Include splits with no shares for calculating money-in and money-out")
-      #f))
-
     (gnc:register-option
       options
       (gnc:make-simple-boolean-option
@@ -191,39 +182,65 @@
     (eq? type (xaccAccountGetType (xaccSplitGetAccount split))))
 
   (define (same-split? s1 s2)
-    (string=? (gncSplitGetGUID s1) (gncSplitGetGUID s2)))
+    (equal? (gncSplitGetGUID s1) (gncSplitGetGUID s2)))
 
   (define (same-account? a1 a2)
-    (string=? (gncAccountGetGUID a1) (gncAccountGetGUID a2)))
+    (equal? (gncAccountGetGUID a1) (gncAccountGetGUID a2)))
+
+  ;; sum up the contents of the b-list built by basis-builder below
+  (define (sum-basis b-list)
+    (if (not (eqv? b-list '()))
+	(gnc-numeric-add (gnc-numeric-mul (caar b-list) (cdar b-list) 100 GNC-RND-ROUND)
+			 (sum-basis (cdr b-list)) 100 GNC-RND-ROUND)
+	(gnc-numeric-zero)
+	)
+    )
   
+  ;; sum up the total number of units in the b-list built by basis-builder below
+  (define (units-basis b-list)
+    (if (not (eqv? b-list '()))
+	(gnc-numeric-add (caar b-list) (units-basis (cdr b-list)) 
+			 100 (logior GNC-DENOM-REDUCE GNC-RND-NEVER))
+	(gnc-numeric-zero)
+	)
+    )
+  
   ;; this builds a list for basis calculation and handles average, fifo and filo methods
   ;; the list is cons cells of (units-of-stock . price-per-unit)... average method produces only one
   ;; cell that mutates to the new average. Need to add a date checker so that we allow for prices
   ;; coming in out of order, such as a transfer with a price adjusted to carryover the basis.
+  ;; 
+  ;; FIXME!! need to implement handling of zero for b-units coming in to handle spinoffs. 
   (define (basis-builder b-list b-units b-value b-method)
+    (gnc:debug "actually in basis-builder")
+    (gnc:debug "b-list is " b-list " b-units is " b-units " b-value is " b-value " b-method is " b-method)
+
+    ;; if there is no b-value, then this is a split/merger and needs special handling
+    ;; FIX ME!! make a (cond (splits/merger) (spin-off) (regular basis adjustment))
+    (if (not (gnc-numeric-zero-p b-value))
+
+	;; nope, its normal, just adjust the basis
     (if (gnc-numeric-positive-p b-units)
 	(case b-method
 	  ((average-basis) 
            (if (not (eqv? b-list '()))
                (list (cons (gnc-numeric-add b-units
-                                            (caar b-list) 10000 GNC-RND-ROUND) 
+						(caar b-list) 10000 GNC-RND-ROUND) 
                            (gnc-numeric-div
                             (gnc-numeric-add b-value
                                              (gnc-numeric-mul (caar b-list)
                                                               (cdar b-list) 
-                                                              10000 GNC-RND-ROUND)
-                                             10000 GNC-RND-ROUND)
+								  10000 GNC-RND-ROUND)
+						 10000 GNC-RND-ROUND)
                             (gnc-numeric-add b-units
-                                             (caar b-list) 10000 GNC-RND-ROUND)
-                            10000 GNC-RND-ROUND)))
+						 (caar b-list) 10000 GNC-RND-ROUND)
+				10000 GNC-RND-ROUND)))
                (append b-list 
                        (list (cons b-units (gnc-numeric-div
-                                            b-value b-units 10000 
-                                            GNC-RND-ROUND))))))
+						b-value b-units 10000 GNC-RND-ROUND))))))
 	  (else (append b-list 
                         (list (cons b-units (gnc-numeric-div
-                                             b-value b-units 10000 
-                                             GNC-RND-ROUND))))))
+						 b-value b-units 10000 GNC-RND-ROUND))))))
 	(if (not (eqv? b-list '()))
 	    (case b-method
 	      ((fifo-basis) 
@@ -231,11 +248,11 @@
                                (gnc-numeric-abs b-units) (caar b-list))))
                    (basis-builder (cdr b-list) (gnc-numeric-add
                                                 b-units 
-                                                (caar b-list) 10000 GNC-RND-ROUND) 
+						    (caar b-list) 10000 GNC-RND-ROUND) 
                                   b-value b-method)
                    (append (list (cons (gnc-numeric-add
                                         b-units 
-                                        (caar b-list) 10000 GNC-RND-ROUND) 
+					    (caar b-list) 10000 GNC-RND-ROUND) 
                                        (cdar b-list))) (cdr b-list))))
 	      ((filo-basis) 
                (if (not (= -1 (gnc-numeric-compare
@@ -244,45 +261,49 @@
                                   (gnc-numeric-add
                                    b-units 
                                    (caar (reverse b-list)) 
-                                   10000 GNC-RND-ROUND) 
+				       10000 GNC-RND-ROUND) 
                                   b-value b-method)
                    (append (cdr (reverse b-list)) 
                            (list (cons (gnc-numeric-add
                                         b-units 
-                                        (caar (reverse b-list)) 10000 GNC-RND-ROUND) 
+					    (caar (reverse b-list)) 10000 GNC-RND-ROUND) 
                                        (cdar (reverse b-list)))))))
 	      ((average-basis) 
                (list (cons (gnc-numeric-add
-                            (caar b-list) b-units 10000 GNC-RND-ROUND) 
+				(caar b-list) b-units 10000 GNC-RND-ROUND) 
                            (cdar b-list)))))
 	    '()
 	    )
 	)
+	;; this is a split/merge...
+	(let* ((current-units (units-basis b-list))
+	       (units-ratio (gnc-numeric-div current-units 
+					     (gnc-numeric-add b-units current-units 10000 GNC-RND-ROUND) 
+					     10000 GNC-RND-ROUND)))
+	  
+	  (define (apply-ratio blist ratio)
+	    (if (not (eqv? blist '()))
+		(cons (cons (gnc-numeric-div (caar blist) ratio 10000 GNC-RND-ROUND) 
+			    (gnc-numeric-mul ratio (cdar blist) 10000 GNC-RND-ROUND)) 
+		      (apply-ratio (cdr blist) ratio ))
+		'()
     )
-
-  ;; sum up the contents of the b-list built by basis-builder above
-  (define (sum-basis b-list)
-    (if (not (eqv? b-list '()))
-	(gnc-numeric-add (gnc-numeric-mul (caar b-list) (cdar b-list) 100 GNC-RND-ROUND)
-			 (sum-basis (cdr b-list)) 100 GNC-RND-ROUND)
-	(gnc-numeric-zero)
 	)
+	  (gnc:debug "blist is " b-list " units ratio is " units-ratio)
+	  (apply-ratio b-list units-ratio) 
     )
-  
-  ;; sum up the total number of units in the b-list built by basis-builder above
-  (define (units-basis b-list)
-    (if (not (eqv? b-list '()))
-	(gnc-numeric-add (caar b-list) (units-basis (cdr b-list)) 100 GNC-RND-ROUND)
-	(gnc-numeric-zero)
+
+	;; FIXME!!! If there are no units, just a value, then its a spin-off, must
+	;; reduce the *values* but not the number of units held
 	)
     )
 
   
 (define (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 show-symbol show-listing show-shares show-price
                                 basis-method prefer-pricelist total-basis total-value total-moneyin total-moneyout
-                                total-gain total-ugain)
+                                total-gain total-ugain total-brokerage)
 
    (let ((share-print-info
 	  (gnc-share-print-info-places
@@ -294,15 +315,13 @@
           (let* ((row-style (if odd-row? "normal-row" "alternate-row"))
                  (current (car accounts))
                  (rest (cdr accounts))
-                 (name (xaccAccountGetName current))
+		 ;; commodity is the actual stock/thing we are looking at
                  (commodity (xaccAccountGetCommodity current))
                  (ticker-symbol (gnc-commodity-get-mnemonic commodity))
                  (listing (gnc-commodity-get-namespace commodity))
                  (unit-collector (gnc:account-get-comm-balance-at-date
                                   current to-date #f))
                  (units (cadr (unit-collector 'getpair commodity #f)))
-;;                 (totalunits 0.0) ;;      these two items do nothing, but are in a debug below, 
- ;;                (totalunityears 0.0);;   so I'm leaving it. asw
 
                  ;; Counter to keep track of stuff
                  (unitscoll     (gnc:make-commodity-collector))
@@ -314,11 +333,21 @@
 
 
                  (price-list (price-fn commodity to-date))
+		 ;; the price of the commodity at the time of the report
                  (price      (if (> (length price-list) 0)
 				 (car price-list) #f))
-		 ;; 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.
+		 ;; 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.
+		 ;; the currency in which the transaction takes place,
+		 ;; for example IBM shares are the commodity, purchsed
+		 ;; with US dollars. In this case, commod-currency
+		 ;; would be US dollars. If there is no price, we
+		 ;; arbitrarily set the commod-currency to the same as
+		 ;; that of the report, currency
 		 (commod-currency (if price (gnc-price-get-currency price) currency))
+		 ;; the value of the commodity, expressed in terms of
+		 ;; the report's currency.
                  (value (exchange-fn (gnc:make-gnc-monetary commodity units) currency))
 
 		 (txn-value (gnc-numeric-zero))
@@ -327,96 +356,155 @@
 		 (use-txn #f)
 		 (basis-list '())
 		 (txn-units (gnc-numeric-zero))
+		 ;; setup an alist for the splits we've already seen.
+		 (seen_split '())
 		 )
 
-
-;;          (gnc:debug "---" name "---")
 	    (for-each
+	     ;; we're looking at each split we find in the account. these splits
+	     ;; could refer to the same transaction, so we have to examine each
+	     ;; split, determine what kind of split it is and then act accordingly.
 	     (lambda (split)
 	       (set! work-done (+ 1 work-done))
 	       (gnc:report-percent-done (* 100 (/ work-done work-to-do)))
-	       (let ((parent (xaccSplitGetParent split)))
-		 (if (gnc:timepair-le (gnc-transaction-get-date-posted parent) to-date)
-		     (begin
+	       
+	       (let* ((parent (xaccSplitGetParent split))
+		      (txn-date (gnc-transaction-get-date-posted parent)))
+		 
+		 ;; we must have a good commod-currency before we go any
+		 ;; farther as the rest relies on it. If we don't have a
+		 ;; price, then we need to make one from somewhere and
+		 ;; grab its commod-currency as well.
+		 (if (not price)
 		       (for-each
 			(lambda (s)
-			  ;; If this is an asset type account for buy or sell, then grab a 
-			  ;; currency and a txn-value for later computation
-			  (cond
-			   ((and (not (same-account? current (xaccSplitGetAccount s)))
-				 (not (or (split-account-type?
-                                           s ACCT-TYPE-EXPENSE)
-					  (split-account-type?
-                                           s ACCT-TYPE-INCOME))))
-
-			    ;;only change the commod-currency if price failed
-			    (if (not price) (set! commod-currency (xaccAccountGetCommodity (xaccSplitGetAccount s))))
-			    (set! txn-value (gnc-numeric-abs (xaccSplitGetValue s)));;FIXME use xaccSplitGetSharePrice
-			    (set! txn-date (gnc-transaction-get-date-posted parent))
-			    (set! pricing-txn parent)
+			(if (and (not (or (split-account-type? s ACCT-TYPE-EXPENSE)
+					  (split-account-type? s ACCT-TYPE-INCOME)
+					  (split-account-type? s ACCT-TYPE-ROOT)))
+				 (not (same-account? current (xaccSplitGetAccount s))))
+			    (begin
+			      ;; we're using a transaction to get the price, so we have to set some stuff
+			      (set! commod-currency (xaccAccountGetCommodity (xaccSplitGetAccount s)))
+			      (set! pricing-txn (xaccSplitGetParent s))
+			      (gnc:debug "pricing txn is " pricing-txn)
 			    )
-			   ((same-account? current (xaccSplitGetAccount s))
-			    (set! txn-units (xaccSplitGetAmount s)))
-			    
 			      )
+			) 
+		      (xaccTransGetSplitList parent)) 
 			  )
 
-			(xaccTransGetSplitList parent))
+		 (if (gnc:timepair-le txn-date to-date)
+		     (begin
+		       ;; here's where we have problems. we are now going to look at each
+		       ;; split of the the parent txn of the current split (above) that we
+		       ;; are on. This means we might hit each split more than once as the
+		       ;; parent transaction might touch the current account more than once.
+		       (for-each
+			(lambda (s)
 
+			  ;; have we seen this split?
+			  (if (not (assoc-ref seen_split (gncSplitGetGUID s)))
 
-		       ;; go build the basis-list
-		       ;; the use of exchange-fn here is an attempt to get the basis list into one
-		       ;; currency to help accomodate stock transfers and other things. might not work.
-		       (set! basis-list (basis-builder basis-list txn-units (gnc:gnc-monetary-amount
-									     (exchange-fn (gnc:make-gnc-monetary 
-											   commod-currency txn-value) 
-											  currency)) basis-method))
+			      (let
+				  ;; get the split's units and value
+				  ((split-units (xaccSplitGetAmount s))
+				   (split-value (xaccSplitGetValue s)))
 
-		       (for-each
-			(lambda (s)
+				;; first add this split to the seen_split list so we only look at it once.
+				(set! seen_split (acons (gncSplitGetGUID s) #t seen_split))
+
+				(gnc:debug "split units " split-units " split-value " split-value " commod-currency " commod-currency)
+
+				;; now we look at what type of split this is and process accordingly
 			  (cond
-			   ((same-split? s split) 
-;;                       (gnc:debug "amount " (gnc-numeric-to-double (xaccSplitGetAmount s))
-;;                                  " acct " (xaccAccountGetName (xaccSplitGetAccount s)) )
-;;                       (gnc:debug "value " (gnc-numeric-to-double (xaccSplitGetValue s))
-;;                                  " in " (gnc-commodity-get-printname commod-currency)
-;;                                  " from " (xaccTransGetDescription (xaccSplitGetParent s)))
-			    (cond
-			     ((or include-gains (not (gnc-numeric-zero-p (xaccSplitGetAmount s))))
-			      (unitscoll 'add commodity (xaccSplitGetAmount s)) ;; Is the stock transaction?
-;; these lines do nothing, but are in a debug so I'm leaving it, just in case. asw.			     
-;;			      (if (< 0 (gnc-numeric-to-double
-;;					(xaccSplitGetAmount s)))
 
+				 ;; in theory, the only expenses are
+				 ;; brokerage fees. Not true, you can
+				 ;; have expenses for "donating"
+				 ;; shares to a charity, for
+				 ;; example. In this case, there will
+				 ;; be *only* two
+				 ;; splits. xaccSplitGetOtherSplit
+				 ;; returns null for a
+				 ;; more-than-two-splits txn
+				 ((split-account-type? s ACCT-TYPE-EXPENSE)
+				  (if (equal? current (xaccSplitGetAccount (xaccSplitGetOtherSplit s)))
+				      ;; "donated shares"
+				      (moneyoutcoll 'add commod-currency split-value)
+				      ;; brokerage fees
+				      (brokeragecoll 'add commod-currency split-value)))
 
-;;				  (set! totalunits
-;;					(+ totalunits
-;;					   (gnc-numeric-to-double (xaccSplitGetAmount s))))
-;;				  )
+				 ;; in theory, income is a dividend of
+				 ;; some kind. it could also be
+				 ;; gains. that gets handled later. it
+				 ;; could also be direct income into
+				 ;; shares, say from an employer into
+				 ;; a retirement account. basically,
+				 ;; there is nothing that can be done
+				 ;; with these to differentiate them
+				 ;; :(
+				 ((split-account-type? s ACCT-TYPE-INCOME)
+				  (dividendcoll 'add commod-currency split-value))
 
+				 ;; we have units, handle all cases of that
+				 ((not (gnc-numeric-zero-p split-units))
+				  (begin
+				    
+				    (gnc:debug "going in to basis list " basis-list split-units split-value)
 
-;;			      (set! totalunityears
-;;				    (+ totalunityears 
-;;				       (* (gnc-numeric-to-double (xaccSplitGetAmount s))
-;;					  (gnc:date-year-delta 
-;;					   (car (gnc-transaction-get-date-posted parent))
-;;					   (current-time))))) 
-			      (cond 
-			       ((gnc-numeric-negative-p (xaccSplitGetValue s))
-				(moneyoutcoll
-				 'add commod-currency
-				 (gnc-numeric-neg (xaccSplitGetValue s))))
-			       (else (moneyincoll 
-				      'add commod-currency
-				      (gnc-numeric-neg (xaccSplitGetValue s))))))))
+				    ;; first fix the basis. but only when we are dealing with the actual stock
+				    (if (same-account? current (xaccSplitGetAccount s))
+					(set! basis-list (basis-builder basis-list split-units (gnc:gnc-monetary-amount 
+												(exchange-fn (gnc:make-gnc-monetary 
+													      commod-currency split-value) 
+													     currency)) basis-method)))
+				    (gnc:debug  "coming out of basis list " basis-list)
+				    ;; now look at what else we have to work with
+				    (cond
 			 
-			   ((split-account-type? s ACCT-TYPE-EXPENSE)
-			     (brokeragecoll 'add commod-currency (xaccSplitGetValue s)))
-			   
-			   ((split-account-type? s ACCT-TYPE-INCOME)
-			     (dividendcoll 'add commod-currency (xaccSplitGetValue s)))
+				     ;; are we looking at the same
+				     ;; account? that means we're
+				     ;; dealing strictly with the
+				     ;; amount of stock moving, and
+				     ;; its value, adjust the money
+				     ;; collectors ((same-account?
+				     ;; current (xaccSplitGetAccount
+				     ;; s)) if the commod-currency and
+				     ;; the commodity of this split,
+				     ;; s, are the same then we're
+				     ;; dealing with actual money
+				     ;; being shuffled and we need to
+				     ;; adjust moneyin/out
+				     ((equal? commod-currency (xaccAccountGetCommodity (xaccSplitGetAccount s)))
+				      (begin
+					(gnc:debug "adjsting the moneyin/out " split-value)
+					(if (gnc-numeric-negative-p split-value)
+					    (moneyincoll 'add commod-currency
+							  (gnc-numeric-neg split-value))
+					    (moneyoutcoll 'add commod-currency split-value)
 			   )
 			  )
+				      )
+				     )
+				    )
+				  )
+
+				 ;; here is where we handle a spin-off txn. This will be a no-units
+				 ;; transaction with only one other split. xaccSplitGetOtherSplit only
+				 ;; returns on a two-split txn :) 
+				 ;; FIXME!! not implemented in basis-builder yet!
+				 ((and (gnc-numeric-zero-p txn-units) (xaccSplitGetOtherSplit s))
+				  (if (same-account? current (xaccSplitGetAccount s))
+				      (set! basis-list (basis-builder basis-list split-units (gnc:gnc-monetary-amount 
+											      (exchange-fn (gnc:make-gnc-monetary 
+													    commod-currency split-value) 
+													   currency)) basis-method))
+				      )
+				  )
+				 )
+				)
+			      )
+			  )
 			(xaccTransGetSplitList parent)
 			)
 		       )
@@ -425,8 +513,6 @@
 	       )
 	     (xaccAccountGetSplitList current)
 	     )
-;;          (gnc:debug "totalunits" totalunits)
-;;          (gnc:debug "totalunityears" totalunityears)
 
 	    ;; now we determine which price data to use, the pricelist or the txn
 	    ;; and if we have a choice, use whichever is newest.
@@ -434,6 +520,9 @@
 			      (if prefer-pricelist #f
 				  (if (not (gnc:timepair-le txn-date (gnc-price-get-time price)))
 				      #t #f))))
+	    (gnc:debug "use txn is " use-txn)
+	    (gnc:debug "prefer-pricelist is " prefer-pricelist)
+	    (gnc:debug "price is " price)
 
 	    ;; okay we're using the txn, so make a new price, value etc. and warn the user
 	    (if use-txn
@@ -442,13 +531,13 @@
 				  (gnc:make-gnc-monetary commod-currency
 							 (gnc-numeric-div txn-value
 									  (gnc-numeric-abs txn-units)
-									  100 GNC-RND-ROUND))
+									  100 (logior GNC-DENOM-REDUCE GNC-RND-NEVER)))
 				  (gnc:make-gnc-monetary commod-currency (gnc-numeric-zero))))
-
+		  
 		  (set! value (if price (gnc:make-gnc-monetary commod-currency 
 						     (gnc-numeric-mul units
 								      (gnc:gnc-monetary-amount price)
-								      100 GNC-RND-ROUND))
+										100 (logior GNC-DENOM-REDUCE GNC-RND-NEVER)))
 				  (gnc:make-gnc-monetary commod-currency (gnc-numeric-zero))))
 		  (set! warn-price-dirty #t)
 		  )  
@@ -457,27 +546,35 @@
 	    ;; what this means is gain = moneyout - moneyin + basis-of-current-shares, and
 	    ;; adjust for brokers and dividends.
 	    (gaincoll 'add currency (sum-basis basis-list))
-            (moneyincoll 'minusmerge dividendcoll #f)
-	    (moneyoutcoll 'minusmerge brokeragecoll #f)
+	    (gnc:debug (list "basis we're using to build rows is " (sum-basis basis-list)))
+	    (gnc:debug (list "but the actual basis list is " basis-list))
+	    ;; FIXME! these lines were intended to adjust the dividends and
+	    ;; brokerage fees back out of the money collector so the user could
+	    ;; see just the pure investment money. It doesn't work because its
+	    ;; impossible to tell where income comes from.
+
+	    ;; (moneyincoll 'minusmerge dividendcoll #f)
+	    ;; (moneyincoll 'minusmerge brokeragecoll #f)
+	    ;; (moneyoutcoll 'minusmerge brokeragecoll #f)
 	    (gaincoll 'merge moneyoutcoll #f)
-	    (gaincoll 'merge moneyincoll #f)
+	    (gaincoll 'minusmerge moneyincoll #f)
 
 
 
 	    
 	  (if (or include-empty (not (gnc-numeric-zero-p units)))
-	    (let* ((moneyin (gnc:monetary-neg
-			    (gnc:sum-collector-commodity moneyincoll currency exchange-fn)))
+	    (let* ((moneyin (gnc:sum-collector-commodity moneyincoll currency exchange-fn))
 		  (moneyout (gnc:sum-collector-commodity moneyoutcoll currency exchange-fn))
+                   (brokerage (gnc:sum-collector-commodity brokeragecoll currency exchange-fn))
 		  ;; just so you know, gain == realized gain, ugain == un-realized gain, bothgain, well..
 		  (gain (gnc:sum-collector-commodity gaincoll currency exchange-fn))
 		  (ugain (gnc:make-gnc-monetary currency 
 						(gnc-numeric-sub (gnc:gnc-monetary-amount (exchange-fn value currency))
 								 (sum-basis basis-list) 
-								 100 GNC-RND-ROUND)))
+								 100 (logior GNC-DENOM-REDUCE GNC-RND-NEVER))))
 		  (bothgain (gnc:make-gnc-monetary currency  (gnc-numeric-add (gnc:gnc-monetary-amount gain)
 									      (gnc:gnc-monetary-amount ugain)
-									      100 GNC-RND-ROUND)))
+									      100 (logior GNC-DENOM-REDUCE GNC-RND-NEVER))))
 
 		  (activecols (list (gnc:html-account-anchor current)))
 		  )
@@ -485,6 +582,7 @@
 	      (total-value 'add (gnc:gnc-monetary-commodity value) (gnc:gnc-monetary-amount value))
 	      (total-moneyin 'merge moneyincoll #f)
 	      (total-moneyout 'merge moneyoutcoll #f)
+              (total-brokerage 'merge brokeragecoll #f)
 	      (total-gain 'merge gaincoll #f)
 	      (total-ugain 'add (gnc:gnc-monetary-commodity ugain) (gnc:gnc-monetary-amount ugain))
 	      (total-basis 'add currency (sum-basis basis-list))
@@ -516,8 +614,6 @@
 					(gnc:make-html-table-header-cell/markup "number-cell" gain)
 					(gnc:make-html-table-header-cell/markup "number-cell" ugain)
 					(gnc:make-html-table-header-cell/markup "number-cell" bothgain)
-										
-										
 					(gnc:make-html-table-header-cell/markup "number-cell" 
 					    (let ((moneyinvalue (gnc-numeric-to-double
 								 (gnc:gnc-monetary-amount moneyin))))
@@ -526,6 +622,7 @@
 						  (sprintf #f "%.2f%%" (* 100 (/ (gnc-numeric-to-double
 									     (gnc:gnc-monetary-amount bothgain))
 									    moneyinvalue))))))
+                                        (gnc:make-html-table-header-cell/markup "number-cell" brokerage)
 					 )
 			)
                        
@@ -560,8 +657,6 @@
                                   gnc:optname-reportname))
         (include-empty (get-option gnc:pagename-accounts
                                   optname-zero-shares))
-        (include-gains (get-option gnc:pagename-general
-                                  optname-include-gains))
 	(show-symbol (get-option gnc:pagename-display
 				  optname-show-symbol))
 	(show-listing (get-option gnc:pagename-display
@@ -581,6 +676,7 @@
         (total-moneyout (gnc:make-commodity-collector))
         (total-gain     (gnc:make-commodity-collector)) ;; realized gain
 	(total-ugain (gnc:make-commodity-collector))    ;; unrealized gain
+        (total-brokerage (gnc:make-commodity-collector))
 	;;document will be the HTML document that we return.
         (table (gnc:make-html-table))
         (document (gnc:make-html-document)))
@@ -638,7 +734,8 @@
 				    (_ "Realized Gain")
 				    (_ "Unrealized Gain")
 				    (_ "Total Gain")
-				    (_ "Total Return")))
+				    (_ "Total Return")
+                                    (_ "Brokerage Fees")))
 
           (append! totalscols (list " "))
 
@@ -648,22 +745,22 @@
           
           (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 
-	   basis-method prefer-pricelist total-basis total-value total-moneyin total-moneyout total-gain total-ugain)
+           include-empty show-symbol show-listing show-shares show-price 
+	   basis-method prefer-pricelist total-basis total-value total-moneyin total-moneyout total-gain total-ugain total-brokerage)
 	  
 
 	  (set! sum-total-gain (gnc:sum-collector-commodity total-gain currency exchange-fn))
 	  (set! sum-total-ugain (gnc:sum-collector-commodity total-ugain currency exchange-fn))
 	  (set! sum-total-both-gains (gnc:make-gnc-monetary currency (gnc-numeric-add (gnc:gnc-monetary-amount sum-total-gain)
 										      (gnc:gnc-monetary-amount sum-total-ugain)
-										      100 GNC-RND-ROUND)))
+										      100 (logior GNC-DENOM-REDUCE GNC-RND-NEVER))))
 
           (gnc:html-table-append-row/markup!
            table
            "grand-total"
            (list
             (gnc:make-html-table-cell/size
-             1 14 (gnc:make-html-text (gnc:html-markup-hr)))))
+             1 15 (gnc:make-html-text (gnc:html-markup-hr)))))
 
 	  ;; finish building the totals columns, now that totals are complete
 	  (append! totalscols (list
@@ -672,7 +769,7 @@
 			       (gnc:make-html-table-cell/markup
 				"total-number-cell" (gnc:sum-collector-commodity total-value currency exchange-fn))
 			       (gnc:make-html-table-cell/markup
-				"total-number-cell" (gnc:monetary-neg (gnc:sum-collector-commodity total-moneyin currency exchange-fn)))
+				"total-number-cell" (gnc:sum-collector-commodity total-moneyin currency exchange-fn))
 			       (gnc:make-html-table-cell/markup
 				"total-number-cell" (gnc:sum-collector-commodity total-moneyout currency exchange-fn))
 			       (gnc:make-html-table-cell/markup
@@ -684,13 +781,15 @@
 			       (gnc:make-html-table-cell/markup
 				"total-number-cell" 
 				(let ((totalinvalue (gnc-numeric-to-double
-						     (gnc:gnc-monetary-amount (gnc:monetary-neg (gnc:sum-collector-commodity 
-									       total-moneyin currency exchange-fn))))))
+						     (gnc:gnc-monetary-amount (gnc:sum-collector-commodity 
+									       total-moneyin currency exchange-fn)))))
 				  (if (= 0.0 totalinvalue) 
 				      (sprintf #f "%.2f%%" totalinvalue) 
 				      (sprintf #f "%.2f%%" (* 100 (/ (gnc-numeric-to-double
 								      (gnc:gnc-monetary-amount sum-total-both-gains))
 										   totalinvalue))))))
+                             (gnc:make-html-table-cell/markup
+                              "total-number-cell" (gnc:sum-collector-commodity total-brokerage currency exchange-fn))
 			       ))
 	  
 



More information about the gnucash-changes mailing list