lib: Distinguish between an Amount having quantity (or rounded quantity 0), and having both quantity and totalprice 0 (or rounded to 0).
This commit is contained in:
parent
81b778a389
commit
ecca7f4e0c
@ -63,6 +63,8 @@ module Hledger.Data.Amount (
|
||||
amountCost,
|
||||
amountIsZero,
|
||||
amountLooksZero,
|
||||
amountAndPriceIsZero,
|
||||
amountAndPriceLooksZero,
|
||||
divideAmount,
|
||||
multiplyAmount,
|
||||
divideAmountAndPrice,
|
||||
@ -114,6 +116,8 @@ module Hledger.Data.Amount (
|
||||
isNegativeMixedAmount,
|
||||
mixedAmountIsZero,
|
||||
mixedAmountLooksZero,
|
||||
mixedAmountAndPriceIsZero,
|
||||
mixedAmountAndPriceLooksZero,
|
||||
mixedAmountTotalPriceToUnitPrice,
|
||||
-- ** rendering
|
||||
styleMixedAmount,
|
||||
@ -324,10 +328,27 @@ amountRoundedQuantity Amount{aquantity=q, astyle=AmountStyle{asprecision=p}} = c
|
||||
amountLooksZero :: Amount -> Bool
|
||||
amountLooksZero = (0==) . amountRoundedQuantity
|
||||
|
||||
-- | Does mixed amount and its price appear to be zero when rendered with its
|
||||
-- display precision ?
|
||||
amountAndPriceLooksZero :: Amount -> Bool
|
||||
amountAndPriceLooksZero amt = amountLooksZero amt && priceLooksZero
|
||||
where
|
||||
priceLooksZero = case aprice amt of
|
||||
Just (TotalPrice p) -> amountLooksZero p
|
||||
_ -> True
|
||||
|
||||
-- | Is this amount exactly zero, ignoring its display precision ?
|
||||
amountIsZero :: Amount -> Bool
|
||||
amountIsZero Amount{aquantity=q} = q == 0
|
||||
|
||||
-- | Are this amount and its price exactly zero, ignoring its display precision ?
|
||||
amountAndPriceIsZero :: Amount -> Bool
|
||||
amountAndPriceIsZero amt@Amount{aquantity=q} = q == 0 && priceIsZero
|
||||
where
|
||||
priceIsZero = case aprice amt of
|
||||
Just (TotalPrice p) -> amountIsZero p
|
||||
_ -> True
|
||||
|
||||
-- | Set an amount's display precision, flipped.
|
||||
withPrecision :: Amount -> AmountPrecision -> Amount
|
||||
withPrecision = flip amountSetPrecision
|
||||
@ -496,8 +517,7 @@ applyDigitGroupStyle (Just (DigitGroups c (g:gs))) l s = addseps (g:|gs) (toInte
|
||||
-- | Canonicalise an amount's display style using the provided commodity style map.
|
||||
canonicaliseAmount :: M.Map CommoditySymbol AmountStyle -> Amount -> Amount
|
||||
canonicaliseAmount styles a@Amount{acommodity=c, astyle=s} = a{astyle=s'}
|
||||
where
|
||||
s' = findWithDefault s c styles
|
||||
where s' = M.findWithDefault s c styles
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- MixedAmount
|
||||
@ -658,10 +678,19 @@ isNegativeMixedAmount m =
|
||||
mixedAmountLooksZero :: MixedAmount -> Bool
|
||||
mixedAmountLooksZero = all amountLooksZero . amounts . normaliseMixedAmountSquashPricesForDisplay
|
||||
|
||||
-- | Does this mixed amount and its price appear to be zero when rendered with its
|
||||
-- display precision ?
|
||||
mixedAmountAndPriceLooksZero :: MixedAmount -> Bool
|
||||
mixedAmountAndPriceLooksZero = all amountAndPriceLooksZero . amounts . normaliseMixedAmountSquashPricesForDisplay
|
||||
|
||||
-- | Is this mixed amount exactly zero, ignoring display precisions ?
|
||||
mixedAmountIsZero :: MixedAmount -> Bool
|
||||
mixedAmountIsZero = all amountIsZero . amounts . normaliseMixedAmountSquashPricesForDisplay
|
||||
|
||||
-- | Is this mixed amount exactly zero, ignoring display precisions ?
|
||||
mixedAmountAndPriceIsZero :: MixedAmount -> Bool
|
||||
mixedAmountAndPriceIsZero = all amountAndPriceIsZero . amounts . normaliseMixedAmountSquashPricesForDisplay
|
||||
|
||||
-- -- | MixedAmount derived Eq instance in Types.hs doesn't know that we
|
||||
-- -- want $0 = EUR0 = 0. Yet we don't want to drag all this code over there.
|
||||
-- -- For now, use this when cross-commodity zero equality is important.
|
||||
|
||||
@ -257,7 +257,7 @@ isPostingInDateSpan' PrimaryDate s = spanContainsDate s . postingDate
|
||||
isPostingInDateSpan' SecondaryDate s = spanContainsDate s . postingDate2
|
||||
|
||||
isEmptyPosting :: Posting -> Bool
|
||||
isEmptyPosting = mixedAmountLooksZero . pamount
|
||||
isEmptyPosting = mixedAmountAndPriceLooksZero . pamount
|
||||
|
||||
-- AccountName stuff that depends on PostingType
|
||||
|
||||
|
||||
@ -367,8 +367,8 @@ 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.mixedAmountCost.pamount) ps of
|
||||
signsOk ps =
|
||||
case filter (not.mixedAmountAndPriceLooksZero) $ map (canonicalise.mixedAmountCost.pamount) ps of
|
||||
nonzeros | length nonzeros >= 2
|
||||
-> length (nubSort $ mapMaybe isNegativeMixedAmount nonzeros) > 1
|
||||
_ -> True
|
||||
@ -378,7 +378,7 @@ transactionCheckBalanced mstyles t = errs
|
||||
(rsum, bvsum) = (sumPostings rps, sumPostings bvps)
|
||||
(rsumcost, bvsumcost) = (mixedAmountCost rsum, mixedAmountCost bvsum)
|
||||
(rsumdisplay, bvsumdisplay) = (canonicalise rsumcost, canonicalise bvsumcost)
|
||||
(rsumok, bvsumok) = (mixedAmountLooksZero rsumdisplay, mixedAmountLooksZero bvsumdisplay)
|
||||
(rsumok, bvsumok) = (mixedAmountAndPriceLooksZero rsumdisplay, mixedAmountAndPriceLooksZero bvsumdisplay)
|
||||
|
||||
-- generate error messages, showing amounts with their original precision
|
||||
errs = filter (not.null) [rmsg, bvmsg]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user