let Map = https://prelude.dhall-lang.org/v21.1.0/Map/Type sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed let CurID = Text let AcntID = Text let TagID = Text let SqlConfig {- TODO pgsql -} = < Sqlite : Text | Postgres > let Currency = { curSymbol : CurID, curFullname : Text } let Tag = { tagID : TagID, tagDesc : Text } let Gregorian = { gYear : Natural, gMonth : Natural, gDay : Natural } let GregorianM = { gmYear : Natural, gmMonth : Natural } let Interval = { intStart : Gregorian, intEnd : Optional Gregorian } let Global = { budgetInterval : Interval, statementInterval : Interval } let TimeUnit = < Day | Week | Month | Year > let Weekday = < Mon | Tue | Wed | Thu | Fri | Sat | Sun > let RepeatPat = { rpStart : Natural, rpBy : Natural, rpRepeats : Optional Natural } let MDYPat = < Single : Natural | Multi : List Natural | Repeat : RepeatPat | After : Natural | Before : Natural | Between : { _between1 : Natural, _between2 : Natural } > let ModPat = { Type = { mpStart : Optional Gregorian , mpBy : Natural , mpUnit : TimeUnit , mpRepeats : Optional Natural } , default = { mpStart = None Gregorian, mpRepeats = None Natural } } let WeekdayPat = < OnDay : Weekday | OnDays : List Weekday > let CronPat = { Type = { cronWeekly : Optional WeekdayPat , cronYear : Optional MDYPat , cronMonth : Optional MDYPat , cronDay : Optional MDYPat } , default = { cronWeekly = None WeekdayPat , cronYear = None MDYPat , cronMonth = None MDYPat , cronDay = None MDYPat } } let DatePat = < Cron : CronPat.Type | Mod : ModPat.Type > let Decimal = { whole : Natural, decimal : Natural, precision : Natural, sign : Bool } let TxOpts = { Type = { toDate : Text , toAmount : Text , toDesc : Text , toOther : List Text , toDateFmt : Text , toAmountFmt : Text } , default = { toDate = "Date" , toAmount = "Amount" , toDesc = "Description" , toOther = [] : List Text , toDateFmt = "%0m/%0d/%Y" , toAmountFmt = "([-+])?([0-9]+)\\.?([0-9]+)?" } } let Field = \(k : Type) -> \(v : Type) -> { fKey : k, fVal : v } let FieldMap = \(k : Type) -> \(v : Type) -> Field k (Map k v) let MatchVal = { Type = { mvSign : Optional Bool , mvNum : Optional Natural , mvDen : Optional Natural , mvPrec : Natural } , default = { mvSign = None Bool , mvNum = None Natural , mvDen = None Natural , mvPrec = 2 } } let MatchYMD = < Y : Natural | YM : GregorianM | YMD : Gregorian > let MatchDate = < On : MatchYMD | In : { _1 : MatchYMD, _2 : Natural } > let MatchOther = < Desc : Field Text Text | Val : Field Text MatchVal.Type > let SplitNum = < LookupN : Text | ConstN : Decimal | AmountN > let SplitText = \(t : Type) -> < ConstT : t | LookupT : Text | MapT : FieldMap Text t | Map2T : FieldMap { _1 : Text, _2 : Text } t > let SplitCur = SplitText CurID let SplitAcnt = SplitText AcntID let Split = \(a : Type) -> \(v : Type) -> \(c : Type) -> { sAcnt : a, sValue : v, sCurrency : c, sComment : Text } let ExpSplit = { Type = Split SplitAcnt (Optional SplitNum) SplitCur , default = { sValue = None SplitNum, sComment = "" } } let ToTx = { ttCurrency : SplitCur , ttPath : SplitAcnt , ttSplit : List ExpSplit.Type } let Match = { Type = { mDate : Optional MatchDate , mVal : MatchVal.Type , mDesc : Optional Text , mOther : List MatchOther , mTx : Optional ToTx , mTimes : Optional Natural , mPriority : Integer } , default = { mDate = None MatchDate , mVal = MatchVal::{=} , mDesc = None Text , mOther = [] : List MatchOther , mTx = None ToTx , mTimes = None Natural , mPriority = +0 } } let Manual = { manualDate : DatePat , manualFrom : AcntID , manualTo : AcntID , manualValue : Decimal , manualDesc : Text , manualCurrency : CurID } let Import = { impPaths : List Text , impMatches : List Match.Type , impDelim : Natural , impTxOpts : TxOpts.Type , impSkipLines : Natural } let Statement = < StmtManual : Manual | StmtImport : Import > let Amount = { amtValue : Decimal, amtDesc : Text } let AmountType = < FixedAmt | Percent | Target > let TimeAmount = { taWhen : DatePat, taAmt : Amount, taAmtType : AmountType } let Tax = { taxAcnt : AcntID, taxValue : Decimal } let Exchange = { xFromCur : CurID, xToCur : CurID, xAcnt : AcntID, xRate : Decimal } let BudgetCurrency = < NoX : CurID | X : Exchange > let TaggedAcnt = { taAcnt : AcntID, taTags : List TagID } let Allocation = { alloTo : TaggedAcnt, alloAmts : List Amount, alloCur : BudgetCurrency } let Income = { incGross : Decimal , incCurrency : CurID , incWhen : DatePat , incFrom : {- this must be an income AcntID, and is the only place income accounts may be specified in the entire budget -} TaggedAcnt , incPretax : List Allocation , incTaxes : List Tax , incPosttax : List Allocation , incToBal : TaggedAcnt } let Transfer = { transFrom : TaggedAcnt , transTo : TaggedAcnt , transAmounts : List TimeAmount , transCurrency : BudgetCurrency } let AcntSet = { Type = { asList : List AcntID, asInclude : Bool } , default = { asList = [] : List AcntID, asInclude = False } } let ShadowMatch = { Type = { smFrom : AcntSet.Type , smTo : AcntSet.Type , smDate : Optional MatchDate , smVal : MatchVal.Type } , default = { smFrom = AcntSet.default , smTo = AcntSet.default , smDate = None MatchDate , smVal = MatchVal.default } } let ShadowTransfer = { stFrom : TaggedAcnt , stTo : TaggedAcnt , stCurrency : CurID , stDesc : Text , stMatch : ShadowMatch.Type , stRatio : Decimal } let Budget = { budgetLabel : Text , income : List Income , transfers : List Transfer , shadowTransfers : List ShadowTransfer } in { CurID , AcntID , SqlConfig , Currency , Tag , TagID , Interval , Global , Gregorian , GregorianM , TimeUnit , Weekday , RepeatPat , MDYPat , ModPat , WeekdayPat , CronPat , DatePat , Decimal , TxOpts , Match , MatchVal , MatchYMD , MatchDate , MatchOther , SplitNum , Field , FieldMap , Split , ExpSplit , SplitText , SplitCur , SplitAcnt , ToTx , Import , Manual , Statement , Transfer , Income , Budget , Tax , Allocation , Amount , TimeAmount , AmountType , ShadowMatch , ShadowTransfer , AcntSet , BudgetCurrency , Exchange , TaggedAcnt }