exchangealgebra-0.6.0.0: test/Golden/AdmissionBaseline.hs
{-# LANGUAGE OverloadedStrings #-}
-- | Deterministic observations of accounting equivalence policies.
module Golden.AdmissionBaseline
( admissionFixtureDir
, admissionFixtures
, renderRows
) where
import ExchangeAlgebra.Accounting.Account (AccountTitles(..))
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
import Data.Text (Text)
import qualified Data.Text as Text
import ExchangeAlgebra.Algebra ((.@), Redundant((.+)), Hat(..))
import ExchangeAlgebra.Algebra.Base (HatBase((:<)))
import ExchangeAlgebra.Accounting.Transaction
( EntityId(..)
, PeriodId(..)
, TxId(..)
, TxKey(..)
, Entry
)
import ExchangeAlgebra.Accounting.Equivalence (Equivalence(..), isEquivalentUpTo)
import ExchangeAlgebra.Algebra.Value (MoneyDecimal)
-- | Directory containing the committed equivalence observations.
admissionFixtureDir :: FilePath
admissionFixtureDir = "test/fixtures/admission-baseline-p1"
-- | Develop revision whose equivalence behavior these rows record.
baselineCommit :: Text
baselineCommit = "2a83fe178d47a1024e0e566794f39533a12b4c20"
-- | Name, P3 category, and observed result of one fixed input.
data GoldenCase = GoldenCase Text Text Text
-- | Escape cells so each case occupies exactly one TSV row.
escapeCell :: Text -> Text
escapeCell = Text.replace "\\" "\\\\"
. Text.replace "\n" "\\n"
. Text.replace "\t" "\\t"
-- | Render the schema, revision, and observations in their declared order.
renderRows :: [GoldenCase] -> Text
renderRows cases =
"# admission-baseline-p1; schema 1; commit " <> baselineCommit <> "\n"
<> "case\tp3\tobservation\n"
<> Text.unlines
[ Text.intercalate "\t" (map escapeCell [name, category, result])
| GoldenCase name category result <- cases
]
-- | Entity used in the fixed equivalence inputs.
entityA :: EntityId
entityA = EntityId "A"
-- | Reporting period used in the fixed equivalence inputs.
periodOne :: PeriodId
periodOne = PeriodId "2026"
-- | Construct a transaction key without parsing its identity.
key :: EntityId -> PeriodId -> Text -> TxKey
key entity period identity = TxKey entity period (TxId identity)
-- | Compare the three policies on fixed redundant and exact-residual inputs.
equivalenceCases :: [GoldenCase]
equivalenceCases =
[ compare "cash-gross-transaction-net" NetWithinTransaction baseline withCash
, compare "cash-gross-postings" PostingMultiset baseline withCash
, compare "cash-gross-selected" selected baseline withCash
, compare "retained-gross-postings" PostingMultiset baseline withGrossRetained
, compare "retained-gross-transaction-net" NetWithinTransaction baseline withGrossRetained
, compare "retained-gross-selected" selected baseline withGrossRetained
, compare "near-cancellation-net" NetWithinTransaction nearCancellation zeroPosting
, compare "near-cancellation-postings" PostingMultiset nearCancellation zeroPosting
, compare "near-cancellation-selected" selected nearCancellation zeroPosting
, compare "tiny-pair-net" NetWithinTransaction tinyPair zeroPosting
, compare "tiny-pair-postings" PostingMultiset tinyPair zeroPosting
, compare "tiny-single-net" NetWithinTransaction tinySingle zeroPosting
]
where
closing = key entityA periodOne "closing"
base = 100 .@ Hat :< Sales
.+ 80 .@ Not :< RetainedEarnings
.+ 20 .@ Hat :< Depreciation :: Entry
cashGross = base .+ 10 .@ Not :< Cash .+ 10 .@ Hat :< Cash
retainedGross = 100 .@ Hat :< Sales
.+ 100 .@ Not :< RetainedEarnings
.+ 20 .@ Hat :< RetainedEarnings
.+ 20 .@ Hat :< Depreciation :: Entry
baseline = Map.singleton closing base
withCash = Map.singleton closing cashGross
withGrossRetained = Map.singleton closing retainedGross
selected = NetAccountsInTransactions
(Set.singleton closing) (Set.singleton RetainedEarnings)
nearCancellation = Map.singleton closing
(1000000000000 .@ Not :< Cash
.+ (1000000000000 - 0.5) .@ Hat :< Cash :: Entry)
zeroPosting = Map.singleton closing (mempty :: Entry)
tiny = 0.00000000000001 :: MoneyDecimal
tinyPair = Map.singleton closing
((2 * tiny) .@ Hat :< Cash .+ tiny .@ Not :< Cash :: Entry)
tinySingle = Map.singleton closing (tiny .@ Hat :< Cash :: Entry)
compare name policy first second = GoldenCase name category
(Text.pack (show (isEquivalentUpTo policy first second)))
where
category = case policy of
PostingMultiset -> "-"
_ -> "exact-residual"
-- | The retained equivalence fixture and its case count.
admissionFixtures :: [(FilePath, Text, Int)]
admissionFixtures =
[("equivalence.tsv", renderRows equivalenceCases, length equivalenceCases)]