dev: refactor transactionCheckBalanced

This commit is contained in:
Simon Michael 2023-09-20 10:24:17 +01:00
parent c13c13ab1f
commit 4e56199c57

View File

@ -93,6 +93,7 @@ defbalancingopts = BalancingOpts
transactionCheckBalanced :: BalancingOpts -> Transaction -> [String] transactionCheckBalanced :: BalancingOpts -> Transaction -> [String]
transactionCheckBalanced BalancingOpts{commodity_styles_} t = errs transactionCheckBalanced BalancingOpts{commodity_styles_} t = errs
where where
-- get real and balanced virtual postings, to be checked separately
(rps, bvps) = foldr partitionPosting ([], []) $ tpostings t (rps, bvps) = foldr partitionPosting ([], []) $ tpostings t
where where
partitionPosting p ~(l, r) = case ptype p of partitionPosting p ~(l, r) = case ptype p of
@ -100,24 +101,30 @@ transactionCheckBalanced BalancingOpts{commodity_styles_} t = errs
BalancedVirtualPosting -> (l, p:r) BalancedVirtualPosting -> (l, p:r)
VirtualPosting -> (l, r) VirtualPosting -> (l, r)
-- check for mixed signs, detecting nonzeros at display precision -- convert this posting's amount to cost,
setstyles = maybe id styleAmounts commodity_styles_ -- without getting confused by redundant costs/equity postings
postingBalancingAmount p postingBalancingAmount p
| "_price-matched" `elem` map fst (ptags p) = mixedAmountStripPrices $ pamount p | "_price-matched" `elem` map fst (ptags p) = mixedAmountStripPrices $ pamount p
| otherwise = mixedAmountCost $ pamount p | otherwise = mixedAmountCost $ pamount p
signsOk ps =
case filter (not.mixedAmountLooksZero) $ map (setstyles.postingBalancingAmount) ps of -- transaction balancedness is checked at each commodity's display precision
nonzeros | length nonzeros >= 2 lookszero = mixedAmountLooksZero . atdisplayprecision
-> length (nubSort $ mapMaybe isNegativeMixedAmount nonzeros) > 1 where
_ -> True atdisplayprecision = maybe id styleAmounts $ commodity_styles_
-- when there's multiple non-zeros, check they do not all have the same sign
(rsignsok, bvsignsok) = (signsOk rps, signsOk bvps) (rsignsok, bvsignsok) = (signsOk rps, signsOk bvps)
where
signsOk ps = length nonzeros < 2 || length nonzerosigns > 1
where
nonzeros = filter (not.lookszero) $ map postingBalancingAmount ps
nonzerosigns = nubSort $ mapMaybe isNegativeMixedAmount nonzeros
-- check for zero sum, at display precision -- check that the sum looks like zero
(rsumcost, bvsumcost) = (foldMap postingBalancingAmount rps, foldMap postingBalancingAmount bvps) (rsumcost, bvsumcost) = (foldMap postingBalancingAmount rps, foldMap postingBalancingAmount bvps)
(rsumdisplay, bvsumdisplay) = (setstyles rsumcost, setstyles bvsumcost) (rsumok, bvsumok) = (lookszero rsumcost, lookszero bvsumcost)
(rsumok, bvsumok) = (mixedAmountLooksZero rsumdisplay, mixedAmountLooksZero bvsumdisplay)
-- generate error messages, showing amounts with their original precision -- Generate error messages if any. Show amounts with their original precisions.
errs = filter (not.null) [rmsg, bvmsg] errs = filter (not.null) [rmsg, bvmsg]
where where
rmsg rmsg