pwncash/dhall/Types.dhall

1247 lines
32 KiB
Plaintext
Raw Normal View History

2022-12-14 23:59:23 -05:00
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
2022-12-14 23:59:23 -05:00
let AccountTree
: Type
=
{-
Recursive type representing a tree of accounts.
2022-12-14 23:59:23 -05:00
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
2023-02-26 22:53:12 -05:00
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
2023-05-04 21:48:21 -04:00
, 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
2022-12-14 23:59:23 -05:00
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
}
2022-12-14 23:59:23 -05:00
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 >
2023-02-26 22:53:12 -05:00
let Gregorian =
{-
A full date like 1976-04-01
-}
{ gYear : Natural, gMonth : Natural, gDay : Natural }
2022-12-14 23:59:23 -05:00
let GregorianM =
{-
Like a Gregorian but without the month
-}
{ gmYear : Natural, gmMonth : Natural }
2022-12-14 23:59:23 -05:00
let Interval =
{-
An interval in time. If end is None, the interval ends at 'forever'
-}
{ intStart : Gregorian, intEnd : Optional Gregorian }
2022-12-14 23:59:23 -05:00
let TemporalScope =
{-
The range of times that will be considered when computing transactions.
-}
{ budgetInterval : Interval, statementInterval : Interval }
2022-12-14 23:59:23 -05:00
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
}
2022-12-14 23:59:23 -05:00
2023-02-09 20:01:43 -05:00
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
-}
2023-02-09 20:01:43 -05:00
< Single : Natural
| Multi : List Natural
| Repeat : RepeatPat
| After : Natural
| Before : Natural
| Between : { _between1 : Natural, _between2 : Natural }
>
2022-12-14 23:59:23 -05:00
let ModPat =
{-
Means to match a date using modular arithmetic.
-}
2022-12-14 23:59:23 -05:00
{ 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
2022-12-14 23:59:23 -05:00
}
, 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 >
2022-12-14 23:59:23 -05:00
let CronPat =
{-
Means of matching dates according to their component parts.
This is similar to 'cron' patterns in unix-like systems.
-}
2022-12-14 23:59:23 -05:00
{ Type =
2023-04-30 22:54:20 -04:00
{ cpWeekly : Optional WeekdayPat
, cpYear : Optional MDYPat
, cpMonth : Optional MDYPat
, cpDay : Optional MDYPat
2022-12-14 23:59:23 -05:00
}
, default =
2023-04-30 22:54:20 -04:00
{ cpWeekly = None WeekdayPat
, cpYear = None MDYPat
, cpMonth = None MDYPat
, cpDay = None MDYPat
2022-12-14 23:59:23 -05:00
}
}
let DatePat =
{-
Means of matching dates
Cron: use cron-like date matching
Mod: use modular temporal arithmetic matching
-}
< Cron : CronPat.Type | Mod : ModPat.Type >
2022-12-14 23:59:23 -05:00
2023-08-16 21:04:16 -04:00
let TxAmount1_ =
2023-08-16 21:01:06 -04:00
\(re : Type) ->
{ a1Column : Text
, a1Fmt :
{-
Format of the amount field. Must include three fields for the
sign, numerator, and denominator of the amount.
-}
re
}
2023-08-16 21:12:11 -04:00
let TxAmount1 =
{ Type = TxAmount1_ Text
, default = { a1Column = "Amount", a1Fmt = "([-+])?([0-9\\.]+)" }
}
2023-08-16 21:04:16 -04:00
let TxAmount2_ =
2023-08-16 21:01:06 -04:00
\(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
}
2023-08-16 21:12:11 -04:00
let TxAmount2 =
{ Type = TxAmount2_ Text
, default =
{ a2Positive = "Deposit"
, a2Negative = "Withdraw"
, a2Fmt = "([0-9\\.]+)"
}
}
2023-08-16 21:04:16 -04:00
let TxAmountSpec_ =
2023-08-16 21:01:06 -04:00
\(re : Type) ->
2023-08-16 21:04:16 -04:00
< AmountSingle : TxAmount1_ re | AmountDual : TxAmount2_ re >
2023-08-16 21:01:06 -04:00
2023-07-07 20:42:41 -04:00
let TxOpts_ =
2023-08-16 21:01:06 -04:00
{-
Additional metadata to use when parsing a statement
-}
2023-07-07 20:20:09 -04:00
\(re : Type) ->
2023-08-16 21:01:06 -04:00
{ toDate :
{-
Column title for date
-}
Text
, toAmount :
{-
Column title for amount
-}
2023-08-16 21:04:16 -04:00
TxAmountSpec_ re
2023-08-16 21:01:06 -04:00
, 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
2023-08-16 22:24:20 -04:00
, 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
2022-12-14 23:59:23 -05:00
}
2023-08-16 21:04:16 -04:00
let TxAmountSpec = TxAmountSpec_ Text
2023-08-16 21:01:06 -04:00
let TxOpts =
{ Type = TxOpts_ Text
, default =
{ toDate = "Date"
2023-08-16 21:12:11 -04:00
, toAmount = TxAmountSpec.AmountSingle TxAmount1::{=}
2023-08-16 21:01:06 -04:00
, toDesc = "Description"
, toOther = [] : List Text
, toDateFmt = "%0m/%0d/%Y"
, toSkipBlankDate = False
, toSkipBlankAmount = False
, toSkipBlankDescription = False
, toSkipBlankOther = [] : List Text
2023-08-16 22:24:20 -04:00
, toSkipMissingFields = False
2023-08-16 21:01:06 -04:00
}
}
2023-07-07 20:42:41 -04:00
let Field =
{-
General key-value type
-}
\(k : Type) -> \(v : Type) -> { fKey : k, fVal : v }
2022-12-14 23:59:23 -05:00
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)
2022-12-14 23:59:23 -05:00
let ValMatcher =
{-
Means to match a decimal value.
-}
2022-12-14 23:59:23 -05:00
{ Type =
2023-04-30 22:54:20 -04:00
{ vmSign :
{-
Sign of value.
True -> positive,
False -> negative,
None -> do not consider.
-}
Optional Bool
2023-04-30 22:54:20 -04:00
, vmNum :
{-
Value of numerator to match. Do not consider numerator if none
-}
Optional Natural
2023-04-30 22:54:20 -04:00
, vmDen :
{-
Value of denominator to match. Do not consider numerator if none
-}
Optional Natural
2023-04-30 22:54:20 -04:00
, 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
2022-12-14 23:59:23 -05:00
}
, default =
2023-04-30 22:54:20 -04:00
{ vmSign = None Bool
, vmNum = None Natural
, vmDen = None Natural
, vmPrec = 2
2022-12-14 23:59:23 -05:00
}
}
let YMDMatcher =
{-
Means to match a given date with varying precision
-}
< Y : Natural | YM : GregorianM | YMD : Gregorian >
2022-12-14 23:59:23 -05:00
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 >
2022-12-14 23:59:23 -05:00
let FieldMatcher = FieldMatcher_ Text
2023-04-17 00:34:09 -04:00
let EntryNumGetter =
{-
Means to get a numeric value from a statement row.
2022-12-14 23:59:23 -05:00
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
>
2023-06-19 12:14:18 -04:00
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
}
2023-06-19 13:00:23 -04:00
, default = { lngScale = 1.0, lngIndex = 0 }
2023-06-19 12:14:18 -04:00
}
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
-}
2022-12-14 23:59:23 -05:00
\(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
2022-12-14 23:59:23 -05:00
let Entry =
{-
General type describing a single line item in an account.
2022-12-14 23:59:23 -05:00
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.
-}
2022-12-14 23:59:23 -05:00
\(a : Type) ->
\(v : Type) ->
2023-02-27 22:15:03 -05:00
\(t : Type) ->
2023-04-30 22:54:20 -04:00
{ eAcnt :
{-
Pertains to account for this entry.
-}
a
2023-04-30 22:54:20 -04:00
, eValue :
{-
Pertains to value for this entry.
-}
v
2023-04-30 22:54:20 -04:00
, eComment :
{-
A short description of this entry (if none, use a blank string)
-}
Text
2023-04-30 22:54:20 -04:00
, eTags :
{-
Pertains to the tags to describe this entry.
-}
List t
2023-02-27 22:15:03 -05:00
}
2022-12-14 23:59:23 -05:00
let EntryGetter =
{-
2023-06-19 12:14:18 -04:00
Means for getting an entry from a given row in a statement (debit side)
-}
2023-06-19 12:14:18 -04:00
\(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
}
}
2023-06-19 12:41:57 -04:00
let FromTxHalfGetter = TxHalfGetter FromEntryGetter.Type
2023-06-19 12:43:16 -04:00
let ToTxHalfGetter = TxHalfGetter ToEntryGetter.Type
2023-06-19 12:41:57 -04:00
let TxSubGetter =
{-
A means for transforming one row in a statement to a transaction
-}
2023-06-17 00:16:01 -04:00
{ Type =
2023-06-19 12:14:18 -04:00
{ tsgValue : EntryNumGetter
2023-06-17 00:16:01 -04:00
, tsgCurrency : EntryCurGetter
2023-06-19 12:14:18 -04:00
, tsgFrom : (TxHalfGetter FromEntryGetter.Type).Type
, tsgTo : (TxHalfGetter ToEntryGetter.Type).Type
2023-06-17 00:16:01 -04:00
}
2023-06-19 12:14:18 -04:00
, default = { tsgFrom = TxHalfGetter, tsgTo = TxHalfGetter }
2022-12-14 23:59:23 -05:00
}
let TxGetter =
{-
A means for transforming one row in a statement to a transaction
-}
2023-06-17 00:16:01 -04:00
{ Type =
2023-06-19 12:14:18 -04:00
{ tgFrom : (TxHalfGetter FromEntryGetter.Type).Type
, tgTo : (TxHalfGetter ToEntryGetter.Type).Type
, tgScale : Double
2023-06-19 12:14:18 -04:00
, tgCurrency : EntryCurGetter
, tgOtherEntries : List TxSubGetter.Type
2023-06-17 00:16:01 -04:00
}
, default =
{ tgOtherEntries = [] : List TxSubGetter.Type
2023-06-19 12:44:14 -04:00
, tgFrom = TxHalfGetter
, tgTo = TxHalfGetter
, tgScale = 1.0
2023-06-17 00:16:01 -04:00
}
2022-12-14 23:59:23 -05:00
}
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.
-}
2023-04-17 00:34:09 -04:00
\(re : Type) ->
{ Type =
2023-04-30 22:54:20 -04:00
{ spDate :
{-
How to match the date column; if none match any date
-}
Optional DateMatcher
2023-04-30 22:54:20 -04:00
, spVal :
{-
How to match the value column; if none match any value
-}
ValMatcher.Type
2023-04-30 22:54:20 -04:00
, spDesc :
{-
Regular expression to match the description;
if none match anythingS
-}
Optional re
2023-04-30 22:54:20 -04:00
, spOther :
{-
How to match additional columns if present
-}
List (FieldMatcher_ re)
2023-04-30 22:54:20 -04:00
, 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).
-}
2023-06-17 00:16:01 -04:00
Optional TxGetter.Type
2023-04-30 22:54:20 -04:00
, spTimes :
{-
Match at most this many rows; if none there is no limit
-}
Optional Natural
2023-04-30 22:54:20 -04:00
, spPriority :
{-
In case of multiple matches, higher priority gets precedence.
-}
Integer
2023-04-17 00:34:09 -04:00
}
, default =
2023-04-30 22:54:20 -04:00
{ spDate = None DateMatcher
, spVal = ValMatcher::{=}
, spDesc = None Text
, spOther = [] : List (FieldMatcher_ re)
2023-06-17 00:16:01 -04:00
, spTx = None TxGetter.Type
2023-04-30 22:54:20 -04:00
, spTimes = None Natural
, spPriority = +0
2022-12-14 23:59:23 -05:00
}
}
2023-04-17 00:34:09 -04:00
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) ->
2023-07-07 20:20:09 -04:00
{ Type =
{ amtWhen : w, amtValue : v, amtDesc : Text, amtPriority : Integer }
, default.amtPriority = +0
}
2022-12-14 23:59:23 -05:00
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
2023-07-07 20:20:09 -04:00
, 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
2023-07-07 20:42:41 -04:00
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
2023-07-07 20:42:41 -04:00
, stmtTxOpts : TxOpts.Type
, stmtSkipLines
{-
how many lines to skip before parsing statement
-}
: Natural
2022-12-14 23:59:23 -05:00
}
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) ->
2023-07-08 19:05:34 -04:00
{ alloTo : TaggedAcnt.Type, alloAmts : List (Amount w v).Type }
2023-02-12 16:23:32 -05:00
let PretaxValue =
{-
How to determine value of a pretax allocation.
-}
{ preValue :
{-
The value to be deducted from gross income
-}
2023-05-04 21:48:21 -04:00
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
}
2022-12-14 23:59:23 -05:00
let TaxBracket =
{-
A single tax bracket. Read as "every unit above limit is taxed at this
percentage".
-}
2023-05-04 21:48:21 -04:00
{ tbLowerLimit : Double, tbPercent : Double }
2022-12-14 23:59:23 -05:00
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.
-}
2023-04-30 22:54:20 -04:00
{ tpDeductible :
{-
Initial amount to subtract from after-pretax-deductions
-}
2023-05-04 21:48:21 -04:00
Double
2023-04-30 22:54:20 -04:00
, tpBrackets :
{-
Tax brackets to apply after deductions (order does not matter, each
entry will be sorted by limit)
-}
List TaxBracket
}
2023-02-26 12:03:35 -05:00
let TaxMethod =
{-
How to implement a given tax (either a progressive tax or a fixed percent)
-}
2023-05-04 21:48:21 -04:00
< TMBracket : TaxProgression | TMPercent : Double >
2023-02-26 12:03:35 -05:00
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
}
2023-02-26 22:53:12 -05:00
let PosttaxValue =
{-
Means to determine value of a post tax allocation.
-}
{ postValue :
{-
The value to be deducted from income remaining after taxes.
-}
2023-05-04 21:48:21 -04:00
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 {}
2023-07-07 20:42:41 -04:00
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
2023-01-29 18:04:24 -05:00
2023-07-07 20:42:41 -04:00
let MultiAlloAmount = \(v : Type) -> Amount Interval v
2023-05-14 19:20:10 -04:00
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
}
2022-12-14 23:59:23 -05:00
let Income =
{-
Means to compute an income stream and how to allocate it
-}
2023-03-16 23:55:59 -04:00
{ Type =
{ incGross :
{-
The value of the income stream.
-}
2023-05-04 21:48:21 -04:00
Double
, incCurrency :
{-
The currency in which the income stream is denominated.
-}
CurID
, incWhen :
{-
The dates on which the income stream is distributed.
-}
DatePat
2023-05-14 19:20:10 -04:00
, 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)
2023-03-16 23:55:59 -04:00
, 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
2023-03-16 23:55:59 -04:00
}
, default =
{ incPretax = [] : List (SingleAllocation PretaxValue)
, incTaxes = [] : List (SingleAllocation TaxValue)
, incPosttaxx = [] : List (SingleAllocation PosttaxValue)
, incPriority = +0
2023-03-16 23:55:59 -04:00
}
2022-12-14 23:59:23 -05:00
}
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
2023-02-13 19:57:39 -05:00
, default =
{ tmFrom = None AcntMatcher.Type
, tmTo = None AcntMatcher.Type
2023-04-30 22:54:20 -04:00
, tmDate = None DateMatcher
, tmVal = ValMatcher.default
2023-02-13 19:57:39 -05:00
}
}
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.
-}
2023-06-30 23:54:39 -04:00
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.
-}
2023-05-04 21:48:21 -04:00
Double
2023-02-13 19:57:39 -05:00
}
let BudgetTransfer =
{-
A manually specified transaction for a budget
-}
HistTransfer
2023-02-05 18:45:56 -05:00
let Budget =
{-
A hypothetical set of transactions (eg a "budget") to be generated
and inserted into the database.
-}
2023-04-30 22:54:20 -04:00
{ bgtLabel :
{-
A unique label for this budget.
Can be useful to compare multiple potential futures.
-}
Text
2023-04-30 22:54:20 -04:00
, bgtIncomes : List Income.Type
, bgtPretax : List (MultiAllocation PretaxValue)
, bgtTax : List (MultiAllocation TaxValue)
, bgtPosttax : List (MultiAllocation PosttaxValue)
, bgtTransfers : List BudgetTransfer
, bgtShadowTransfers : List ShadowTransfer
2023-05-29 18:15:01 -04:00
, bgtInterval : Optional Interval
2023-02-13 19:57:39 -05:00
}
2022-12-14 23:59:23 -05:00
in { CurID
, AcntID
, SqlConfig
, Currency
2023-02-26 22:53:12 -05:00
, Tag
2023-02-27 21:57:35 -05:00
, TagID
2022-12-14 23:59:23 -05:00
, Interval
, TemporalScope
2022-12-14 23:59:23 -05:00
, Gregorian
, GregorianM
, TimeUnit
, Weekday
, RepeatPat
, MDYPat
, ModPat
, WeekdayPat
, CronPat
, DatePat
, TxOpts
2023-07-07 20:42:41 -04:00
, TxOpts_
, StatementParser
, StatementParser_
, ValMatcher
, YMDMatcher
, DateMatcher
, FieldMatcher
, FieldMatcher_
, EntryNumGetter
2023-06-19 12:14:18 -04:00
, LinkedEntryNumGetter
, LinkedNumGetter
2022-12-14 23:59:23 -05:00
, Field
, FieldMap
, Entry
2023-06-19 12:14:18 -04:00
, FromEntryGetter
, ToEntryGetter
, EntryTextGetter
, EntryCurGetter
, EntryAcntGetter
2022-12-14 23:59:23 -05:00
, Statement
, History
2023-01-30 21:12:08 -05:00
, Transfer
2022-12-15 22:55:12 -05:00
, Income
2022-12-14 23:59:23 -05:00
, Budget
2023-01-29 18:04:24 -05:00
, Allocation
2023-01-29 18:14:00 -05:00
, Amount
, TransferMatcher_
, TransferMatcher
2023-02-13 19:57:39 -05:00
, ShadowTransfer
2023-02-26 22:53:12 -05:00
, TaggedAcnt
2023-06-11 12:27:57 -04:00
, AccountTree
, Account
, Placeholder
, PretaxValue
, PosttaxValue
, TaxBracket
, TaxProgression
, TaxMethod
, TaxValue
, TransferValue
, TransferType
2023-04-30 11:52:30 -04:00
, TxGetter
2023-06-16 23:46:09 -04:00
, TxSubGetter
2023-06-19 12:39:56 -04:00
, TxHalfGetter
2023-06-19 12:41:57 -04:00
, FromTxHalfGetter
, ToTxHalfGetter
2023-04-30 12:00:35 -04:00
, HistTransfer
2023-04-30 15:23:29 -04:00
, SingleAllocation
, MultiAllocation
2023-05-14 19:20:10 -04:00
, HourlyPeriod
, Period
, PeriodType
2023-07-07 20:42:41 -04:00
, TransferAmount
, MultiAlloAmount
, SingleAlloAmount
, AcntMatcher_
, AcntMatcher
2023-08-16 21:01:06 -04:00
, TxAmountSpec
2023-08-16 21:04:16 -04:00
, TxAmountSpec_
, TxAmount1_
, TxAmount2_
2023-08-16 21:12:11 -04:00
, TxAmount1
, TxAmount2
2022-12-14 23:59:23 -05:00
}