mirror of
https://github.com/simonmichael/hledger.git
synced 2024-12-28 12:54:07 +03:00
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