pwncash/dhall/Types.dhall

1248 lines
32 KiB
Plaintext

let Map =
https://prelude.dhall-lang.org/v21.1.0/Map/Type
sha256:210c7a9eba71efbb0f7a66b3dcf8b9d3976ffc2bc0e907aadfb6aa29c333e8ed
let List/map =
https://prelude.dhall-lang.org/v21.1.0/List/map
sha256:dd845ffb4568d40327f2a817eb42d1c6138b929ca758d50bc33112ef3c885680
let AccountTree
: Type
=
{-
Recursive type representing a tree of accounts.
A node in the tree can either be an account (leaf) which has a name
and description, or a placeholder (branch) which has name, description,
and a non-empty list of accounts or other placeholders.
-}
forall (a : Type) ->
forall ( Fix
: < AccountF : { _1 : Text, _2 : Text }
| PlaceholderF :
{ _1 : Text
, _2 : Text
, _3 :
{- TODO nonempty? -}
List a
}
> ->
a
) ->
a
let AccountTreeF =
{-
Fixed type abstraction for an account tree.
-}
\(a : Type) ->
< AccountF : { _1 : Text, _2 : Text }
| PlaceholderF : { _1 : Text, _2 : Text, _3 : List a }
>
let Account
: Text -> Text -> AccountTree
=
{-
Smart constructor to build an account node in an account tree.
-}
\(desc : Text) ->
\(name : Text) ->
\(a : Type) ->
let f = AccountTreeF a
in \(Fix : f -> a) -> Fix (f.AccountF { _1 = desc, _2 = name })
let Placeholder
: Text -> Text -> List AccountTree -> AccountTree
=
{-
Smart constructor to build a placeholder node in an account tree.
-}
\(desc : Text) ->
\(name : Text) ->
\(children : List AccountTree) ->
\(a : Type) ->
let f = AccountTreeF a
in \(Fix : f -> a) ->
let apply = \(x : AccountTree) -> x a Fix
in Fix
( f.PlaceholderF
{ _1 = desc
, _2 = name
, _3 = List/map AccountTree a apply children
}
)
let AcntID =
{-
A unique ID for an account; the exact ID associated with each account
depends on the path in which each account exists in a tree. If the leaf
node of an account's path is totally unique, this ID will be that leaf node.
If not, then branch nodes will be appended to the front (delimited by
underscores) until the ID is unique.
This ID will be used throughout the config to refer to a specific account.
-}
Text
let CurID =
{-
A unique, short (usually three uppercase characters) ID for a currency;
this symbol will be used throughout the configuration to signify a
particular currency
-}
Text
let Currency =
{-
A unit of exchange.
-}
{ curSymbol : CurID
, curFullname :
{-
The full description of this currency (eg "Yugoslavian Twitcoin")
-}
Text
, curPrecision :
{-
The number of decimal places for this currency
-}
Natural
}
let TagID =
{-
A unique ID for a tag. This ID will be used throughout the configuration
to refer to a specific tag.
-}
Text
let Tag =
{-
A short metadata identifier associated with an account or entry.
-}
{ tagID : TagID
, tagDesc :
{-
A description to convey the meaning of this tag.
-}
Text
}
let SqlConfig {- TODO pgsql -} =
{-
How to connect to a SQL database. Only SQLite is supported, in which case
the only parameter is the output path of the db file.
-}
< Sqlite : Text | Postgres >
let Gregorian =
{-
A full date like 1976-04-01
-}
{ gYear : Natural, gMonth : Natural, gDay : Natural }
let GregorianM =
{-
Like a Gregorian but without the month
-}
{ gmYear : Natural, gmMonth : Natural }
let Interval =
{-
An interval in time. If end is None, the interval ends at 'forever'
-}
{ intStart : Gregorian, intEnd : Optional Gregorian }
let TemporalScope =
{-
The range of times that will be considered when computing transactions.
-}
{ budgetInterval : Interval, statementInterval : Interval }
let TimeUnit = < Day | Week | Month | Year >
let Weekday = < Mon | Tue | Wed | Thu | Fri | Sat | Sun >
let RepeatPat =
{-
Means to match a repeated set of numeric values.
-}
{ rpStart :
{-
Initial value to match
-}
Natural
, rpBy :
{-
Distance between each repeated value
-}
Natural
, rpRepeats :
{-
Number of repeats after initial value to match. If not given, this
number continues until an upper bound determined from context.
-}
Optional Natural
}
let MDYPat =
{-
Means to match either a year, month, or day in a date (the matched component
is determined by context)
Single: match a single number
Multi: match several numbers
Repeat: match a repeated pattern
After: match any number greater than a given value
Before: match any number less than a given value
Between: match any number between two values
-}
< Single : Natural
| Multi : List Natural
| Repeat : RepeatPat
| After : Natural
| Before : Natural
| Between : { _between1 : Natural, _between2 : Natural }
>
let ModPat =
{-
Means to match a date using modular arithmetic.
-}
{ Type =
{ mpStart :
{-
The starting date to begin matching. If not given, start at the
beginning of whatever global time window is active.
-}
Optional Gregorian
, mpBy :
{-
Numeric number of temporal units to repeat before next match.
-}
Natural
, mpUnit :
{-
Unit of each interval
-}
TimeUnit
, mpRepeats :
{-
Number of repeats to match. If not given, match all repeats until
the end of the active global interval
-}
Optional Natural
}
, default = { mpStart = None Gregorian, mpRepeats = None Natural }
}
let WeekdayPat =
{-
Means to match a given day of week
OnDay: Match a single weekday
OnDays: Match multiple weekdays
-}
< OnDay : Weekday | OnDays : List Weekday >
let CronPat =
{-
Means of matching dates according to their component parts.
This is similar to 'cron' patterns in unix-like systems.
-}
{ Type =
{ cpWeekly : Optional WeekdayPat
, cpYear : Optional MDYPat
, cpMonth : Optional MDYPat
, cpDay : Optional MDYPat
}
, default =
{ cpWeekly = None WeekdayPat
, cpYear = None MDYPat
, cpMonth = None MDYPat
, cpDay = None MDYPat
}
}
let DatePat =
{-
Means of matching dates
Cron: use cron-like date matching
Mod: use modular temporal arithmetic matching
-}
< Cron : CronPat.Type | Mod : ModPat.Type >
let TxAmount1_ =
\(re : Type) ->
{ a1Column : Text
, a1Fmt :
{-
Format of the amount field. Must include three fields for the
sign, numerator, and denominator of the amount.
-}
re
}
let TxAmount1 =
{ Type = TxAmount1_ Text
, default = { a1Column = "Amount", a1Fmt = "([-+])?([0-9\\.]+)" }
}
let TxAmount2_ =
\(re : Type) ->
{ a2Positive : Text
, a2Negative : Text
, a2Fmt :
{-
Format of the amount field. Must include two fields for the
numerator and denominator of the amount.
-}
re
}
let TxAmount2 =
{ Type = TxAmount2_ Text
, default =
{ a2Positive = "Deposit"
, a2Negative = "Withdraw"
, a2Fmt = "([0-9\\.]+)"
}
}
let TxAmountSpec_ =
\(re : Type) ->
< AmountSingle : TxAmount1_ re | AmountDual : TxAmount2_ re >
let TxOpts_ =
{-
Additional metadata to use when parsing a statement
-}
\(re : Type) ->
{ toDate :
{-
Column title for date
-}
Text
, toAmount :
{-
Column title for amount
-}
TxAmountSpec_ re
, toDesc :
{-
Column title for description
-}
Text
, toOther :
{-
Titles of other columns to include; these will be available in
a map for use in downstream processing (see 'Field')
-}
List Text
, toDateFmt :
{-
Format of the date field as specified in the
Data.Time.Format.formattime Haskell function.
-}
Text
, toSkipBlankDate :
{-
Skip line if date field is a blank
-}
Bool
, toSkipBlankAmount :
{-
Skip line if amount field(s) is(are) a blank
-}
Bool
, toSkipBlankDescription :
{-
Skip line if description field is a blank
-}
Bool
, toSkipBlankOther :
{-
Skip line if any arbitrary fields are blank (these fields must also
be listed in 'toOther' to be considered)
-}
List Text
, toSkipMissingFields :
{-
Skip line if any fields are missing (this is different from blank;
'missing' means there is no field with name 'X', 'blank' means that
there is a field 'X' and its value is an empty string)
-}
Bool
}
let TxAmountSpec = TxAmountSpec_ Text
let TxOpts =
{ Type = TxOpts_ Text
, default =
{ toDate = "Date"
, toAmount = TxAmountSpec.AmountSingle TxAmount1::{=}
, toDesc = "Description"
, toOther = [] : List Text
, toDateFmt = "%0m/%0d/%Y"
, toSkipBlankDate = False
, toSkipBlankAmount = False
, toSkipBlankDescription = False
, toSkipBlankOther = [] : List Text
, toSkipMissingFields = False
}
}
let Field =
{-
General key-value type
-}
\(k : Type) -> \(v : Type) -> { fKey : k, fVal : v }
let FieldMap =
{-
Key-value type where key maps to a Map with key of the same type
-}
\(k : Type) -> \(v : Type) -> Field k (Map k v)
let ValMatcher =
{-
Means to match a decimal value.
-}
{ Type =
{ vmSign :
{-
Sign of value.
True -> positive,
False -> negative,
None -> do not consider.
-}
Optional Bool
, vmNum :
{-
Value of numerator to match. Do not consider numerator if none
-}
Optional Natural
, vmDen :
{-
Value of denominator to match. Do not consider numerator if none
-}
Optional Natural
, vmPrec :
{-
Precision of decimal to use when matching. This only affects the
denominator, such that a query of '10.1' with a precision of 2
will have a denominator of '10'
-}
Natural
}
, default =
{ vmSign = None Bool
, vmNum = None Natural
, vmDen = None Natural
, vmPrec = 2
}
}
let YMDMatcher =
{-
Means to match a given date with varying precision
-}
< Y : Natural | YM : GregorianM | YMD : Gregorian >
let DateMatcher =
{-
Means to match either one discrete date or a range of dates
-}
< On : YMDMatcher | In : { _1 : YMDMatcher, _2 : Natural } >
let FieldMatcher_ =
{-
Means to match a given field (either textual or numeric)
-}
\(re : Type) ->
< Desc : Field Text re | Val : Field Text ValMatcher.Type >
let FieldMatcher = FieldMatcher_ Text
let EntryNumGetter =
{-
Means to get a numeric value from a statement row.
LookupN: lookup the value from a field
ConstN: a constant value
AmountN: the value of the 'Amount' column times a scaling factor
BalanceN: the amount required to make the target account reach a balance
PercentN: the amount required to make an account reach a given percentage
-}
< LookupN : Text
| ConstN : Double
| AmountN : Double
| BalanceN : Double
| PercentN : Double
>
let LinkedNumGetter =
{-
Means to get a numeric value from another entry
-}
{ Type =
{ lngIndex :
{-
Index of the entry to link.
-}
Natural
, lngScale :
{-
Factor by which to multiply the value of the linked entry.
-}
Double
}
, default = { lngScale = 1.0, lngIndex = 0 }
}
let LinkedEntryNumGetter =
{-
Means to get a numeric value from a statement row or another entry getter.
Linked: a number referring to the entry on the 'from' side of the
transaction (with 0 being the primary entry)
Getter: a normal getter
-}
< Linked : LinkedNumGetter.Type | Getter : EntryNumGetter >
let EntryTextGetter =
{-
Means to get a textual value from a statement row.
ConstT: a constant value
LookupT: lookup the value of a field
MapT: use the value of a column as the key for a map
Map2T: use the paired value of 2 columns as the key for a map
-}
\(t : Type) ->
< ConstT : t
| LookupT : Text
| MapT : FieldMap Text t
| Map2T : FieldMap { _1 : Text, _2 : Text } t
>
let EntryCurGetter =
{-
Means to get a currency ID from a statement row.
-}
EntryTextGetter CurID
let EntryAcntGetter =
{-
Means to get an account ID from a statement row.
-}
EntryTextGetter AcntID
let Entry =
{-
General type describing a single line item in an account.
The polymorphism of this type allows representation of an actual line
item itself as well as the means to get a line item from other data.
-}
\(a : Type) ->
\(v : Type) ->
\(t : Type) ->
{ eAcnt :
{-
Pertains to account for this entry.
-}
a
, eValue :
{-
Pertains to value for this entry.
-}
v
, eComment :
{-
A short description of this entry (if none, use a blank string)
-}
Text
, eTags :
{-
Pertains to the tags to describe this entry.
-}
List t
}
let EntryGetter =
{-
Means for getting an entry from a given row in a statement (debit side)
-}
\(n : Type) ->
{ Type = Entry EntryAcntGetter n TagID
, default = { eComment = "", eTags = [] : List TagID }
}
let FromEntryGetter =
{-
Means for getting an entry from a given row in a statement (debit side)
-}
EntryGetter EntryNumGetter
let ToEntryGetter =
{-
Means for getting an entry from a given row in a statement (credit side)
-}
EntryGetter LinkedEntryNumGetter
let TxHalfGetter =
{-
Means of transforming one row in a statement to either the credit or debit
half of a transaction
-}
\(e : Type) ->
{ Type =
{ thgAcnt :
{-
Account from which this transaction will be balanced. The value
of the transaction will be assigned to this account unless
other entries are specified (see below).
This account (and its associated entry) will be denoted
'primary'.
-}
EntryAcntGetter
, thgEntries :
{-
Means of getting additional entries from which this transaction
will be balanced. If this list is empty, the total value of the
transaction will be assigned to the value defined by 'tsgAcnt'.
Otherwise, the entries specified here will be added to this side
of this transaction, and their sum value will be subtracted from
the total value of the transaction and assigned to 'tsgAcnt'.
This is useful for situations where a particular transaction
denotes values that come from multiple subaccounts.
-}
List e
, thgComment :
{-
Comment for the primary entry
-}
Text
, thgTags :
{-
Tags for the primary entry
-}
List TagID
}
, default =
{ thgTags = [] : List TagID
, thgComment = ""
, thgEntries = [] : List e
}
}
let FromTxHalfGetter = TxHalfGetter FromEntryGetter.Type
let ToTxHalfGetter = TxHalfGetter ToEntryGetter.Type
let TxSubGetter =
{-
A means for transforming one row in a statement to a transaction
-}
{ Type =
{ tsgValue : EntryNumGetter
, tsgCurrency : EntryCurGetter
, tsgFrom : (TxHalfGetter FromEntryGetter.Type).Type
, tsgTo : (TxHalfGetter ToEntryGetter.Type).Type
}
, default = { tsgFrom = TxHalfGetter, tsgTo = TxHalfGetter }
}
let TxGetter =
{-
A means for transforming one row in a statement to a transaction
-}
{ Type =
{ tgFrom : (TxHalfGetter FromEntryGetter.Type).Type
, tgTo : (TxHalfGetter ToEntryGetter.Type).Type
, tgScale : Double
, tgCurrency : EntryCurGetter
, tgOtherEntries : List TxSubGetter.Type
}
, default =
{ tgOtherEntries = [] : List TxSubGetter.Type
, tgFrom = TxHalfGetter
, tgTo = TxHalfGetter
, tgScale = 1.0
}
}
let StatementParser_ =
{-
A recipe to match and transform a given entry in a statement to a
transaction between 2 or more accounts.
Polymorphism allows regular expressions to be computed and cached within
the type during parsing.
-}
\(re : Type) ->
{ Type =
{ spDate :
{-
How to match the date column; if none match any date
-}
Optional DateMatcher
, spVal :
{-
How to match the value column; if none match any value
-}
ValMatcher.Type
, spDesc :
{-
Regular expression to match the description;
if none match anythingS
-}
Optional re
, spOther :
{-
How to match additional columns if present
-}
List (FieldMatcher_ re)
, spTx :
{-
How to translate the matched statement row into entries for
a transaction. If none, don't make a transaction (eg 'skip'
this row in the statement).
-}
Optional TxGetter.Type
, spTimes :
{-
Match at most this many rows; if none there is no limit
-}
Optional Natural
, spPriority :
{-
In case of multiple matches, higher priority gets precedence.
-}
Integer
}
, default =
{ spDate = None DateMatcher
, spVal = ValMatcher::{=}
, spDesc = None Text
, spOther = [] : List (FieldMatcher_ re)
, spTx = None TxGetter.Type
, spTimes = None Natural
, spPriority = +0
}
}
let StatementParser =
{-
A statement parser specialized to raw regular expressions.
-}
StatementParser_ Text
let Amount =
{-
A quantify of currency at a given time.
-}
\(w : Type) ->
\(v : Type) ->
{ Type =
{ amtWhen : w, amtValue : v, amtDesc : Text, amtPriority : Integer }
, default.amtPriority = +0
}
let TransferType =
{-
The type of a budget transfer.
BTFixed: Tranfer a fixed amount
BTPercent: Transfer a percent of the source account to destination
BTTarget: Transfer an amount such that the destination has a given target
value
-}
< TPercent | TBalance | TFixed >
let TransferValue =
{-
Means to determine the value of a budget transfer.
-}
{ Type = { tvVal : Double, tvType : TransferType }
, default.tvType = TransferType.TFixed
}
let Transfer =
{-
1-1 transaction(s) between two accounts.
-}
\(a : Type) ->
\(c : Type) ->
\(w : Type) ->
\(v : Type) ->
{ transFrom : a
, transTo : a
, transCurrency : c
, transAmounts : List (Amount w v).Type
}
let TaggedAcnt =
{-
An account with a tag
-}
{ Type = { taAcnt : AcntID, taTags : List TagID }
, default.taTags = [] : List TagID
}
let HistTransfer =
{-
A manually specified historical transfer
-}
Transfer TaggedAcnt.Type CurID DatePat TransferValue.Type
let TransferAmount = Amount DatePat TransferValue.Type
let Statement =
{-
How to import a statement from local file(s). Statements are assumed to be
tabular with one statement per row.
-}
{ stmtPaths
{-
paths to statement files
-}
: List Text
, stmtParsers
{-
parsers to match statements
-}
: List StatementParser.Type
, stmtDelim
{-
file delimiter as a numeric char, usually either tab (9) or comma (44)
-}
: Natural
, stmtTxOpts : TxOpts.Type
, stmtSkipLines
{-
how many lines to skip before parsing statement
-}
: Natural
}
let History =
{-
How to generate historical transactions; either specified as manual
transfers or via statements in files on local disk
-}
< HistTransfer : HistTransfer | HistStatement : Statement >
let Allocation =
{-
How to allocate a given budget stream. This can be thought of as a Transfer
without an incoming account specified.
-}
\(w : Type) ->
\(v : Type) ->
{ alloTo : TaggedAcnt.Type, alloAmts : List (Amount w v).Type }
let PretaxValue =
{-
How to determine value of a pretax allocation.
-}
{ preValue :
{-
The value to be deducted from gross income
-}
Double
, prePercent :
{-
If true, value is interpreted as a percent of gross income instead of
a fixed amount.
-}
Bool
, preCategory :
{-
A category for this allocation. This is used when calculating taxes,
which match against this to determine how much to deduct from the
gross income stream.
-}
Text
}
let TaxBracket =
{-
A single tax bracket. Read as "every unit above limit is taxed at this
percentage".
-}
{ tbLowerLimit : Double, tbPercent : Double }
let TaxProgression =
{-
A tax progression using a deductible and a series of tax brackets.
This will cover simple cases of the US income tax as of 2017 and similar.
-}
{ tpDeductible :
{-
Initial amount to subtract from after-pretax-deductions
-}
Double
, tpBrackets :
{-
Tax brackets to apply after deductions (order does not matter, each
entry will be sorted by limit)
-}
List TaxBracket
}
let TaxMethod =
{-
How to implement a given tax (either a progressive tax or a fixed percent)
-}
< TMBracket : TaxProgression | TMPercent : Double >
let TaxValue =
{-
Means to determine value of an income tax allocation.
-}
{ tvCategories :
{-
A list of categories corresponding to pretax allocations. Taxable
income (from the perspective of this type) will be determined by
subtracting matching allocations from gross income.
-}
List Text
, tvMethod : TaxMethod
}
let PosttaxValue =
{-
Means to determine value of a post tax allocation.
-}
{ postValue :
{-
The value to be deducted from income remaining after taxes.
-}
Double
, postPercent :
{-
If true, subtract a percentage from the after-tax remainder instead
of a fixed value.
-}
Bool
}
let SingleAllocation =
{-
An allocation specialized to an income stream (which means the timing is
dictated by the income stream)
-}
Allocation {}
let SingleAlloAmount = \(v : Type) -> Amount {} v
let MultiAllocation =
{-
An allocation specialized to capturing multiple income streams within a given
time period (useful for instances where an allocation might change independent
of a change in income)
-}
Allocation Interval
let MultiAlloAmount = \(v : Type) -> Amount Interval v
let HourlyPeriod =
{-
Definition for a pay period denominated in hours
-}
{ hpAnnualHours :
{-
Number of hours in one year
-}
Natural
, hpDailyHours :
{-
Number of hours in one working day
-}
Natural
, hpWorkingDays :
{-
Days which count as working days
-}
List Weekday
}
let PeriodType =
{-
Type of pay period.
Hourly: pay period is denominated in hours
Daily: pay period is denominated in working days (specified in a list)
-}
< Hourly : HourlyPeriod | Daily : List Weekday >
let Period =
{-
Definition of a pay period
-} { pType :
{-
Type of pay period
-}
PeriodType
, pStart :
{-
Start date of the pay period. Must occur before first payment
in this income stream is dispersed.
-}
Gregorian
}
let Income =
{-
Means to compute an income stream and how to allocate it
-}
{ Type =
{ incGross :
{-
The value of the income stream.
-}
Double
, incCurrency :
{-
The currency in which the income stream is denominated.
-}
CurID
, incWhen :
{-
The dates on which the income stream is distributed.
-}
DatePat
, incPayPeriod :
{-
Defines the period of time over which this income was earned
(mostly used for taxes)
-}
Period
, incPretax : List (SingleAllocation PretaxValue)
, incTaxes : List (SingleAllocation TaxValue)
, incPosttax : List (SingleAllocation PosttaxValue)
, incFrom :
{-
The account in which the income is recorded.
This must be an income AcntID, and is the only place income
accounts may be specified in the entire budget.
-}
TaggedAcnt.Type
, incToBal :
{-
The account to which to send the remainder of the income stream
(if any) after all allocations have been applied.
-}
TaggedAcnt.Type
, incPriority : Integer
}
, default =
{ incPretax = [] : List (SingleAllocation PretaxValue)
, incTaxes = [] : List (SingleAllocation TaxValue)
, incPosttaxx = [] : List (SingleAllocation PosttaxValue)
, incPriority = +0
}
}
let AcntMatcher_ =
{-
Regex pattern by which matching account ids will be identified
-}
\(re : Type) ->
{ Type = { amPat : re, amInvert : Bool }, default.amInvert = False }
let AcntMatcher = AcntMatcher_ Text
let TransferMatcher_ =
{-
Means to match a transfer (which will be used to "clone" it in some
fashion)
-}
\(re : Type) ->
{ tmFrom : Optional (AcntMatcher_ re).Type
, tmTo : Optional (AcntMatcher_ re).Type
, tmDate :
{-
If given, means to match the date of a transfer.
-}
Optional DateMatcher
, tmVal :
{-
If given, means to match the value of a transfer.
-}
ValMatcher.Type
}
let TransferMatcher =
{ Type = TransferMatcher_ Text
, default =
{ tmFrom = None AcntMatcher.Type
, tmTo = None AcntMatcher.Type
, tmDate = None DateMatcher
, tmVal = ValMatcher.default
}
}
let ShadowTransfer =
{-
A transaction analogous to another transfer with given properties.
-}
{ stFrom :
{-
Source of this transfer
-}
TaggedAcnt.Type
, stTo :
{-
Destination of this transfer.
-}
TaggedAcnt.Type
, stCurrency :
{-
Currency of this transfer.
-}
CurID
, stDesc :
{-
Description of this transfer.
-}
Text
, stMatch :
{-
Means to match other transfers which will be used as the basis to
compute this transfer. The date is taken as-is, the value is
multiplied by a constant (see 'stRatio') and everything else is
specified in other fields of this type.
-}
TransferMatcher.Type
, stRatio :
{-
Fixed multipler to translate value of matched transfer to this one.
-}
Double
}
let BudgetTransfer =
{-
A manually specified transaction for a budget
-}
HistTransfer
let Budget =
{-
A hypothetical set of transactions (eg a "budget") to be generated
and inserted into the database.
-}
{ bgtLabel :
{-
A unique label for this budget.
Can be useful to compare multiple potential futures.
-}
Text
, bgtIncomes : List Income.Type
, bgtPretax : List (MultiAllocation PretaxValue)
, bgtTax : List (MultiAllocation TaxValue)
, bgtPosttax : List (MultiAllocation PosttaxValue)
, bgtTransfers : List BudgetTransfer
, bgtShadowTransfers : List ShadowTransfer
, bgtInterval : Optional Interval
}
in { CurID
, AcntID
, SqlConfig
, Currency
, Tag
, TagID
, Interval
, TemporalScope
, Gregorian
, GregorianM
, TimeUnit
, Weekday
, RepeatPat
, MDYPat
, ModPat
, WeekdayPat
, CronPat
, DatePat
, TxOpts
, TxOpts_
, StatementParser
, StatementParser_
, ValMatcher
, YMDMatcher
, DateMatcher
, FieldMatcher
, FieldMatcher_
, EntryNumGetter
, LinkedEntryNumGetter
, LinkedNumGetter
, Field
, FieldMap
, Entry
, FromEntryGetter
, ToEntryGetter
, EntryTextGetter
, EntryCurGetter
, EntryAcntGetter
, Statement
, History
, Transfer
, Income
, Budget
, Allocation
, Amount
, TransferMatcher_
, TransferMatcher
, ShadowTransfer
, TaggedAcnt
, AccountTree
, Account
, Placeholder
, PretaxValue
, PosttaxValue
, TaxBracket
, TaxProgression
, TaxMethod
, TaxValue
, TransferValue
, TransferType
, TxGetter
, TxSubGetter
, TxHalfGetter
, FromTxHalfGetter
, ToTxHalfGetter
, HistTransfer
, SingleAllocation
, MultiAllocation
, HourlyPeriod
, Period
, PeriodType
, TransferAmount
, MultiAlloAmount
, SingleAlloAmount
, AcntMatcher_
, AcntMatcher
, TxAmountSpec
, TxAmountSpec_
, TxAmount1_
, TxAmount2_
, TxAmount1
, TxAmount2
, BudgetTransfer
}