;lib: refactor amount cost functions
Rename costOfAmount -> amountCost, costOfMixedAmount -> mixedAmountCost, drop amountToCost, mixedAmountToCost.
This commit is contained in:
parent
90b18080b2
commit
97f2235bca
@ -61,8 +61,7 @@ module Hledger.Data.Amount (
|
||||
(@@),
|
||||
amountWithCommodity,
|
||||
-- ** arithmetic
|
||||
costOfAmount,
|
||||
amountToCost,
|
||||
amountCost,
|
||||
amountIsZero,
|
||||
amountLooksZero,
|
||||
divideAmount,
|
||||
@ -103,8 +102,7 @@ module Hledger.Data.Amount (
|
||||
normaliseMixedAmount,
|
||||
mixedAmountStripPrices,
|
||||
-- ** arithmetic
|
||||
costOfMixedAmount,
|
||||
mixedAmountToCost,
|
||||
mixedAmountCost,
|
||||
divideMixedAmount,
|
||||
multiplyMixedAmount,
|
||||
divideMixedAmountAndPrice,
|
||||
@ -211,22 +209,21 @@ similarAmountsOp op Amount{acommodity=_, aquantity=q1, astyle=AmountStyle{aspre
|
||||
amountWithCommodity :: CommoditySymbol -> Amount -> Amount
|
||||
amountWithCommodity c a = a{acommodity=c, aprice=Nothing}
|
||||
|
||||
-- | Convert an amount to the commodity of its assigned price, if any. Notes:
|
||||
-- | Convert a amount to its "cost" or "selling price" in another commodity,
|
||||
-- using its attached transaction price if it has one. Notes:
|
||||
--
|
||||
-- - price amounts must be MixedAmounts with exactly one component Amount (or there will be a runtime error) XXX
|
||||
-- - price amounts must be MixedAmounts with exactly one component Amount
|
||||
-- (or there will be a runtime error XXX)
|
||||
--
|
||||
-- - price amounts should be positive, though this is not currently enforced
|
||||
costOfAmount :: Amount -> Amount
|
||||
costOfAmount a@Amount{aquantity=q, aprice=mp} =
|
||||
-- - price amounts should be positive
|
||||
-- (though this is currently not enforced)
|
||||
amountCost :: Amount -> Amount
|
||||
amountCost a@Amount{aquantity=q, aprice=mp} =
|
||||
case mp of
|
||||
Nothing -> a
|
||||
Just (UnitPrice p@Amount{aquantity=pq}) -> p{aquantity=pq * q}
|
||||
Just (TotalPrice p@Amount{aquantity=pq}) -> p{aquantity=pq * signum q}
|
||||
|
||||
-- | Convert this amount to cost, and apply the appropriate amount style.
|
||||
amountToCost :: M.Map CommoditySymbol AmountStyle -> Amount -> Amount
|
||||
amountToCost styles = styleAmount styles . costOfAmount
|
||||
|
||||
-- | Replace an amount's TotalPrice, if it has one, with an equivalent UnitPrice.
|
||||
-- Has no effect on amounts without one.
|
||||
-- Also increases the unit price's display precision to show one extra decimal place,
|
||||
@ -370,8 +367,9 @@ showAmountPriceDebug Nothing = ""
|
||||
showAmountPriceDebug (Just (UnitPrice pa)) = " @ " ++ showAmountDebug pa
|
||||
showAmountPriceDebug (Just (TotalPrice pa)) = " @@ " ++ showAmountDebug pa
|
||||
|
||||
-- | Given a map of standard amount display styles, apply the appropriate one to this amount.
|
||||
-- If there's no standard style for this amount's commodity, return the amount unchanged.
|
||||
-- | Given a map of standard commodity display styles, apply the
|
||||
-- appropriate one to this amount. If there's no standard style for
|
||||
-- this amount's commodity, return the amount unchanged.
|
||||
styleAmount :: M.Map CommoditySymbol AmountStyle -> Amount -> Amount
|
||||
styleAmount styles a =
|
||||
case M.lookup (acommodity a) styles of
|
||||
@ -576,14 +574,10 @@ filterMixedAmountByCommodity c (Mixed as) = Mixed as'
|
||||
mapMixedAmount :: (Amount -> Amount) -> MixedAmount -> MixedAmount
|
||||
mapMixedAmount f (Mixed as) = Mixed $ map f as
|
||||
|
||||
-- | Convert a mixed amount's component amounts to the commodity of their
|
||||
-- assigned price, if any.
|
||||
costOfMixedAmount :: MixedAmount -> MixedAmount
|
||||
costOfMixedAmount (Mixed as) = Mixed $ map costOfAmount as
|
||||
|
||||
-- | Convert all component amounts to cost, and apply the appropriate amount styles.
|
||||
mixedAmountToCost :: M.Map CommoditySymbol AmountStyle -> MixedAmount -> MixedAmount
|
||||
mixedAmountToCost styles (Mixed as) = Mixed $ map (amountToCost styles) as
|
||||
-- | Convert all component amounts to cost/selling price where
|
||||
-- possible (see amountCost).
|
||||
mixedAmountCost :: MixedAmount -> MixedAmount
|
||||
mixedAmountCost (Mixed as) = Mixed $ map amountCost as
|
||||
|
||||
-- | Divide a mixed amount's quantities by a constant.
|
||||
divideMixedAmount :: Quantity -> MixedAmount -> MixedAmount
|
||||
@ -635,7 +629,8 @@ mixedAmountIsZero = all amountIsZero . amounts . normaliseMixedAmountSquashPrice
|
||||
-- where a' = normaliseMixedAmountSquashPricesForDisplay a
|
||||
-- b' = normaliseMixedAmountSquashPricesForDisplay b
|
||||
|
||||
-- | Given a map of standard amount display styles, apply the appropriate ones to each individual amount.
|
||||
-- | Given a map of standard commodity display styles, apply the
|
||||
-- appropriate one to each individual amount.
|
||||
styleMixedAmount :: M.Map CommoditySymbol AmountStyle -> MixedAmount -> MixedAmount
|
||||
styleMixedAmount styles (Mixed as) = Mixed $ map (styleAmount styles) as
|
||||
|
||||
@ -742,11 +737,11 @@ mixedAmountTotalPriceToUnitPrice (Mixed as) = Mixed $ map amountTotalPriceToUnit
|
||||
tests_Amount = tests "Amount" [
|
||||
tests "Amount" [
|
||||
|
||||
test "costOfAmount" $ do
|
||||
costOfAmount (eur 1) @?= eur 1
|
||||
costOfAmount (eur 2){aprice=Just $ UnitPrice $ usd 2} @?= usd 4
|
||||
costOfAmount (eur 1){aprice=Just $ TotalPrice $ usd 2} @?= usd 2
|
||||
costOfAmount (eur (-1)){aprice=Just $ TotalPrice $ usd 2} @?= usd (-2)
|
||||
test "amountCost" $ do
|
||||
amountCost (eur 1) @?= eur 1
|
||||
amountCost (eur 2){aprice=Just $ UnitPrice $ usd 2} @?= usd 4
|
||||
amountCost (eur 1){aprice=Just $ TotalPrice $ usd 2} @?= usd 2
|
||||
amountCost (eur (-1)){aprice=Just $ TotalPrice $ usd 2} @?= usd (-2)
|
||||
|
||||
,test "amountLooksZero" $ do
|
||||
assertBool "" $ amountLooksZero amount
|
||||
|
||||
@ -331,7 +331,7 @@ postingApplyValuation priceoracle styles periodlast mreportlast today ismultiper
|
||||
|
||||
-- | Convert this posting's amount to cost, and apply the appropriate amount styles.
|
||||
postingToCost :: M.Map CommoditySymbol AmountStyle -> Posting -> Posting
|
||||
postingToCost styles p@Posting{pamount=a} = p{pamount=mixedAmountToCost styles a}
|
||||
postingToCost styles p@Posting{pamount=a} = p{pamount=styleMixedAmount styles $ mixedAmountCost a}
|
||||
|
||||
-- | Convert this posting's amount to market value in the given commodity,
|
||||
-- or the default valuation commodity, at the given valuation date,
|
||||
|
||||
@ -357,7 +357,7 @@ transactionCheckBalanced mstyles t = errs
|
||||
-- check for mixed signs, detecting nonzeros at display precision
|
||||
canonicalise = maybe id canonicaliseMixedAmount mstyles
|
||||
signsOk ps =
|
||||
case filter (not.mixedAmountLooksZero) $ map (canonicalise.costOfMixedAmount.pamount) ps of
|
||||
case filter (not.mixedAmountLooksZero) $ map (canonicalise.mixedAmountCost.pamount) ps of
|
||||
nonzeros | length nonzeros >= 2
|
||||
-> length (nubSort $ mapMaybe isNegativeMixedAmount nonzeros) > 1
|
||||
_ -> True
|
||||
@ -365,7 +365,7 @@ transactionCheckBalanced mstyles t = errs
|
||||
|
||||
-- check for zero sum, at display precision
|
||||
(rsum, bvsum) = (sumPostings rps, sumPostings bvps)
|
||||
(rsumcost, bvsumcost) = (costOfMixedAmount rsum, costOfMixedAmount bvsum)
|
||||
(rsumcost, bvsumcost) = (mixedAmountCost rsum, mixedAmountCost bvsum)
|
||||
(rsumdisplay, bvsumdisplay) = (canonicalise rsumcost, canonicalise bvsumcost)
|
||||
(rsumok, bvsumok) = (mixedAmountLooksZero rsumdisplay, mixedAmountLooksZero bvsumdisplay)
|
||||
|
||||
@ -475,7 +475,7 @@ inferBalancingAmount styles t@Transaction{tpostings=ps}
|
||||
-- Inferred amounts are converted to cost.
|
||||
-- Also ensure the new amount has the standard style for its commodity
|
||||
-- (since the main amount styling pass happened before this balancing pass);
|
||||
a' = styleMixedAmount styles $ normaliseMixedAmount $ costOfMixedAmount (-a)
|
||||
a' = styleMixedAmount styles $ normaliseMixedAmount $ mixedAmountCost (-a)
|
||||
|
||||
-- | Infer prices for this transaction's posting amounts, if needed to make
|
||||
-- the postings balance, and if possible. This is done once for the real
|
||||
|
||||
@ -141,8 +141,8 @@ mixedAmountApplyValuation priceoracle styles periodlast mreportlast today ismult
|
||||
amountApplyValuation :: PriceOracle -> M.Map CommoditySymbol AmountStyle -> Day -> Maybe Day -> Day -> Bool -> ValuationType -> Amount -> Amount
|
||||
amountApplyValuation priceoracle styles periodlast mreportlast today ismultiperiod v a =
|
||||
case v of
|
||||
AtCost Nothing -> amountToCost styles a
|
||||
AtCost mc -> amountValueAtDate priceoracle styles mc periodlast $ amountToCost styles a
|
||||
AtCost Nothing -> styleAmount styles $ amountCost a
|
||||
AtCost mc -> amountValueAtDate priceoracle styles mc periodlast $ styleAmount styles $ amountCost a
|
||||
AtThen _mc -> error' unsupportedValueThenError -- TODO
|
||||
-- amountValueAtDate priceoracle styles mc periodlast a -- posting date unknown, handle like AtEnd
|
||||
AtEnd mc -> amountValueAtDate priceoracle styles mc periodlast a
|
||||
|
||||
@ -885,7 +885,7 @@ getAmount rules record currency p1IsVirtual n =
|
||||
, let a = parseAmount rules record currency v
|
||||
-- With amount/amount-in/amount-out, in posting 2,
|
||||
-- flip the sign and convert to cost, as they did before 1.17
|
||||
, let a' = if f `elem` unnumberedfieldnames && n==2 then costOfMixedAmount (-a) else a
|
||||
, let a' = if f `elem` unnumberedfieldnames && n==2 then mixedAmountCost (-a) else a
|
||||
]
|
||||
|
||||
-- if any of the numbered field names are present, discard all the unnumbered ones
|
||||
|
||||
@ -296,7 +296,7 @@ budgetReportAsText ropts@ReportOpts{..} budgetr =
|
||||
_ -> -- trace (pshow $ (maybecost actual, maybecost budget)) -- debug missing percentage
|
||||
Nothing
|
||||
where
|
||||
maybecost = if valuationTypeIsCost ropts then costOfMixedAmount else id
|
||||
maybecost = if valuationTypeIsCost ropts then mixedAmountCost else id
|
||||
showamt :: MixedAmount -> String
|
||||
showamt | color_ = cshowMixedAmountOneLineWithoutPrice
|
||||
| otherwise = showMixedAmountOneLineWithoutPrice
|
||||
|
||||
@ -234,7 +234,7 @@ total trans query = unMix $ sumPostings $ filter (matchesPosting query) $ concat
|
||||
|
||||
unMix :: MixedAmount -> Quantity
|
||||
unMix a =
|
||||
case (normaliseMixedAmount $ costOfMixedAmount a) of
|
||||
case (normaliseMixedAmount $ mixedAmountCost a) of
|
||||
(Mixed [a]) -> aquantity a
|
||||
_ -> error "MixedAmount failed to normalize"
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user