2000-07-17 03:26:56 -05:00
|
|
|
@node Engine, Register, Top Level, Top
|
|
|
|
@chapter Engine
|
2000-08-31 03:50:20 -05:00
|
|
|
@cindex The Engine
|
2000-08-23 23:34:03 -05:00
|
|
|
|
2000-08-31 03:50:20 -05:00
|
|
|
The Engine provides an interface to a financial engine with three basic
|
2000-08-23 23:34:03 -05:00
|
|
|
financial entities: Accounts, Transactions (known as Journal Entries in
|
|
|
|
accounting practice), and Splits (known as Ledger Entries). These three
|
|
|
|
entities are the central data structures of the GnuCash financial data
|
|
|
|
model.
|
|
|
|
|
|
|
|
In addition, the Engine provides the abstraction of Account Groups
|
|
|
|
(collections of releated accounts) and Sessions. A Session abstracts
|
|
|
|
a file-editing session allowing transparent support for locking and
|
|
|
|
implementation with other backends such as SQL.
|
|
|
|
|
|
|
|
The Engine code contains no GUI code whatsoever and is designed to
|
|
|
|
be created as a shared library for use by other programs.
|
|
|
|
|
|
|
|
@menu
|
2000-08-31 03:50:20 -05:00
|
|
|
* Engine Introduction::
|
2000-08-23 23:34:03 -05:00
|
|
|
* Globally Unique Identifiers::
|
|
|
|
* Key-Value Pair Frames::
|
2000-08-24 16:59:38 -05:00
|
|
|
* Splits::
|
2000-08-31 03:50:20 -05:00
|
|
|
* Transactions::
|
|
|
|
* Accounts::
|
|
|
|
* Account Groups::
|
|
|
|
* Sessions::
|
2000-08-23 23:34:03 -05:00
|
|
|
@end menu
|
|
|
|
|
|
|
|
|
2000-08-31 03:50:20 -05:00
|
|
|
@node Engine Introduction, Globally Unique Identifiers, Engine, Engine
|
|
|
|
@section Introduction
|
|
|
|
|
|
|
|
Splits (@pxref{Splits}), or "Journal Entries" are the fundamental
|
|
|
|
accounting units. Each Split consists of a quantity (number of dollar
|
|
|
|
bills, number of shares, etc.), the price of that quantity (the price of
|
|
|
|
one dollar is 1.00 dollars, etc.), a Memo, a pointer to the parent
|
|
|
|
Transaction, a pointer to the debited Account, a reconciled flag and
|
|
|
|
timestamp, an "Action" field, and a key-value frame which can store
|
|
|
|
arbitrary data (@pxref{Key-Value Pair Frames}).
|
|
|
|
|
|
|
|
Transactions (@pxref{Transactions}) embody the notion of "double entry"
|
|
|
|
accounting. A Transaction consists of a date, a description, a number, a
|
|
|
|
list of one or more Splits, and a key-value frame. When double-entry
|
|
|
|
rules are properly enabled in the engine (they are settable with various
|
|
|
|
flags), the total value of the splits is forced to be zero. Note that
|
|
|
|
if there is just one split, its value must be zero; this is useful
|
|
|
|
because a zero-valued split can store a price (useful for e.g. tracking
|
|
|
|
stocks). If there are two splits, then the value of one must be
|
|
|
|
positive, the other negative: this denotes that one account is credited,
|
|
|
|
and another is debited by an equal amount. Positive Split values are
|
|
|
|
'debits' and negative Split values are 'credits'. Forcing the Splits to
|
|
|
|
'add up' to zero causes a double-entry accounting system to always
|
|
|
|
balance.
|
|
|
|
|
|
|
|
Through various flags, forced double-entry can be disabled; this is
|
|
|
|
often desirable for novice, home-oriented users. As an alternative, it
|
|
|
|
may be better to leave double-entry enabled, but credit all dangling
|
|
|
|
splits to some dummy account, and then simply not show that dummy
|
|
|
|
account to the user.
|
|
|
|
|
|
|
|
Note the sum of the values of Splits in a Transaction is always computed
|
|
|
|
with respect to a currency; thus splits can be balanced even when they
|
|
|
|
are in different currencies, as long as they share a common currency.
|
|
|
|
The conversion price is simply the price stored in the Split. This
|
|
|
|
feature allows currency-trading accounts to be established.
|
|
|
|
|
|
|
|
Every Split must point at its parent Transaction, and that Transaction
|
|
|
|
must in turn include that Split in the Transaction's list of Splits. A
|
|
|
|
Split can belong to at most one Transaction. These relationships are
|
|
|
|
forced by the engine. The engine user cannnot accidentally destroy this
|
|
|
|
relationship as long as they stick to using the API and never access
|
|
|
|
internal structures directly.
|
|
|
|
|
|
|
|
Splits are grouped into Accounts (@pxref{Accounts}). Each Account
|
|
|
|
consists of a list of Splits that debit that Account. To ensure
|
|
|
|
consistency, if a Split points at an Account, then the Account must
|
|
|
|
point at the Split, and vice-versa. A Split can belong to at most one
|
|
|
|
Account. Besides merely containing a list of Splits, the Account
|
|
|
|
structure also give the Account a name, a code number, description and
|
|
|
|
notes fields, a key-value frame, a pointer to the currency that is used
|
|
|
|
for all splits in this account, and a pointer to the "security" used for
|
|
|
|
all splits in this account. The "security" can be the name of a stock
|
|
|
|
(e.g. "IBM", "McDonald's"), or another currency (e.g. "USD", "GBP").
|
|
|
|
The security is used during Transaction balancing to enable trading
|
|
|
|
between accounts denominated in different currencies, or to, for
|
|
|
|
example, move stocks from one Account to another.
|
|
|
|
|
|
|
|
Accounts can be arranged in a hierarchical tree. The nodes of the tree
|
|
|
|
are called "Account Groups" (@pxref{Account Groups}). By accounting
|
|
|
|
convention, the value of an Account is equal to the value of all of its
|
|
|
|
Splits plus the value of all of its sub-Accounts.
|
|
|
|
|
|
|
|
|
|
|
|
@node Globally Unique Identifiers, Key-Value Pair Frames, Engine Introduction, Engine
|
2000-08-23 23:34:03 -05:00
|
|
|
@section Globally Unique Identifiers
|
|
|
|
@tindex GUID
|
|
|
|
|
|
|
|
|
2000-08-31 03:50:20 -05:00
|
|
|
@node Key-Value Pair Frames, Splits, Globally Unique Identifiers, Engine
|
2000-08-23 23:34:03 -05:00
|
|
|
@section Key-Value Pair Frames
|
2000-08-25 20:05:09 -05:00
|
|
|
@cindex Key-Value Pairs
|
2000-08-23 23:34:03 -05:00
|
|
|
|
|
|
|
The number and types of data items which are associated with the
|
|
|
|
financial abstractions (Accounts, Transactions, and Splits) can vary
|
|
|
|
widely. For example, an Account which represents a user's checking
|
|
|
|
account might need to store the bank name, a telephone number, and a
|
|
|
|
username for online banking purposes. Another Account representing the
|
|
|
|
user's ownership of a stock might need to store information about
|
|
|
|
retrieving price quotes online such as the ticker symbol and the
|
|
|
|
exchange.
|
|
|
|
|
2000-08-29 02:08:36 -05:00
|
|
|
To meet this need for varying data storage, the GnuCash accounting
|
|
|
|
entities use Key-Value Pair Frames (hereafter referred to as the
|
|
|
|
datatype @code{kvp_frame}). A @code{kvp_frame} is a set of associations
|
|
|
|
between character strings (keys) and @code{kvp_value} structures. A
|
|
|
|
@code{kvp_value} is a union with possible types enumerated in the
|
|
|
|
@code{kvp_value_t} enum which indicates the type of data stored in a
|
|
|
|
@code{kvp_value} object.
|
2000-08-23 23:34:03 -05:00
|
|
|
|
2000-08-25 20:05:09 -05:00
|
|
|
@menu
|
|
|
|
* kvp_frame::
|
|
|
|
* kvp_value::
|
2000-08-26 02:52:05 -05:00
|
|
|
* kvp_list::
|
2000-08-29 02:08:36 -05:00
|
|
|
* Key-Value Policy::
|
2000-08-25 20:05:09 -05:00
|
|
|
@end menu
|
|
|
|
|
|
|
|
|
|
|
|
@node kvp_frame, kvp_value, Key-Value Pair Frames, Key-Value Pair Frames
|
|
|
|
@subsection kvp_frame
|
|
|
|
@tindex kvp_frame
|
|
|
|
|
|
|
|
A @code{kvp_frame} is the datatype used to associate key strings with
|
|
|
|
@code{kvp_value} objects (@pxref{kvp_value}).
|
|
|
|
|
|
|
|
@deftypefun kvp_frame* kvp_frame_new (void)
|
|
|
|
Create and initialize a new @code{kvp_frame} object and return
|
|
|
|
a pointer to it.
|
|
|
|
@end deftypefun
|
|
|
|
|
|
|
|
@deftypefun void kvp_frame_delete(kvp_frame * @var{frame})
|
|
|
|
Free all memory associated with @var{frame}.
|
|
|
|
@end deftypefun
|
|
|
|
|
|
|
|
@deftypefun kvp_frame* kvp_frame_copy(const kvp_frame * frame)
|
|
|
|
Return a deep copy of @var{frame}.
|
|
|
|
@end deftypefun
|
|
|
|
|
|
|
|
@deftypefun void kvp_frame_set_slot(kvp_frame * @var{frame}, const char * @var{key}, const kvp_value * @var{value})
|
|
|
|
Associate @var{key} with @var{value} in @var{frame}.
|
|
|
|
@end deftypefun
|
|
|
|
|
|
|
|
@deftypefun kvp_value* kvp_frame_get_slot(kvp_frame * @var{frame}, const char * @var{key})
|
|
|
|
Return the @code{kvp_value} object associated with @var{key}
|
|
|
|
in @var{frame} or return @code{NULL} if there is no association
|
|
|
|
for @var{key}. The value returned is not a copy.
|
|
|
|
@end deftypefun
|
|
|
|
|
|
|
|
|
2000-08-26 02:52:05 -05:00
|
|
|
@node kvp_value, kvp_list, kvp_frame, Key-Value Pair Frames
|
2000-08-25 20:05:09 -05:00
|
|
|
@subsection kvp_value
|
|
|
|
@tindex kvp_value
|
|
|
|
@tindex kvp_value_t
|
|
|
|
|
|
|
|
The @code{kvp_value} object stores the 'value' part of a key-value
|
|
|
|
association in a @code{kvp_frame} object.
|
|
|
|
|
2000-08-26 02:52:05 -05:00
|
|
|
@deftypefun void kvp_value_delete(kvp_value * @var{value})
|
|
|
|
Free all of the memory associated with @var{value}.
|
|
|
|
@end deftypefun
|
|
|
|
|
|
|
|
@deftypefun kvp_value* kvp_value_copy(const kvp_value * @var{value})
|
|
|
|
Return a deep copy of @var{value}.
|
|
|
|
@end deftypefun
|
|
|
|
|
2000-08-25 20:05:09 -05:00
|
|
|
@deftypefun kvp_value_t kvp_value_get_type(const kvp_value * @var{value})
|
|
|
|
Return the type of value stored in @var{value}.
|
|
|
|
@end deftypefun
|
|
|
|
|
|
|
|
A @code{kvp_value_t} enum must have one of the following values:
|
|
|
|
|
2000-08-23 23:34:03 -05:00
|
|
|
@table @code
|
|
|
|
|
|
|
|
@item KVP_TYPE_NONE
|
2000-08-25 20:05:09 -05:00
|
|
|
Indicates the abscence of a value in a @code{kvp_frame}.
|
2000-08-23 23:34:03 -05:00
|
|
|
|
|
|
|
@item KVP_TYPE_INT64
|
|
|
|
A @code{gint64} value.
|
|
|
|
|
|
|
|
@item KVP_TYPE_FLOAT64
|
|
|
|
A @code{double} value.
|
|
|
|
|
|
|
|
@item KVP_TYPE_STRING
|
|
|
|
A @code{char *} value of arbitrary length.
|
|
|
|
|
|
|
|
@item KVP_TYPE_GUID
|
|
|
|
A @code{GUID} value. @xref{Globally Unique Identifiers}.
|
|
|
|
|
|
|
|
@item KVP_TYPE_BINARY
|
|
|
|
Arbitrary binary data.
|
|
|
|
|
|
|
|
@item KVP_TYPE_LIST
|
|
|
|
A @code{kvp_list} item which contains a list of @code{kvp_value} items.
|
|
|
|
|
|
|
|
@item KVP_TYPE_FRAME
|
|
|
|
A @code{kvp_frame} object. Thus, frames may contain other frames in a
|
|
|
|
recursive manner.
|
|
|
|
|
|
|
|
@end table
|
|
|
|
|
2000-08-26 02:52:05 -05:00
|
|
|
@subsubsection Value Constructors
|
|
|
|
|
|
|
|
The following functions create and return @code{kvp_value} objects with
|
|
|
|
particular values. In the case of pointer arguments, deep copies are
|
|
|
|
performed.
|
|
|
|
|
|
|
|
@deftypefun kvp_value* kvp_value_new_int64(gint64 @var{value})
|
|
|
|
@end deftypefun
|
|
|
|
@deftypefun kvp_value* kvp_value_new_float64(double @var{value})
|
|
|
|
@end deftypefun
|
|
|
|
@deftypefun kvp_value* kvp_value_new_string(const char * @var{value})
|
|
|
|
@end deftypefun
|
|
|
|
@deftypefun kvp_value* kvp_value_new_guid(const GUID * @var{guid})
|
|
|
|
@end deftypefun
|
|
|
|
@deftypefun kvp_value* kvp_value_new_binary(const void * @var{data}, int @var{datasize})
|
|
|
|
@end deftypefun
|
|
|
|
@deftypefun kvp_value* kvp_value_new_list(const kvp_list * @var{value})
|
|
|
|
@end deftypefun
|
|
|
|
@deftypefun kvp_value* kvp_value_new_frame(const kvp_frame * @var{value});
|
|
|
|
@end deftypefun
|
|
|
|
|
|
|
|
@subsubsection Value Accessors
|
|
|
|
|
|
|
|
The following functions access the value of a given @code{kvp_value}
|
|
|
|
object. If the type of the object does not correspond to that named
|
|
|
|
in the function, @code{NULL} is returned.
|
|
|
|
|
|
|
|
@deftypefun gint64 kvp_value_get_int64(const kvp_value * @var{value})
|
|
|
|
@end deftypefun
|
|
|
|
@deftypefun double kvp_value_get_float64(const kvp_value * @var{value})
|
|
|
|
@end deftypefun
|
|
|
|
@deftypefun char* kvp_value_get_string(const kvp_value * @var{value})
|
|
|
|
@end deftypefun
|
|
|
|
@deftypefun GUID* kvp_value_get_guid(const kvp_value * @var{value})
|
|
|
|
@end deftypefun
|
|
|
|
@deftypefun void* kvp_value_get_binary(const kvp_value * @var{value}, int * @var{size_return})
|
|
|
|
@end deftypefun
|
|
|
|
@deftypefun kvp_list* kvp_value_get_list(const kvp_value * @var{value})
|
|
|
|
@end deftypefun
|
|
|
|
@deftypefun kvp_frame* kvp_value_get_frame(const kvp_value * @var{value})
|
|
|
|
@end deftypefun
|
|
|
|
|
|
|
|
|
2000-08-29 02:08:36 -05:00
|
|
|
@node kvp_list, Key-Value Policy, kvp_value, Key-Value Pair Frames
|
2000-08-26 02:52:05 -05:00
|
|
|
@subsection kvp_list
|
|
|
|
@tindex kvp_list
|
|
|
|
|
|
|
|
A @code{kvp_list} object abstract a list of @code{kvp_value} objects.
|
|
|
|
|
|
|
|
@deftypefun kvp_list* kvp_list_new()
|
|
|
|
Return a newly allocated @code{kvp_list} object.
|
|
|
|
@end deftypefun
|
|
|
|
|
|
|
|
@deftypefun void kvp_list_delete(kvp_list * @var{list})
|
|
|
|
Free all memory associated with @var{list}, including the
|
|
|
|
@code{kvp_value} objects in @var{list}.
|
|
|
|
@end deftypefun
|
|
|
|
|
|
|
|
@deftypefun kvp_list* kvp_list_copy(const kvp_list * @var{list})
|
|
|
|
Return a deep copy of @var{list}.
|
|
|
|
@end deftypefun
|
|
|
|
|
|
|
|
@deftypefun gboolean kvp_list_null_p(const kvp_list * @var{list})
|
|
|
|
Return @code{TRUE} if @var{list} is the empty list.
|
|
|
|
@end deftypefun
|
|
|
|
|
|
|
|
@deftypefun kvp_value* kvp_list_car(kvp_list * @var{list})
|
|
|
|
If @var{list} is @code{NULL} or the empty list, return @code{NULL}.
|
|
|
|
Otherwise, return the first @code{kvp_value} object in the list.
|
|
|
|
@end deftypefun
|
|
|
|
|
|
|
|
@deftypefun kvp_list* kvp_list_cdr(kvp_list * @var{list})
|
|
|
|
If @var{list} is @code{NULL} or the empty list, return @code{NULL}.
|
|
|
|
Otherwise, return a @code{kvp_list} object consisting of @var{list}
|
|
|
|
with the first value removed. NOTE: the returned list is not a copy!
|
|
|
|
@end deftypefun
|
|
|
|
|
|
|
|
@deftypefun kvp_list* kvp_list_cons(kvp_value * @var{car}, kvp_list * @var{cdr})
|
|
|
|
If either @var{car} or @var{cdr} is @code{NULL}, return @code{NULL}. Otherwise,
|
|
|
|
return a @code{kvp_list} object consisting of the value of @var{car} followed
|
|
|
|
by the values of @var{cdr}. This function uses 'hand-over' semantics, i.e.,
|
|
|
|
the arguments @var{car} and @var{cdr} are no longer the responsibility of
|
|
|
|
the caller and should not be accessed after the function returns.
|
|
|
|
@end deftypefun
|
|
|
|
|
2000-08-23 23:34:03 -05:00
|
|
|
|
2000-08-29 02:08:36 -05:00
|
|
|
@node Key-Value Policy, , kvp_list, Key-Value Pair Frames
|
|
|
|
@subsection Key-Value Policy
|
|
|
|
@cindex Key-Value Policy
|
|
|
|
|
|
|
|
This section defines the policy that programmers should follow
|
|
|
|
when using key-value pairs to store information. Because of the
|
|
|
|
large amount of information which can potentially be stored using
|
|
|
|
this mechanism, it is important to follow these guidelines so
|
|
|
|
that order will be maintained.
|
|
|
|
|
|
|
|
The following rules should be followed for using key-value pairs:
|
|
|
|
|
|
|
|
@itemize
|
|
|
|
|
|
|
|
@item
|
|
|
|
The document @file{src/engine/kvp_doc.txt} should be used to document
|
|
|
|
the use of keys and values. Please consult this document before planning
|
|
|
|
any use of new keys.
|
|
|
|
|
|
|
|
@item
|
2000-08-31 02:15:02 -05:00
|
|
|
Key strings should be in all lower case with the '_' character
|
|
|
|
separating words. If possible, use only alphanumeric characters
|
|
|
|
and '_'. Example: @code{"bank_info"}
|
2000-08-29 02:08:36 -05:00
|
|
|
|
|
|
|
@item
|
|
|
|
Favor longer, descriptive key strings over short ones. Example:
|
|
|
|
@code{"online_banking_info"} is better than @code{"onln_bnk"}.
|
|
|
|
|
2000-08-31 02:15:02 -05:00
|
|
|
@item
|
|
|
|
Make use of the fact that frames can be stored in frames. If a group
|
|
|
|
of keys are used for a related purpose, consider storing them together
|
|
|
|
in a sub-frame.
|
|
|
|
|
|
|
|
@item
|
|
|
|
Values should generally not be accessed directly through keys, but
|
|
|
|
should rather be accessed through specific API calls.
|
|
|
|
|
2000-08-29 02:08:36 -05:00
|
|
|
@end itemize
|
|
|
|
|
2000-08-31 02:15:02 -05:00
|
|
|
|
2000-08-31 03:50:20 -05:00
|
|
|
@node Splits, Transactions, Key-Value Pair Frames, Engine
|
|
|
|
@section Splits
|
|
|
|
@tindex Split
|
|
|
|
|
|
|
|
|
|
|
|
@node Transactions, Accounts, Splits, Engine
|
|
|
|
@section Transactions
|
|
|
|
@tindex Transaction
|
|
|
|
|
|
|
|
|
|
|
|
@node Accounts, Account Groups, Transactions, Engine
|
|
|
|
@section Accounts
|
|
|
|
@tindex Account
|
|
|
|
|
|
|
|
|
|
|
|
@node Account Groups, Sessions, Accounts, Engine
|
|
|
|
@section Account Groups
|
|
|
|
@tindex AccountGroup
|
|
|
|
|
|
|
|
|
|
|
|
@node Sessions, , Account Groups, Engine
|
2000-08-23 23:34:03 -05:00
|
|
|
@section Sessions
|
|
|
|
@tindex Session
|
|
|
|
|
|
|
|
The @dfn{Session} interface provides wrappers for initiating/concluding
|
|
|
|
a file-editing session. This class provides several important services:
|
|
|
|
|
|
|
|
@itemize
|
|
|
|
|
|
|
|
@item
|
|
|
|
Prevents multiple users from editing the same file at the same time,
|
|
|
|
thus avoiding lost data due to race conditions. Thus an open session
|
|
|
|
implies that the associated file is locked.
|
|
|
|
|
|
|
|
@item
|
|
|
|
Provides a search path for the file to be edited. This should simplify
|
2000-08-25 20:05:09 -05:00
|
|
|
install & maintenance problems for users who may not have a good grasp
|
|
|
|
of what a file system is, or where they want to keep their data files.
|
2000-08-23 23:34:03 -05:00
|
|
|
|
|
|
|
@end itemize
|
|
|
|
|
|
|
|
The current implementation assumes the use of files and file locks;
|
|
|
|
however, the API was designed to be general enough to allow the use
|
|
|
|
of generic URL's, and/or implementation on top of SQL or other
|
|
|
|
database/persistant object technology.
|