lib: (divide|multiply)[Mixed]AmountAndPrice (#928)
Divide/multiply amounts *and* their total price, if they have one. Helpful for keeping transactions balanced when transaction modifiers are multiplying amounts.
This commit is contained in:
parent
b053942e9b
commit
d7919003ae
@ -59,6 +59,8 @@ module Hledger.Data.Amount (
|
|||||||
costOfAmount,
|
costOfAmount,
|
||||||
divideAmount,
|
divideAmount,
|
||||||
multiplyAmount,
|
multiplyAmount,
|
||||||
|
divideAmountAndPrice,
|
||||||
|
multiplyAmountAndPrice,
|
||||||
amountValue,
|
amountValue,
|
||||||
amountTotalPriceToUnitPrice,
|
amountTotalPriceToUnitPrice,
|
||||||
-- ** rendering
|
-- ** rendering
|
||||||
@ -91,6 +93,8 @@ module Hledger.Data.Amount (
|
|||||||
costOfMixedAmount,
|
costOfMixedAmount,
|
||||||
divideMixedAmount,
|
divideMixedAmount,
|
||||||
multiplyMixedAmount,
|
multiplyMixedAmount,
|
||||||
|
divideMixedAmountAndPrice,
|
||||||
|
multiplyMixedAmountAndPrice,
|
||||||
averageMixedAmounts,
|
averageMixedAmounts,
|
||||||
isNegativeAmount,
|
isNegativeAmount,
|
||||||
isNegativeMixedAmount,
|
isNegativeMixedAmount,
|
||||||
@ -214,7 +218,7 @@ costOfAmount a@Amount{aquantity=q, aprice=price} =
|
|||||||
-- | Replace an amount's TotalPrice, if it has one, with an equivalent UnitPrice.
|
-- | Replace an amount's TotalPrice, if it has one, with an equivalent UnitPrice.
|
||||||
-- Has no effect on amounts without one.
|
-- Has no effect on amounts without one.
|
||||||
-- Also increases the unit price's display precision to show one extra decimal place,
|
-- Also increases the unit price's display precision to show one extra decimal place,
|
||||||
-- to help the unit-priced amounts to still balance.
|
-- to help keep transaction amounts balancing.
|
||||||
-- Does Decimal division, might be some rounding/irrational number issues.
|
-- Does Decimal division, might be some rounding/irrational number issues.
|
||||||
amountTotalPriceToUnitPrice :: Amount -> Amount
|
amountTotalPriceToUnitPrice :: Amount -> Amount
|
||||||
amountTotalPriceToUnitPrice
|
amountTotalPriceToUnitPrice
|
||||||
@ -230,6 +234,22 @@ divideAmount n a@Amount{aquantity=q} = a{aquantity=q/n}
|
|||||||
multiplyAmount :: Quantity -> Amount -> Amount
|
multiplyAmount :: Quantity -> Amount -> Amount
|
||||||
multiplyAmount n a@Amount{aquantity=q} = a{aquantity=q*n}
|
multiplyAmount n a@Amount{aquantity=q} = a{aquantity=q*n}
|
||||||
|
|
||||||
|
-- | Divide an amount's quantity (and its total price, if it has one) by a constant.
|
||||||
|
-- The total price will be kept positive regardless of the multiplier's sign.
|
||||||
|
divideAmountAndPrice :: Quantity -> Amount -> Amount
|
||||||
|
divideAmountAndPrice n a@Amount{aquantity=q,aprice=p} = a{aquantity=q/n, aprice=f p}
|
||||||
|
where
|
||||||
|
f (TotalPrice a) = TotalPrice $ abs $ n `divideAmount` a
|
||||||
|
f p = p
|
||||||
|
|
||||||
|
-- | Multiply an amount's quantity (and its total price, if it has one) by a constant.
|
||||||
|
-- The total price will be kept positive regardless of the multiplier's sign.
|
||||||
|
multiplyAmountAndPrice :: Quantity -> Amount -> Amount
|
||||||
|
multiplyAmountAndPrice n a@Amount{aquantity=q,aprice=p} = a{aquantity=q*n, aprice=f p}
|
||||||
|
where
|
||||||
|
f (TotalPrice a) = TotalPrice $ abs $ n `multiplyAmount` a
|
||||||
|
f p = p
|
||||||
|
|
||||||
-- | Is this amount negative ? The price is ignored.
|
-- | Is this amount negative ? The price is ignored.
|
||||||
isNegativeAmount :: Amount -> Bool
|
isNegativeAmount :: Amount -> Bool
|
||||||
isNegativeAmount Amount{aquantity=q} = q < 0
|
isNegativeAmount Amount{aquantity=q} = q < 0
|
||||||
@ -553,6 +573,16 @@ divideMixedAmount n = mapMixedAmount (divideAmount n)
|
|||||||
multiplyMixedAmount :: Quantity -> MixedAmount -> MixedAmount
|
multiplyMixedAmount :: Quantity -> MixedAmount -> MixedAmount
|
||||||
multiplyMixedAmount n = mapMixedAmount (multiplyAmount n)
|
multiplyMixedAmount n = mapMixedAmount (multiplyAmount n)
|
||||||
|
|
||||||
|
-- | Divide a mixed amount's quantities (and total prices, if any) by a constant.
|
||||||
|
-- The total prices will be kept positive regardless of the multiplier's sign.
|
||||||
|
divideMixedAmountAndPrice :: Quantity -> MixedAmount -> MixedAmount
|
||||||
|
divideMixedAmountAndPrice n = mapMixedAmount (divideAmountAndPrice n)
|
||||||
|
|
||||||
|
-- | Multiply a mixed amount's quantities (and total prices, if any) by a constant.
|
||||||
|
-- The total prices will be kept positive regardless of the multiplier's sign.
|
||||||
|
multiplyMixedAmountAndPrice :: Quantity -> MixedAmount -> MixedAmount
|
||||||
|
multiplyMixedAmountAndPrice n = mapMixedAmount (multiplyAmountAndPrice n)
|
||||||
|
|
||||||
-- | Calculate the average of some mixed amounts.
|
-- | Calculate the average of some mixed amounts.
|
||||||
averageMixedAmounts :: [MixedAmount] -> MixedAmount
|
averageMixedAmounts :: [MixedAmount] -> MixedAmount
|
||||||
averageMixedAmounts [] = 0
|
averageMixedAmounts [] = 0
|
||||||
|
|||||||
@ -154,7 +154,7 @@ instance ToMarkup Quantity
|
|||||||
toMarkup = toMarkup . show
|
toMarkup = toMarkup . show
|
||||||
|
|
||||||
-- | An amount's price (none, per unit, or total) in another commodity.
|
-- | An amount's price (none, per unit, or total) in another commodity.
|
||||||
-- Note the price should be a positive number, although this is not enforced.
|
-- The price amount should always be positive.
|
||||||
data Price = NoPrice | UnitPrice Amount | TotalPrice Amount
|
data Price = NoPrice | UnitPrice Amount | TotalPrice Amount
|
||||||
deriving (Eq,Ord,Typeable,Data,Generic,Show)
|
deriving (Eq,Ord,Typeable,Data,Generic,Show)
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user