lib: Move unifyMixedAmount to Hledger.Data.Amount, make it return Maybe Amount, export it.
This commit is contained in:
		
							parent
							
								
									e090e0f949
								
							
						
					
					
						commit
						015492553e
					
				| @ -100,6 +100,7 @@ module Hledger.Data.Amount ( | ||||
|   mapMixedAmount, | ||||
|   normaliseMixedAmountSquashPricesForDisplay, | ||||
|   normaliseMixedAmount, | ||||
|   unifyMixedAmount, | ||||
|   mixedAmountStripPrices, | ||||
|   -- ** arithmetic | ||||
|   mixedAmountCost, | ||||
| @ -131,6 +132,7 @@ module Hledger.Data.Amount ( | ||||
|   tests_Amount | ||||
| ) where | ||||
| 
 | ||||
| import Control.Monad (foldM) | ||||
| import Data.Char (isDigit) | ||||
| import Data.Decimal (roundTo, decimalPlaces, normalizeDecimal) | ||||
| import Data.Function (on) | ||||
| @ -537,6 +539,19 @@ normaliseHelper squashprices (Mixed as) | ||||
| normaliseMixedAmountSquashPricesForDisplay :: MixedAmount -> MixedAmount | ||||
| normaliseMixedAmountSquashPricesForDisplay = normaliseHelper True | ||||
| 
 | ||||
| -- | Unify a MixedAmount to a single commodity value if possible. | ||||
| -- Like normaliseMixedAmount, this consolidates amounts of the same commodity | ||||
| -- and discards zero amounts; but this one insists on simplifying to | ||||
| -- a single commodity, and will return Nothing if this is not possible. | ||||
| unifyMixedAmount :: MixedAmount -> Maybe Amount | ||||
| unifyMixedAmount = foldM combine 0 . amounts | ||||
|   where | ||||
|     combine amount result | ||||
|       | amountIsZero amount                    = Just result | ||||
|       | amountIsZero result                    = Just amount | ||||
|       | acommodity amount == acommodity result = Just $ amount + result | ||||
|       | otherwise                              = Nothing | ||||
| 
 | ||||
| -- | Sum same-commodity amounts in a lossy way, applying the first | ||||
| -- price to the result and discarding any other prices. Only used as a | ||||
| -- rendering helper. | ||||
|  | ||||
| @ -25,20 +25,21 @@ module Hledger.Reports.MultiBalanceReport ( | ||||
| ) | ||||
| where | ||||
| 
 | ||||
| import Data.List | ||||
| import Control.Monad (guard) | ||||
| import Data.List (sortBy, transpose) | ||||
| import Data.HashMap.Strict (HashMap) | ||||
| import qualified Data.HashMap.Strict as HM | ||||
| import Data.Map (Map) | ||||
| import qualified Data.Map as M | ||||
| import Data.Maybe | ||||
| import Data.Ord | ||||
| import Data.Maybe (fromMaybe, mapMaybe) | ||||
| import Data.Ord (comparing) | ||||
| #if !(MIN_VERSION_base(4,11,0)) | ||||
| import Data.Semigroup ((<>)) | ||||
| #endif | ||||
| import Data.Time.Calendar | ||||
| import Safe | ||||
| import Data.Time.Calendar (Day, addDays, fromGregorian) | ||||
| import Safe (headDef, headMay, lastMay) | ||||
| import Text.Tabular as T | ||||
| import Text.Tabular.AsciiWide | ||||
| import Text.Tabular.AsciiWide (render) | ||||
| 
 | ||||
| import Hledger.Data | ||||
| import Hledger.Query | ||||
| @ -511,32 +512,15 @@ subaccountTallies as = foldr incrementParent mempty allaccts | ||||
|     allaccts = expandAccountNames as | ||||
|     incrementParent a = HM.insertWith (+) (parentAccountName a) 1 | ||||
| 
 | ||||
| -- | Helper to unify a MixedAmount to a single commodity value. | ||||
| -- Like normaliseMixedAmount, this consolidates amounts of the same commodity | ||||
| -- and discards zero amounts; but this one insists on simplifying to | ||||
| -- a single commodity, and will throw a program-terminating error if | ||||
| -- this is not possible. | ||||
| unifyMixedAmount :: MixedAmount -> Amount | ||||
| unifyMixedAmount mixedAmount = foldl combine (num 0) (amounts mixedAmount) | ||||
|   where | ||||
|     combine amount result = | ||||
|       if amountIsZero amount | ||||
|       then result | ||||
|       else if amountIsZero result | ||||
|         then amount | ||||
|         else if acommodity amount == acommodity result | ||||
|           then amount + result | ||||
|           else error' "Cannot calculate percentages for accounts with multiple commodities. (Hint: Try --cost, -V or similar flags.)" | ||||
| 
 | ||||
| -- | Helper to calculate the percentage from two mixed. Keeps the sign of the first argument. | ||||
| -- Uses unifyMixedAmount to unify each argument and then divides them. | ||||
| perdivide :: MixedAmount -> MixedAmount -> MixedAmount | ||||
| perdivide a b = | ||||
|   let a' = unifyMixedAmount a | ||||
|       b' = unifyMixedAmount b | ||||
|   in if amountIsZero a' || amountIsZero b' || acommodity a' == acommodity b' | ||||
|     then mixed [per $ if aquantity b' == 0 then 0 else (aquantity a' / abs (aquantity b') * 100)] | ||||
|     else error' "Cannot calculate percentages if accounts have different commodities. (Hint: Try --cost, -V or similar flags.)" | ||||
| perdivide a b = fromMaybe (error' errmsg) $ do | ||||
|     a' <- unifyMixedAmount a | ||||
|     b' <- unifyMixedAmount b | ||||
|     guard $ amountIsZero a' || amountIsZero b' || acommodity a' == acommodity b' | ||||
|     return $ mixed [per $ if aquantity b' == 0 then 0 else aquantity a' / abs (aquantity b') * 100] | ||||
|   where errmsg = "Cannot calculate percentages if accounts have different commodities (Hint: Try --cost, -V or similar flags.)" | ||||
| 
 | ||||
| -- Local debug helper | ||||
| -- add a prefix to this function's debug output | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user