mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Doxygen - merge separate txt files into respective header files
This commit is contained in:
@@ -22,6 +22,135 @@
|
|||||||
# @author Jeff Green, ParIT Worker Co-operative <jeff@parit.ca>
|
# @author Jeff Green, ParIT Worker Co-operative <jeff@parit.ca>
|
||||||
|
|
||||||
# The following is for doxygen
|
# The following is for doxygen
|
||||||
|
|
||||||
|
## @defgroup python_bindings Python Bindings Module
|
||||||
|
# Also have a look at the page @ref python_bindings_page.
|
||||||
|
|
||||||
|
## @defgroup python_bindings_examples Python Bindings Examples Module
|
||||||
|
# @ingroup python_bindings
|
||||||
|
# The python-bindings come with quite a lot of example scripts.
|
||||||
|
|
||||||
|
## @page python_bindings_page Python bindings
|
||||||
|
# Also have a look at group @ref python_bindings.
|
||||||
|
#
|
||||||
|
# In the source tree they are located at bindings/python.
|
||||||
|
#
|
||||||
|
# To enable them in the compilation process you have to add -DWITH_PYTHON=ON
|
||||||
|
# to the call of cmake.
|
||||||
|
#
|
||||||
|
# As a starting point have a look at the \link python_bindings_examples example-scripts\endlink.
|
||||||
|
#
|
||||||
|
# @section possibilities What can Python Bindings be used for ?
|
||||||
|
#
|
||||||
|
# The python bindings supply the ability to access a wide range of the core functions of GnuCash. You
|
||||||
|
# can read and write Transactions, Commodities, Lots, access the business stuff... You gain the ability
|
||||||
|
# to manipulate your financial data with a flexible scripting language.
|
||||||
|
#
|
||||||
|
# Not everything GnuCash can is possible to access though. The bindings focus on basic accounting functions.
|
||||||
|
# Have a look at the examples to get an impression.
|
||||||
|
#
|
||||||
|
# Some functions are broken because they have not been wrapped properly. They may crash the program or return unaccessible values.
|
||||||
|
# Please file a bug report if you find one to help support the development process.
|
||||||
|
#
|
||||||
|
# @section python_bindings_section Principles
|
||||||
|
# The python-bindings are generated using SWIG from parts of the source-files of GnuCash.
|
||||||
|
#
|
||||||
|
# @note Python-scripts should not be executed while GnuCash runs. GnuCash is designed as
|
||||||
|
# a single user application with only one program accessing the data at one time. You can force your
|
||||||
|
# access but that may corrupt data. Maybe one day that may change but for the moment there is no active development on that.
|
||||||
|
#
|
||||||
|
# @subsection swigworks What SWIG does
|
||||||
|
#
|
||||||
|
# SWIG extracts information from the c-sources and provides access to the structures
|
||||||
|
# to python. It's work is controlled by interface files :
|
||||||
|
#
|
||||||
|
# @li gnucash_core.i
|
||||||
|
# @li timespec.i
|
||||||
|
# @li glib.i
|
||||||
|
# @li @link base-typemaps.i src/base-typemaps.i @endlink This file is shared with Guile.
|
||||||
|
#
|
||||||
|
# it outputs:
|
||||||
|
#
|
||||||
|
# @li gnucash_core.c
|
||||||
|
# @li gnucash_core_c.py
|
||||||
|
#
|
||||||
|
# If you have generated your own local doxygen documentation (by "make doc") after having compiled the python-bindings, doxygen
|
||||||
|
# will include SWIGs output-files.
|
||||||
|
# It's actually quite interesting to have a look at them through doxygen, because they contain all that you can
|
||||||
|
# access from python.
|
||||||
|
#
|
||||||
|
# This c-style-api is the bottom layer. It is a quite raw extract and close to the original source. Some more details are described further down.
|
||||||
|
#
|
||||||
|
# For some parts there is a second layer of a nice pythonic interface. It is declared
|
||||||
|
# in
|
||||||
|
# @li gnucash_core.py and
|
||||||
|
# @li gnucash_business.py.
|
||||||
|
# @li function_class.py contains helper functions for that.
|
||||||
|
#
|
||||||
|
# @section howto How to use the Python bindings
|
||||||
|
# @subsection highlevel High level python wrapper classes
|
||||||
|
# If you
|
||||||
|
#
|
||||||
|
# @code >> import gnucash @endcode
|
||||||
|
#
|
||||||
|
# You can access the structures of the high level api. For Example you get a Session object by
|
||||||
|
#
|
||||||
|
# @code >> session=gnucash.Session() @endcode
|
||||||
|
#
|
||||||
|
# Here you will find easy to use things. But sometimes - and at the current level rather sooner than
|
||||||
|
# later - you may be forced to search for solutions at the :
|
||||||
|
#
|
||||||
|
# @subsection c_style_api C-style-api
|
||||||
|
#
|
||||||
|
# If you
|
||||||
|
#
|
||||||
|
# @code >> import gnucash @endcode
|
||||||
|
#
|
||||||
|
# The c-style-api can be accessed via gnucash.gnucash_core_c. You can have a look at all the possibilities
|
||||||
|
# at gnucash_core_c.py.
|
||||||
|
#
|
||||||
|
# You will find a lot of pointers here which you can just ignore if input and output of the function have the
|
||||||
|
# same type.
|
||||||
|
#
|
||||||
|
# For example you could start a session by gnucash.gnucash_core_c.qof_session_begin(). But if you just try
|
||||||
|
#
|
||||||
|
# @code session=gnucash.gnucash_core_c.qof_session_begin() @endcode
|
||||||
|
#
|
||||||
|
# you will get an error message and realize the lack of convenience for you have to add the correct function parameters.
|
||||||
|
#
|
||||||
|
# Not all of the available structures will work. SWIG just takes everything from the sources that it is fed with and translates it. Not everything
|
||||||
|
# is a working translation, because not everything has been worked through. At this point you are getting closer to the developers who you can
|
||||||
|
# contact at the mailing-list gnucash-devel@gnucash.org. There may be a workaround. Maybe the problem can only be fixed by changing SWIGs input
|
||||||
|
# files to correctly translate the c-source. Feel free to post a question at the developers list. It may awaken the interest of someone who creates
|
||||||
|
# some more beautiful python-interfaces.
|
||||||
|
#
|
||||||
|
# @section Thisorthat When to use which api ?
|
||||||
|
#
|
||||||
|
# The start would surely be the high-level api for you can be quite sure to have something working and you will maybe find
|
||||||
|
# explanations in the example-scripts. If you search for something that is not yet implemented in that way you will have to
|
||||||
|
# take your way to the c-style-api.
|
||||||
|
#
|
||||||
|
# @section pydoc (Further) documentation
|
||||||
|
#
|
||||||
|
# @li The documentation you just read uses doxygen. It collects documentation in GnuCash's sources. Besides that there is
|
||||||
|
# @li the classic python-documentation using help() and docstrings. Have a look at both.
|
||||||
|
# @li There is a page in the GnuCash wiki at https://wiki.gnucash.org/wiki/Python
|
||||||
|
# @li You may also have a look into the archives of gnucash-devel@gnucash.org.
|
||||||
|
# @li On Bugzilla there is also some interesting talk regarding the development process.
|
||||||
|
# @li Then you can use the abilities of git to see the history of the code by @code git log @endcode done in the directory of the python-bindings.
|
||||||
|
#
|
||||||
|
# @section pytodo To-Do
|
||||||
|
# @li Work out the relation of scheme/guile and python-bindings
|
||||||
|
# @li maybe join python_bindings_page and group
|
||||||
|
# @li work on the structure of the documentation to make it more clear
|
||||||
|
# @li try to make SWIG include the documentation of the c-source
|
||||||
|
# @li make function-links in SWIG-generated files work.
|
||||||
|
# @li some words to the tests
|
||||||
|
#
|
||||||
|
# @author Christoph Holtermann
|
||||||
|
# @date December 2010
|
||||||
|
|
||||||
|
|
||||||
## @file
|
## @file
|
||||||
# @brief High level python wrapper classes for the core parts of GnuCash
|
# @brief High level python wrapper classes for the core parts of GnuCash
|
||||||
# @author Mark Jenkins, ParIT Worker Co-operative <mark@parit.ca>
|
# @author Mark Jenkins, ParIT Worker Co-operative <mark@parit.ca>
|
||||||
|
|||||||
@@ -4,9 +4,6 @@ set(doc_FILES
|
|||||||
doxygen_main_page.c
|
doxygen_main_page.c
|
||||||
finderv.html
|
finderv.html
|
||||||
finutil.html
|
finutil.html
|
||||||
loans.txt
|
|
||||||
lots.txt
|
|
||||||
python-bindings-doxygen.py
|
|
||||||
README
|
README
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,288 +0,0 @@
|
|||||||
/** \page loanhandling Handling loan repayment in GnuCash::Scheduled Transactions
|
|
||||||
\sa The original email thread at <https://lists.gnucash.org/pipermail/gnucash-devel/2002-July/006438.html>.
|
|
||||||
|
|
||||||
July, 2002 - jsled@asynchronous.org
|
|
||||||
|
|
||||||
API: \ref SchedXaction
|
|
||||||
|
|
||||||
We define loan repayment values in the following terms:
|
|
||||||
|
|
||||||
Identifiers:\n
|
|
||||||
P : the original principal. This is the overall principal afforded by the
|
|
||||||
loan at the time of it's creation.\n
|
|
||||||
P' : The beginning principal. This is the principal at the time of entry
|
|
||||||
into GnuCash.\n
|
|
||||||
I : The interest rate associated with the loan. Note that this may change
|
|
||||||
over time [based on an addition to the Prime rate, for instance], at
|
|
||||||
various frequencies [yearly, monthly, quarterly...]. Ideally, we can
|
|
||||||
use the FreqSpec mechanism to facilitate the interest rate adjustment.\n
|
|
||||||
N : The length of the loan in periods.\n
|
|
||||||
m : The minimum periodic payment.\n
|
|
||||||
n : The current period of the repayment.
|
|
||||||
|
|
||||||
Functions:\n
|
|
||||||
PMT : Total equal periodic payment, as per Gnumeric/Excel's definitions
|
|
||||||
[see end for more detail].\n
|
|
||||||
IPMT : Monthly payment interest portion, ""\n
|
|
||||||
PPMT : Monthly payment principal portion, ""
|
|
||||||
|
|
||||||
[ NOTE: 'PMT(I,N,P) = IPMT(I, n, N, P) + PPMT(I, n, N, P)' for 0 <= n < N ]
|
|
||||||
|
|
||||||
|
|
||||||
The formula entered into the SX template for a loan may then look like:
|
|
||||||
|
|
||||||
Example 1:
|
|
||||||
\verbatim
|
|
||||||
Desc/Memo | Account | Credit | Debit
|
|
||||||
----------+-----------------------------+----------------+-------------------
|
|
||||||
Repayment | Assets:Bank:Checking | | =PMT(I,n,N,P)
|
|
||||||
| | | + fixed_amt
|
|
||||||
Interest | Expenses:Loan_Name:Interest | =IPMT(I,n,N,P) |
|
|
||||||
PMI | Expenses:Loan_Name:Misc | fixed_amt |
|
|
||||||
Principal | Liabilities:Loan_Name | =PPMT(I,n,N,P) |
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
Or, in the case where an escrow account is involved [with thanks to warlord
|
|
||||||
for the review and fixes]:
|
|
||||||
|
|
||||||
Example 2:
|
|
||||||
\verbatim
|
|
||||||
Desc/Memo | Account | Credit | Debit
|
|
||||||
---------------+-----------------------------+----------------+--------------
|
|
||||||
Repayment | Assets:Bank:Checking | | =PMT(I,n,N,P)
|
|
||||||
| | | + escrow_amt
|
|
||||||
| | | + fixed_amt
|
|
||||||
| | | + pre_payment
|
|
||||||
Escrow | Assets:Loan_Escrow_acct | escrow_amt |
|
|
||||||
Interest | Expenses:Loan_Name:Interest | =IPMT(I,n,N,P) |
|
|
||||||
PMI | Expenses:Loan_Name:Misc | fixed_amt |
|
|
||||||
Principal | Liabilities:Loan_Name | =PPMT(I,n,N,P) |
|
|
||||||
| | + pre_payment |
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
FreqSpec = 1 month
|
|
||||||
\verbatim
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Desc/Memo | Account | Credit | Debit
|
|
||||||
---------------+-----------------------------+----------------+--------------
|
|
||||||
Insurance | Assets:Loan_Escrow_acct | | insurance_amt
|
|
||||||
Insurance | Expenses:Home_Insurance | insurance_amt |
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
FreqSpec = 1 year
|
|
||||||
\verbatim
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
Desc/Memo | Account | Credit | Debit
|
|
||||||
---------------+-----------------------------+----------------+--------------
|
|
||||||
Taxes | Assets:Loan_Escrow_acct | | taxes_amt
|
|
||||||
Taxes | Expenses:Property_Taxes | taxes_amt |
|
|
||||||
FreqSpec = Quarterly
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
|
|
||||||
\section guidpractical Practical questions regarding the implementation of this facility are:
|
|
||||||
|
|
||||||
| 1. The transactions as in Example 2 are not going to be scheduled for the\n
|
|
||||||
| same day; are their values linked at all / do they need to share the\n
|
|
||||||
| same var bindings?
|
|
||||||
|
|
||||||
Yes, they would want to be linked. More precisely, the insurance/tax amounts
|
|
||||||
are very likely linked to the escrow_amt in Ex.2. Unfortunately, these are
|
|
||||||
very likely separate SXes...
|
|
||||||
|
|
||||||
-----
|
|
||||||
| 2. How does this effect the SX implementation of variables?
|
|
||||||
|
|
||||||
Vastly.
|
|
||||||
|
|
||||||
It becomes clear that multiple SXes will be related. While they'll have
|
|
||||||
separate FreqSpecs and template transactions, they'll share some state. For
|
|
||||||
both visualization [i.e., the SX list] and processing [credit/debit cell
|
|
||||||
value computation] we'll want some manner of dealing with this.
|
|
||||||
|
|
||||||
It becomes clear as well that the nature of variables and functions needs to
|
|
||||||
be more clearly defined with respect to these issues. We probably want to
|
|
||||||
institute a clear policy for the scoping of variables. As well, since the
|
|
||||||
SXes will have different instantiation dates, we'll need a method and
|
|
||||||
implementation for the relation of SXes to each other.
|
|
||||||
|
|
||||||
A substantial hurdle is that if a set of SXes are [strongly] related, there
|
|
||||||
is no-longer a single instantiation date for a set of related SXes. In fact,
|
|
||||||
there may be different frequencies of recurrence.
|
|
||||||
|
|
||||||
One option -- on the surface -- to relate them would be to maintain an
|
|
||||||
instance variable-binding frame cache, which would store user-entered and
|
|
||||||
computed variable bindings. The first instantiated SX of the set would create
|
|
||||||
the frame, and the "last" instance would clean it up. First "last" instance
|
|
||||||
is defined by the last-occurring SX in a related set, in a given time range.
|
|
||||||
|
|
||||||
For example: a loan SX-set is defined by two monthly SXes ["repayment" and
|
|
||||||
"insurance"], and a quarterly "tax" SX. The first monthly SX would create a
|
|
||||||
frame, which would be passed two the second monthly SX. This would occur for
|
|
||||||
the 3 months of interest. The Quarterly SX would get all 3 frames for it's
|
|
||||||
creation, and use them in an /appropriate/ [read: to be defined through a lot
|
|
||||||
of pain] way. As the time-based dependency relationship between the frames
|
|
||||||
plays out, the frame can be removed from the system.
|
|
||||||
|
|
||||||
Another option is to toss this idea entirely and instead let the user DTRT
|
|
||||||
manually.
|
|
||||||
|
|
||||||
A related option is to add the necessary grouping mechanism to the SX
|
|
||||||
storage/data structure: immediately allowing visual grouping of related SXes,
|
|
||||||
and potentially allowing a storage place for such frame data in the future
|
|
||||||
with less file-versioning headache. This is the option that will be pursued.
|
|
||||||
|
|
||||||
Another element implicit in the original requirements to support
|
|
||||||
loans/repayment calculations is implicit variables. These are symbolic names
|
|
||||||
which can be used and are automagically bound to values. The known implicit
|
|
||||||
variables to support loan/repayment are:
|
|
||||||
|
|
||||||
P [loan principal amount], N [loan repayment periods], I [interest], m
|
|
||||||
[minimum payment] and n [current period]. Some of these [P, N, I, m] are
|
|
||||||
fixed over many instances; some [n] are rebound specific to the instance.
|
|
||||||
See the 'variable-scope-frame' below for a method of handling these
|
|
||||||
variables.
|
|
||||||
|
|
||||||
And yet-another element implicit in the original requirement is support for
|
|
||||||
detecting and computing the result of functions in the template transaction's
|
|
||||||
credit/debit cells. Changes to the src/app-utils/gnc-exp-parser.[hc] and
|
|
||||||
src/calculation/expression_parser.[ch] to support functions would be
|
|
||||||
necessitated. It is conceivable that after parsing, the parsed expression
|
|
||||||
could be passed to scheme for evaluation. Hopefully this would make it
|
|
||||||
easier to add support for new functions to the SX code via Scheme.
|
|
||||||
|
|
||||||
|
|
||||||
| 3. How do we deal with periodic [yearly, semi-yearly] updating of various\n
|
|
||||||
| "fixed" variables?
|
|
||||||
|
|
||||||
Another change in the way variables are used is that some SXes -- especially
|
|
||||||
loan-repayment -- may involve variables which are not tied to the instance of
|
|
||||||
the SX, but rather to variables which:
|
|
||||||
- are also involved in another SX
|
|
||||||
- change with a frequency different than the SX
|
|
||||||
- are represented by a relationship to the outside world ["prime + 1.7"]
|
|
||||||
|
|
||||||
A partial fix for this problem is to provide multiple levels of scope for
|
|
||||||
variable bindings, and expose this to the user by a method of assigning
|
|
||||||
[perhaps time-dependent] values to these variables. Variables bound in this
|
|
||||||
manner would absolve the user of the need to bind them at SX-creation time.
|
|
||||||
|
|
||||||
An added benefit of this would be to allow some users [see Bug#85707] have
|
|
||||||
"fixed variable" values for a group of SXes.
|
|
||||||
|
|
||||||
In combination with the SX Grouping, this would provide most of a fix for the
|
|
||||||
problem described in #2, above. The variable_frame could be used to provide
|
|
||||||
the shared-state between related SXes, without imposing quite the same
|
|
||||||
burden. This approach is slightly less flexible, but that allows it to be
|
|
||||||
implemented more readily, and understood more easily.
|
|
||||||
|
|
||||||
A question which comes up when thinking about yearly-changing values such as
|
|
||||||
interest rates is if the historical information needs to be versioned. For
|
|
||||||
now, we punt on this issue, but hopefully will provide enough of a framework
|
|
||||||
for this to be reasonably added in the future.
|
|
||||||
|
|
||||||
We define four types of variables supported by this scheme:
|
|
||||||
|
|
||||||
implicit : provided only by the system
|
|
||||||
e.g.: 'n', the current index of the repayment
|
|
||||||
|
|
||||||
transient : have user-defined values, bound at instantiation time.
|
|
||||||
e.g.: existing ad-hoc variables in SXes.
|
|
||||||
|
|
||||||
static : have a user-defined values, and are not expected to change with
|
|
||||||
any measurable frequency. The user may change these at their
|
|
||||||
leisure, but no facility to assist or encourage this is
|
|
||||||
provided.
|
|
||||||
e.g.: paycheck amount, loan principal amount
|
|
||||||
|
|
||||||
periodic : have user-defined values which change at specific points in
|
|
||||||
time [July 1, yearly]. After the expiration of a variable value,
|
|
||||||
it's re-binding will prevent any dependent SXes from being
|
|
||||||
created.
|
|
||||||
e.g.: loan tax amount, loan interest rate
|
|
||||||
|
|
||||||
| 4. From where do we get the dollar amount against which to do the [PI]PMT\n
|
|
||||||
| calculation?
|
|
||||||
|
|
||||||
The user will specify the parameters of the Loan via some UI... then where
|
|
||||||
does the data go?
|
|
||||||
|
|
||||||
- KVP data for that account?
|
|
||||||
- KVP data for the SX?
|
|
||||||
- Do we have a different top-level "Loan" object?
|
|
||||||
- Present only in the SX template transactions/variable-frames?
|
|
||||||
|
|
||||||
I believe that the only location of the data after Druid creation is in the
|
|
||||||
variable-binding frames and the formulae in the template transactions. The
|
|
||||||
Druid would thus simply assist the user in creating the following SX-related
|
|
||||||
structures:
|
|
||||||
|
|
||||||
- SXGroup: Loan Repayment
|
|
||||||
- variable_frame
|
|
||||||
- P [static]
|
|
||||||
- N [static]
|
|
||||||
- n [implicit]
|
|
||||||
- I [periodic]
|
|
||||||
- pmi_amount [periodic]
|
|
||||||
- tax_amount [periodic]
|
|
||||||
- pre_payment [periodic]
|
|
||||||
- insurance_amount [periodic]
|
|
||||||
- SX: Payment
|
|
||||||
- Bank -> { Escrow,
|
|
||||||
Liability:Loan:Principal,
|
|
||||||
Expense:Loan:Interest,
|
|
||||||
Expense:Loan:Insurance }
|
|
||||||
- SX: Tax
|
|
||||||
- Escrow -> Expense:Tax
|
|
||||||
- SX: Insurance
|
|
||||||
- Escrow -> Expense:Insurance
|
|
||||||
|
|
||||||
|
|
||||||
\section loansreference Reference
|
|
||||||
|
|
||||||
|
|
||||||
\subsection loanssoftware Other software:
|
|
||||||
|
|
||||||
Gnumeric supports the following functions WRT payment calculation:
|
|
||||||
|
|
||||||
- PMT( rate, nper, pv [, fv, type] )
|
|
||||||
PMT returns the amount of payment for a loan based on a constant interest
|
|
||||||
rate and constant payments (ea. payment equal).
|
|
||||||
@rate : constant interest rate
|
|
||||||
@nper : overall number of payments
|
|
||||||
@pv : present value
|
|
||||||
@fv : future value
|
|
||||||
@type : payment type
|
|
||||||
- 0 : end of period
|
|
||||||
- 1 : beginning of period
|
|
||||||
|
|
||||||
- IPMT( rate, per, nper, pv, fv, type )
|
|
||||||
IPMT calculates the amount of a payment of an annuity going towards
|
|
||||||
interest. Formula for IPMT is:
|
|
||||||
IPMT(per) = - principal(per-1) * interest_rate
|
|
||||||
where:
|
|
||||||
principal(per-1) = amount of the remaining principal from last period.
|
|
||||||
|
|
||||||
- ISPMT( rate, per, nper, pv )
|
|
||||||
ISPMT returns the interest paid on a given period.
|
|
||||||
If @per < 1 or @per > @nper, returns #NUM! err.
|
|
||||||
|
|
||||||
- PPMT(rate, per, nper, pv [, fv, type] )
|
|
||||||
PPMT calculates the amount of a payment of an annuity going towards
|
|
||||||
principal.
|
|
||||||
PPMT(per) = PMT - IPMT(per)
|
|
||||||
where: PMT is payment
|
|
||||||
- IPMT is interest for period per
|
|
||||||
|
|
||||||
- PV( rate, nper, pmt [, fv, type] )
|
|
||||||
Calculates the present value of an investment
|
|
||||||
@rate : periodic interest rate
|
|
||||||
@nper : number of compounding periods
|
|
||||||
@pmt : payment made each period
|
|
||||||
@fv : future value
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
@@ -1,522 +0,0 @@
|
|||||||
/** \page lotsoverview Lots Architecture & Implementation Overview
|
|
||||||
|
|
||||||
Linas Vepstas <linas@linas.org>
|
|
||||||
Last Revised May 2004
|
|
||||||
|
|
||||||
API \ref Lot
|
|
||||||
|
|
||||||
One often needs to know that the item 'bought' in one transaction
|
|
||||||
is the same one as the item 'sold' in a different transaction.
|
|
||||||
Lots are used to make this association. One Lot holds all of the
|
|
||||||
splits that involve the same item. A lot is typically formed when
|
|
||||||
the item is bought, and is closed when the item is sold out.
|
|
||||||
A lot need not be a single item, it can be a quantity of the same
|
|
||||||
thing e.g. 500 gallons of paint (sold off a few gallons at a time).
|
|
||||||
Lots are required to correctly implement invoices, inventory,
|
|
||||||
depreciation and stock market investment gains.
|
|
||||||
|
|
||||||
'Lots' capture a fundamental accounting idea behind AR/AP, billing,
|
|
||||||
inventory, capital gains, depreciation and the like. The basic idea
|
|
||||||
is that a set of items is tracked together as a 'lot'; the date of
|
|
||||||
creation of the lot helps determine when a bill is due, when depreciation
|
|
||||||
starts, or the tax rate for capital gains on a stock market investment.
|
|
||||||
|
|
||||||
\section lotsdefines Definition
|
|
||||||
|
|
||||||
In GnuCash, a 'lot' will consist of a set of splits identified with
|
|
||||||
a unique lot number. Any given split can belong to one lot and one
|
|
||||||
lot only. All splits in a lot must also belong to the same account.
|
|
||||||
Lots have a 'balance': the sum of all the splits in the lot. A lot
|
|
||||||
is 'opened' when the first split is assigned to it. The date of that
|
|
||||||
split is the 'opening date' of the lot, and its quantity is the
|
|
||||||
'opening balance'. A lot is 'closed' when its balance is zero;
|
|
||||||
once closed, a lot cannot be re-opened. Open lots are always carried
|
|
||||||
forward into the current open book; closed lots are left behind in the
|
|
||||||
book in which they were closed.
|
|
||||||
|
|
||||||
\section How Lots Are Used
|
|
||||||
|
|
||||||
The following sections review how lots are used to implement various
|
|
||||||
accounting devices, and some of the related issues.
|
|
||||||
|
|
||||||
\subsection Billing
|
|
||||||
|
|
||||||
Tracking lots is the 'definition' of A/R and A/P. You want to be able
|
|
||||||
to say that this bill is 120 days old, and its balance has been partly
|
|
||||||
paid off; and you want to be able to do this whether or not there are
|
|
||||||
also other bills, of different ages, to the same company. In GnuCash,
|
|
||||||
a 'bill' is tracked as a lot: The 'billing date' is the opening date
|
|
||||||
of the lot, and the 'balance due' is the balance of the lot. When the
|
|
||||||
bill is 'paid in full', the lot is closed. The average age of
|
|
||||||
receivables can be computed by traversing all lots, etc. Additional
|
|
||||||
information about bills, such as a due date or payment terms, should
|
|
||||||
be stored as kvp values associated with the lot.
|
|
||||||
|
|
||||||
\subsection Billing Example
|
|
||||||
|
|
||||||
Normally, there is a one-to-one correspondence between bills and
|
|
||||||
lots: there is one lot per bill, and one bill per lot. (Note: this
|
|
||||||
is not how gnucash invoices are currently implemented; this is a
|
|
||||||
proposed implementation.)
|
|
||||||
|
|
||||||
For example:
|
|
||||||
\verbatim
|
|
||||||
invoice #258 customer XXX
|
|
||||||
Order placed 20 December 2001
|
|
||||||
quant (10) gallons paint $10/each $100
|
|
||||||
quant (2) paintbrushes $15/each $30
|
|
||||||
sales tax $8.27
|
|
||||||
------------
|
|
||||||
Total due $138.27
|
|
||||||
|
|
||||||
Payment received 24 january 2002 $50 Balance Due: $88.27
|
|
||||||
Payment received 13 february 2002 $60 Balance Due: $28.27
|
|
||||||
Payment received 18 march 2002 $28.27 PAID IN FULL
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
In this example, the lot encompasses four transactions, dated
|
|
||||||
December, January, February and March. The December transaction
|
|
||||||
opens the lot, and gives it a non-zero balance. To be precise,
|
|
||||||
the lot actually consists of four splits, belonging to four
|
|
||||||
different transactions. All four splits are a part of an imagined
|
|
||||||
"Accounts Receivable-Billing" account. The first split is for
|
|
||||||
$138.27, the second split is for $50, the third split is for $60,
|
|
||||||
and the fourth split is for $28.27. Note that the sales-tax
|
|
||||||
split, and th paint/paint-brush splits are *NOT* a part of this
|
|
||||||
lot. They are only a part of the transaction that opened this lot.
|
|
||||||
|
|
||||||
Note also that this example might also encompass two other lots:
|
|
||||||
the transfer of paint may belong to a lot in the "Paint Inventory"
|
|
||||||
account, and the split describing the paintbrushes might be a part
|
|
||||||
of a lot in the "Paintbrush Inventory" account. These lots should
|
|
||||||
not be confused with the invoice lot.
|
|
||||||
|
|
||||||
\subsection lotsinventory Inventory
|
|
||||||
|
|
||||||
The correct way of handling inventory under GnuCash is to have a
|
|
||||||
separate account for each widget type. The account balance represents
|
|
||||||
how many widgets there are in the warehouse. Lots offer an additional
|
|
||||||
level of detail that can be useful when, for example, the widgets have
|
|
||||||
an expiration date (e.g. milk) or vary slightly from batch to batch
|
|
||||||
(e.g paint), and creating a new account to track these differences
|
|
||||||
would be too heavy-weight.
|
|
||||||
|
|
||||||
In order to track widgets as single units (and prohibit fractional
|
|
||||||
widgets), set the currency denominator to 1. This will prevent
|
|
||||||
fractional widgets from being transferred into/out of an account.
|
|
||||||
|
|
||||||
Note that using accounts to track the inventory of a grocery store
|
|
||||||
causes an explosion of accounts, and this explosion would overwhelm
|
|
||||||
many of the account GUI's in GnuCash. The GUI should probably be
|
|
||||||
modified to treat inventory accounts in a special way, e.g. by
|
|
||||||
not listing them in account lists, and providing an alternate
|
|
||||||
management GUI.
|
|
||||||
|
|
||||||
\subsection Capital Gains
|
|
||||||
|
|
||||||
In the United States, gains on stock investments are taxed at different
|
|
||||||
rates depending on how long they were held before being sold. By using
|
|
||||||
lots with an investment account, it becomes easy to track when any given
|
|
||||||
share was bought or sold, and thus, the length of time that share was
|
|
||||||
held.
|
|
||||||
|
|
||||||
Note, however, that using lots might cause some confusion for naive
|
|
||||||
users, since some transactions might be split across different lots.
|
|
||||||
For example, the user may have conceptually made the following
|
|
||||||
transactions:
|
|
||||||
|
|
||||||
\verbatim
|
|
||||||
> Date Desc Buy Sell Price Value
|
|
||||||
> 18/1/01 XCORP 500 $10.00 $5000.00
|
|
||||||
> 21/3/01 XCORP 500 $12.00 $6000.00
|
|
||||||
> 14/7/02 XCORP 750 $20.00 $15000.00
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
However, the two buy transactions create different lots (because
|
|
||||||
you can't add to a stock-investment lot after its been created, because
|
|
||||||
the purchases occurred on different dates). Thus, when the shares are
|
|
||||||
sold, the sale is split across two lots:
|
|
||||||
|
|
||||||
\verbatim
|
|
||||||
> Date Desc Lot Buy Sell Price Value
|
|
||||||
> 18/1/01 XCORP 187 500 $10.00 $5000.00
|
|
||||||
> 21/3/01 XCORP 188 500 $12.00 $6000.00
|
|
||||||
> 14/7/02 XCORP 187 500 $20.00 $10000.00
|
|
||||||
> 14/7/02 XCORP 188 250 $20.00 $5000.00
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
In the above, lot 187 was closed, and lot 188 has a balance of 250
|
|
||||||
shares. Note that we used a FIFO accounting method in this example:
|
|
||||||
the oldest shares were sold first.
|
|
||||||
|
|
||||||
Note also, that by using lots in this example, we are able to accurately
|
|
||||||
compute the gains in this transaction: it is 500*($20-$10) + 250*($20-$12)
|
|
||||||
= $5000+$2000 = $7000. If we had used LIFO accounting, and sold the
|
|
||||||
youngest shares first, then the profits would have been 500*($20-$12)
|
|
||||||
+ 250*($20-$10) = $4000 + 2500 = $6500. Thus, different accounting
|
|
||||||
methods do affect income, and thus the tax rate.
|
|
||||||
|
|
||||||
Note that the two ledgers, the 'without-lots' and the 'with-lots'
|
|
||||||
ledgers look different, even though the conceptual transactions are
|
|
||||||
the same. If a naive user was expecting a 'without-lots' ledger,
|
|
||||||
and is shown a 'with lots' ledger, they may get confused. I don't
|
|
||||||
know of any simple way of dealing with this. In order to have lots
|
|
||||||
work (thereby allowing cap gains reports to work correctly), the GnuCash
|
|
||||||
engine *must* use the 'with-lots' representation of the data. If the
|
|
||||||
GUI wants to hide the fact that there are lots under the covers, it
|
|
||||||
must figure out a way of doing this (i.e. re-combining splits) on
|
|
||||||
its own.
|
|
||||||
|
|
||||||
\section lotsclosing Closing of Books
|
|
||||||
|
|
||||||
A few words on lots and the closing of books. Without lots, there
|
|
||||||
is really no way of correctly implementing book closing. That is
|
|
||||||
because some reports, such as the capital-gains report, need to know
|
|
||||||
not only the account balance, but also the purchase dates. Lots
|
|
||||||
provide the natural mechanism for storing this information.
|
|
||||||
|
|
||||||
When a book is closed, any open lots must be moved into/kept with
|
|
||||||
the open book. Since the splits in a lot belong to transactions,
|
|
||||||
and transactions are 'atomic', this means that the associated
|
|
||||||
transactions must be moved into the open book as well. A lot
|
|
||||||
is considered closed when its balance is zero; when a book is closed,
|
|
||||||
all of the lots that were closed stay with that book. That is,
|
|
||||||
closed lots are not propagated forward into the currently open book.
|
|
||||||
|
|
||||||
Actually, its slightly more subtle than that. Not only must open
|
|
||||||
lots stay with the open book, but so must all transactions that
|
|
||||||
have splits that participate in the open lot, and, by extension,
|
|
||||||
all closed lots that participate in these 'open transactions',
|
|
||||||
ad infinitum.
|
|
||||||
|
|
||||||
\section lotsdouble The "Double Balance" Requirement
|
|
||||||
|
|
||||||
The following is a proposal for how to handle both realized
|
|
||||||
and unrealized gains/losses by means of "adjusting transactions."
|
|
||||||
It works for simple cases, but has issues for more complex cases.
|
|
||||||
|
|
||||||
|
|
||||||
Canonical transaction balancing: If all splits in a transaction
|
|
||||||
are in the same 'currency' as the transaction currency, then the
|
|
||||||
sum of the splits *must* equal zero. This is the old, existing
|
|
||||||
double-entry requirement as implemented in Gnucash, and doesn't
|
|
||||||
change.
|
|
||||||
|
|
||||||
If some splits are in one commodity, and others in another, then
|
|
||||||
we can't force a zero balance as above. Instead, we will force
|
|
||||||
a different requirement, the 'double-balance' requirement:
|
|
||||||
|
|
||||||
- All splits that are *not* in the transaction currency C
|
|
||||||
must be made a part of a lot. (Thus, for example,
|
|
||||||
the transaction currency C is dollars, whereas the split
|
|
||||||
commodity is 'S', shares of RHAT. If a transaction
|
|
||||||
has C in dollars, and 'S' in RHAT, then the S split must
|
|
||||||
be made a part of a Lot.)
|
|
||||||
- The lot will have a designated 'lot currency' L that must
|
|
||||||
be the same as the C of every split in the lot. One
|
|
||||||
cannot enter a split into the lot if C != L. (That is,
|
|
||||||
if I'm working with a Lot of RHAT shares, then *all*
|
|
||||||
splits in the lot must belong to dollar-denominated
|
|
||||||
transactions.)
|
|
||||||
- When a lot is closed, we must have the 'double-balance'
|
|
||||||
condition: The sum total of all 'S' is zero, and the
|
|
||||||
sum total of all 'C' is zero. Thus, if I buy 100 shares
|
|
||||||
of RHAT for $5 and sell 100 shares of RHAT for $10, then
|
|
||||||
I *must* also add an 'adjusting transaction' for zero
|
|
||||||
shares of RHAT, at $500. If there is no adjusting transaction,
|
|
||||||
then the lot cannot be closed. If sum 'S' is zero,
|
|
||||||
while sum 'C' is not zero, then the lot is declared to
|
|
||||||
be 'out-of-balance', and an 'adjusting transaction' must
|
|
||||||
be forced.
|
|
||||||
|
|
||||||
It is only by 'closing a lot' that one is able to regain
|
|
||||||
'perfect balance' in the books. That is, the 'double-balance'
|
|
||||||
requirement is the generalization of the 'double-entry'
|
|
||||||
requirement for stock accounts.
|
|
||||||
|
|
||||||
Note that because the 'adjusting transaction' has one split
|
|
||||||
in dollars, and another split in RHAT shares (albeit for zero
|
|
||||||
RHAT shares), it evades the old double-entry requirement,
|
|
||||||
and will not be flagged as 'out of balance'. Note also
|
|
||||||
that because the 'adjusting transaction' contains a split
|
|
||||||
holding S (albeit zero S), it *must* be a part of a Lot.
|
|
||||||
|
|
||||||
|
|
||||||
The above seems to work for simple stock-transactions, but
|
|
||||||
fails in other more complex cases. Here's an example.
|
|
||||||
|
|
||||||
Imagine 'S' is in euros, instead of 'RHAT'. So I sell
|
|
||||||
100 dollars, and buy 110 euros. This causes a lot to open
|
|
||||||
up for the euros, with the lot currency 'L' in dollars.
|
|
||||||
Now I try to transfer the euros to other euro accounts.
|
|
||||||
What happens to the lot? Do I have to give up on it?
|
|
||||||
How can I save this bad situation?
|
|
||||||
|
|
||||||
A similar problem occurs for more complex stock transactions:
|
|
||||||
If I buy 100 shares of RHAT with Schwab, and transfer them
|
|
||||||
to another account with Etrade, then I have the same lot
|
|
||||||
closing problem. There's an even worse scenario, where
|
|
||||||
I move to Brazil, and take my RHAT stock (purchased in dollars)
|
|
||||||
to my Brazilian broker (who will sell them for cruzeiros).
|
|
||||||
|
|
||||||
Is the correct answer to just 'punt' in these cases?
|
|
||||||
How is the closing of books to be handled in such a case?
|
|
||||||
|
|
||||||
GUI Elements:
|
|
||||||
- The user should be able to specify a default 'realized-gain'
|
|
||||||
account that is associated with a stock account.
|
|
||||||
- The user should be able to specify a default 'unrealized-gain'
|
|
||||||
account that is associated with a stock account.
|
|
||||||
|
|
||||||
\section lotsfifo FIFO's
|
|
||||||
|
|
||||||
What is a FIFO ? A FIFO is a type of accounting policy where
|
|
||||||
income from selling inventory is accounted by selling the oldest
|
|
||||||
inventory first. Thus, the profit/loss of the sale corresponds
|
|
||||||
to the difference in price between when it was bought and sold.
|
|
||||||
FIFO's are also used in depreciation schedules, and in other places.
|
|
||||||
|
|
||||||
Currently the only policy that is implemented in the cap-gains
|
|
||||||
code is the FIFO policy. I believe that it's been abstracted
|
|
||||||
properly, so that it should be easy to add other policies,
|
|
||||||
e.g. LIFO. See policy.c for what would need to be implemented.
|
|
||||||
|
|
||||||
\section lotsimplement Implementation
|
|
||||||
|
|
||||||
Every split has a pointer to a lot (which may be null). A lot has a list
|
|
||||||
of splits in it (so that the other splits in the lot can be easily found).
|
|
||||||
A lot does not need to maintain a balance (this is easy enough to calculate
|
|
||||||
on the fly). A lot has a kvp tree (for storage of lot-related date, such
|
|
||||||
as due dates for invoices, etc. A lot has a GUID.
|
|
||||||
|
|
||||||
From the memory-management and data-base management point of view, lots
|
|
||||||
belong to accounts. The GnuCash account structure maintains a list of
|
|
||||||
lots so that all lots belonging to an account can be quickly retrieved.
|
|
||||||
(In principle, the lots can be found by scanning every split in the
|
|
||||||
account, but this is a painful process.)
|
|
||||||
|
|
||||||
\section lotscapgains Implementing Cap Gains (Is a Pain in the Neck)
|
|
||||||
|
|
||||||
Although Lots provide a good conceptual framework for determining
|
|
||||||
gains or losses when a lot is closed, cap-gains on half-open
|
|
||||||
lots present additional complexities. Consider the following
|
|
||||||
stock purchase and subsequent sale of half the stock:
|
|
||||||
|
|
||||||
Account A is a stock account
|
|
||||||
|
|
||||||
Account B is a bank account
|
|
||||||
|
|
||||||
Account C is an income account
|
|
||||||
\verbatim
|
|
||||||
Acct A Txn Acct B Acct C
|
|
||||||
Date Action Amt Prc Value Amt Amt
|
|
||||||
1/1/01 buy 100s $10 $1000 ($1000) -
|
|
||||||
2/2/02 sell (50)s $25 $1250 $1250 -
|
|
||||||
2/2/02 gain - - $750 $750
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
The gain, shown in the third line, is computed as a straight
|
|
||||||
sum of purchase price to sale price.
|
|
||||||
|
|
||||||
Should the above be represented as two transactions, or as three?
|
|
||||||
One could, in principle, combine the second and third lines into
|
|
||||||
one transaction. However, this has some drawbacks: computing
|
|
||||||
the overall balance of such a transaction is tricky, because
|
|
||||||
it has so many different splits (including, possibly, splits
|
|
||||||
for brokerage fees, tax, etc. not shown). The alternative
|
|
||||||
is to represent each line as a separate transaction. This has
|
|
||||||
other drawbacks: If the date, amount, price or value is adjusted
|
|
||||||
for the second transaction, the corresponding values must be
|
|
||||||
adjusted for the third, and vice-versa.
|
|
||||||
|
|
||||||
Both schemes pose trouble for the register display: we want
|
|
||||||
the stock register to show the gain as if it were a part of
|
|
||||||
the stock sale; but the third line is a pair of splits, and
|
|
||||||
we want to show only one of these two splits. Whichever method
|
|
||||||
is chosen, the register has to filter out some of the splits
|
|
||||||
that it shows.
|
|
||||||
|
|
||||||
The implementation that seems best is to represent the sale
|
|
||||||
with two separate transactions: one for the sale itself, and a
|
|
||||||
separate one for the gains. This makes computing the balance
|
|
||||||
easier, although it makes the logic for setting the date
|
|
||||||
more complex. Ughh..
|
|
||||||
|
|
||||||
\section loanscapnotes Cap Gains Implementation Notes
|
|
||||||
|
|
||||||
Cap Gains will be handled by GnuCash as described above, using
|
|
||||||
two distinct transactions. These transactions will be marked up
|
|
||||||
using KVP, pointing to each other, so that the one can be found
|
|
||||||
from the other. Implementation in src/engine/cap-gains.c
|
|
||||||
|
|
||||||
Quick API Overview:
|
|
||||||
- xaccSplitGetCapGains(): Returns the capital gains associated with
|
|
||||||
a split. Split must have been a sale/purchase in a previously
|
|
||||||
opened lot.
|
|
||||||
- xaccSplitAssignToLot(): If a split is not already in a lot,
|
|
||||||
then it places it into a lot, using a FIFO accounting policy.
|
|
||||||
|
|
||||||
\section lotscapimplement Cap Gains Actual Implementation
|
|
||||||
|
|
||||||
Cap Gains are noted by creating a separate transaction with two
|
|
||||||
splits in it. One of the splits is as described above: zero
|
|
||||||
amount, non-zero value. There is a GUI requirement that when
|
|
||||||
the looking at a gains transaction, certain things need to be
|
|
||||||
kept in sync with the transaction that is the source of the gains.
|
|
||||||
In order to accomplish this, the engine uses a set of 'dirty'
|
|
||||||
flags, and a pair of pointers between the gains split and the
|
|
||||||
source split, so that the one can be quickly found from the other.
|
|
||||||
|
|
||||||
Things kept in sync:
|
|
||||||
- date posted
|
|
||||||
- value
|
|
||||||
- void status
|
|
||||||
- other things ?
|
|
||||||
|
|
||||||
Things not kept in sync:
|
|
||||||
- kvp trees
|
|
||||||
- description, memo, action.
|
|
||||||
|
|
||||||
The posted date is kept in sync using a data-constraint scheme.
|
|
||||||
If xaccTransactionSetDatePosted() is called, the date change is
|
|
||||||
accepted, and the split is marked date-dirty. When the transaction
|
|
||||||
is committed (using xaccTransCommitEdit()), the date-dirty flag
|
|
||||||
is evaluated, and, if needed, the date changes are propagated/rolled
|
|
||||||
back on the appropriate gains splits. Currently, one can only change
|
|
||||||
the date on the gains-source transaction; the date on the
|
|
||||||
gains-recording split cannot be changed.
|
|
||||||
|
|
||||||
The value recorded by the gains transaction is updated whenever
|
|
||||||
the value of the source changes. The actual update is done by
|
|
||||||
the xaccSplitComputeCapGains() routine, via xaccScrubLot(), which
|
|
||||||
is called at the time of xaccTransCommitEdit(). Note that two
|
|
||||||
different things can affect the gains: a change in the value of
|
|
||||||
the sale, and a change of the value of the purchase. A set of
|
|
||||||
dirty flags are used to track these.
|
|
||||||
|
|
||||||
If the amount of a plit changes, then the lot that its in becomes
|
|
||||||
potentially unbalanced. This requires the lot membership to be
|
|
||||||
recomputed; this in turn may require the split to be split into
|
|
||||||
pieces, or to be recombined into one from several pieces.
|
|
||||||
|
|
||||||
\section lotstodo TODO
|
|
||||||
- need to copy void status when source split date changes.
|
|
||||||
- its possible for the the price, as recorded by one split
|
|
||||||
to vary wildly from that in another split in the same
|
|
||||||
transaction. That's bad, prices should be normalized.
|
|
||||||
There's a routine to do this, xaccScrubSubSplitPrice()
|
|
||||||
but its not currently used.
|
|
||||||
- write automated test cases to handle each situation.
|
|
||||||
|
|
||||||
\section lotsconversion Conversion
|
|
||||||
|
|
||||||
As Lots are put into production, old GnuCash datasets
|
|
||||||
will need to be converted. Conversion will be done by running
|
|
||||||
all splits in an account through an accounting policy (currently,
|
|
||||||
there is only one policy, a FIFO). The goal of the policy is to
|
|
||||||
match up purchases and sales so that these can be assigned to a Lot.
|
|
||||||
|
|
||||||
The conversion algorithm will work as follows:
|
|
||||||
\verbatim
|
|
||||||
for each account {
|
|
||||||
loop over splits {
|
|
||||||
// perform the 'double-balance' check
|
|
||||||
if (split commodity != transaction currency) account needs conversion
|
|
||||||
}
|
|
||||||
if account needs conversion
|
|
||||||
for each split {
|
|
||||||
If (split amount > 0) create new lot, put split in lot.
|
|
||||||
If (split amount < 0) find oldest lot, put split in that lot
|
|
||||||
}
|
|
||||||
}
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
See the file Scrub2.h for details of the low-level API, and Scrub3.h
|
|
||||||
for the high-level API.
|
|
||||||
|
|
||||||
There is a bit of a problem with this conversion procedure: If the
|
|
||||||
user had previously recorded cap gains using a 'handmade' version of
|
|
||||||
lots, those cap gains will be ignored and will throw off balances.
|
|
||||||
User will need to hand-edit to recover.
|
|
||||||
|
|
||||||
- TODO: Modify scrub routines to look for splits with zero amount,
|
|
||||||
try to assign these to lots as appropriate. ??
|
|
||||||
|
|
||||||
\section lotsgui GUI
|
|
||||||
|
|
||||||
A GUI for handling Lots is needed: ability to view a lot, and to cut/paste
|
|
||||||
or move a split from one lot to another. Need a GUI to create a lot,
|
|
||||||
maybe append some notes to it. Need ability to view account in lot-mode.
|
|
||||||
|
|
||||||
For automatically managing accounts, need to implement a variety of
|
|
||||||
different accounting policies (of which the FIFO policy is currently
|
|
||||||
implemented in the 'Scrub' routines).
|
|
||||||
|
|
||||||
\subsection lotsbasicgui Basic GUI
|
|
||||||
The goal of the basic GUI is to handle most usages of
|
|
||||||
most lots in most places. There also need to be special-purpose
|
|
||||||
dialogs for specific applications, e.g. stocks, inventory, etc.
|
|
||||||
|
|
||||||
Shows three areas:
|
|
||||||
- list of lots, one of which can be highlighted.
|
|
||||||
Lot names can be edited in-place.
|
|
||||||
- contents of a single lot (displayed in a narrow,
|
|
||||||
mini-register view, showing only date, memo, quant,
|
|
||||||
balance)
|
|
||||||
- list of splits not in any lot.
|
|
||||||
(not clear if screen real-estate allows side-by-side
|
|
||||||
placement, or if this must be above/below. above/below
|
|
||||||
would suck)
|
|
||||||
|
|
||||||
Shows various buttons:
|
|
||||||
- two arrows, which move split into/out of lot.
|
|
||||||
This is a traditional way of moving something from one
|
|
||||||
list to another, but some UI designers argue against this.
|
|
||||||
Is there a better way to move splits into/out-of a lot?
|
|
||||||
|
|
||||||
- button, labeled 'close lot', which, when pressed, will
|
|
||||||
set lot balance to zero. (by using fifo on the unassigned
|
|
||||||
splits, if possible).
|
|
||||||
|
|
||||||
- A field showing realized gain/loss on a closed lot, and
|
|
||||||
a pull-down allowing the gain/loss to be posted to a
|
|
||||||
specific account.
|
|
||||||
(The default is stored in kvp:/lots-mgmt/gains-acct/)
|
|
||||||
|
|
||||||
- button or menu item, 'add notes to this lot'.
|
|
||||||
|
|
||||||
\subsection lotsguitodo todo:
|
|
||||||
- change lot viewer to use gnc-query-list
|
|
||||||
- after the gnome2 port, add the 'unclaimed splits" window
|
|
||||||
to the lot viewer, this will allow it to be a simple lot editor.
|
|
||||||
- Add a new policy (or change the existing fifo policy) to only
|
|
||||||
open lots with a particular sign for the opening split. This
|
|
||||||
way, things like business invoice overpayments are not used
|
|
||||||
to start new lots, but are instead applied to new purchases.
|
|
||||||
|
|
||||||
\section lotsstatus Status
|
|
||||||
|
|
||||||
- Core support for Lots in the engine is complete (April 2002, ships in
|
|
||||||
version 1.8.x, used by business backend).
|
|
||||||
- See src/engine/gnc-lot.h for the public API.
|
|
||||||
- The XML backend support for lot is complete (April 2002, ships in
|
|
||||||
version 1.8.x).
|
|
||||||
- Scrub routines to automatically take old gnucash datasets and
|
|
||||||
transition them to double-balanced lots have been implemented.
|
|
||||||
These implement a FIFO accounting policy (April 2003)
|
|
||||||
- Closed/Open lots are handled correctly during book closing.
|
|
||||||
See src/engine/Period.c (August 2003)
|
|
||||||
- Work is finished on the automatic computation & tracking
|
|
||||||
of gain/loss transactions. Most of the engine API is in
|
|
||||||
src/engine/cap-gains.h although the high-level 'scrub' API
|
|
||||||
is in src/engine/Scrub3.h. See src/doc/constraints.txt for
|
|
||||||
a 'big picture' view of how its done. (September 2003)
|
|
||||||
- A basic lot-viewing GUI is in src/gnome/lot-viewer.c
|
|
||||||
This GUI cannot 'edit' lots. (August 2003)
|
|
||||||
- Need to write extensive test cases to verify the rather complex
|
|
||||||
constraints between the gains and lots and splits.
|
|
||||||
- Need to write a cap-gains report!
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
-------------------------- end of file ------------------------------
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
## @file
|
|
||||||
# @brief Documentation file for GnuCashs python bindings, input file for doxygen.
|
|
||||||
#
|
|
||||||
# This file holds the more explanatory parts of the doxygen-source-documentation.
|
|
||||||
# You will find the contents at @ref python_bindings_page.
|
|
||||||
#
|
|
||||||
# @par To-Do:
|
|
||||||
# @li Work out the relation of scheme/guile and python-bindings
|
|
||||||
# @li maybe join python_bindings_page and group
|
|
||||||
# @li work on the structure of the documentation to make it more clear
|
|
||||||
# @li try to make SWIG include the documentation of the c-source
|
|
||||||
# @li make function-links in SWIG-generated files work.
|
|
||||||
# @li some words to the tests
|
|
||||||
#
|
|
||||||
# @author Christoph Holtermann
|
|
||||||
# @date December 2010
|
|
||||||
# @ingroup python_bindings
|
|
||||||
|
|
||||||
|
|
||||||
## @defgroup python_bindings Python Bindings Module
|
|
||||||
# Also have a look at the page @ref python_bindings_page.
|
|
||||||
|
|
||||||
## @defgroup python_bindings_examples Python Bindings Examples Module
|
|
||||||
# @ingroup python_bindings
|
|
||||||
# The python-bindings come with quite a lot of example scripts.
|
|
||||||
|
|
||||||
## @page python_bindings_page Python bindings
|
|
||||||
# Also have a look at group @ref python_bindings.
|
|
||||||
#
|
|
||||||
# In the source tree they are located at bindings/python.
|
|
||||||
#
|
|
||||||
# To enable them in the compilation process you have to add -DWITH_PYTHON=ON
|
|
||||||
# to the call of cmake.
|
|
||||||
#
|
|
||||||
# As a starting point have a look at the \link python_bindings_examples example-scripts\endlink.
|
|
||||||
#
|
|
||||||
# @section possibilities What can Python Bindings be used for ?
|
|
||||||
#
|
|
||||||
# The python bindings supply the ability to access a wide range of the core functions of GnuCash. You
|
|
||||||
# can read and write Transactions, Commodities, Lots, access the business stuff... You gain the ability
|
|
||||||
# to manipulate your financial data with a flexible scripting language.
|
|
||||||
#
|
|
||||||
# Not everything GnuCash can is possible to access though. The bindings focus on basic accounting functions.
|
|
||||||
# Have a look at the examples to get an impression.
|
|
||||||
#
|
|
||||||
# Some functions are broken because they have not been wrapped properly. They may crash the program or return unaccessible values.
|
|
||||||
# Please file a bug report if you find one to help support the development process.
|
|
||||||
#
|
|
||||||
# @section python_bindings_section Principles
|
|
||||||
# The python-bindings are generated using SWIG from parts of the source-files of GnuCash.
|
|
||||||
#
|
|
||||||
# @note Python-scripts should not be executed while GnuCash runs. GnuCash is designed as
|
|
||||||
# a single user application with only one program accessing the data at one time. You can force your
|
|
||||||
# access but that may corrupt data. Maybe one day that may change but for the moment there is no active development on that.
|
|
||||||
#
|
|
||||||
# @subsection swigworks What SWIG does
|
|
||||||
#
|
|
||||||
# SWIG extracts information from the c-sources and provides access to the structures
|
|
||||||
# to python. It's work is controlled by interface files :
|
|
||||||
#
|
|
||||||
# @li gnucash_core.i
|
|
||||||
# @li timespec.i
|
|
||||||
# @li glib.i
|
|
||||||
# @li @link base-typemaps.i src/base-typemaps.i @endlink This file is shared with Guile.
|
|
||||||
#
|
|
||||||
# it outputs:
|
|
||||||
#
|
|
||||||
# @li gnucash_core.c
|
|
||||||
# @li gnucash_core_c.py
|
|
||||||
#
|
|
||||||
# If you have generated your own local doxygen documentation (by "make doc") after having compiled the python-bindings, doxygen
|
|
||||||
# will include SWIGs output-files.
|
|
||||||
# It's actually quite interesting to have a look at them through doxygen, because they contain all that you can
|
|
||||||
# access from python.
|
|
||||||
#
|
|
||||||
# This c-style-api is the bottom layer. It is a quite raw extract and close to the original source. Some more details are described further down.
|
|
||||||
#
|
|
||||||
# For some parts there is a second layer of a nice pythonic interface. It is declared
|
|
||||||
# in
|
|
||||||
# @li gnucash_core.py and
|
|
||||||
# @li gnucash_business.py.
|
|
||||||
# @li function_class.py contains helper functions for that.
|
|
||||||
#
|
|
||||||
# @section howto How to use the Python bindings
|
|
||||||
# @subsection highlevel High level python wrapper classes
|
|
||||||
# If you
|
|
||||||
#
|
|
||||||
# @code >> import gnucash @endcode
|
|
||||||
#
|
|
||||||
# You can access the structures of the high level api. For Example you get a Session object by
|
|
||||||
#
|
|
||||||
# @code >> session=gnucash.Session() @endcode
|
|
||||||
#
|
|
||||||
# Here you will find easy to use things. But sometimes - and at the current level rather sooner than
|
|
||||||
# later - you may be forced to search for solutions at the :
|
|
||||||
#
|
|
||||||
# @subsection c_style_api C-style-api
|
|
||||||
#
|
|
||||||
# If you
|
|
||||||
#
|
|
||||||
# @code >> import gnucash @endcode
|
|
||||||
#
|
|
||||||
# The c-style-api can be accessed via gnucash.gnucash_core_c. You can have a look at all the possibilities
|
|
||||||
# at gnucash_core_c.py.
|
|
||||||
#
|
|
||||||
# You will find a lot of pointers here which you can just ignore if input and output of the function have the
|
|
||||||
# same type.
|
|
||||||
#
|
|
||||||
# For example you could start a session by gnucash.gnucash_core_c.qof_session_begin(). But if you just try
|
|
||||||
#
|
|
||||||
# @code session=gnucash.gnucash_core_c.qof_session_begin() @endcode
|
|
||||||
#
|
|
||||||
# you will get an error message and realize the lack of convenience for you have to add the correct function parameters.
|
|
||||||
#
|
|
||||||
# Not all of the available structures will work. SWIG just takes everything from the sources that it is fed with and translates it. Not everything
|
|
||||||
# is a working translation, because not everything has been worked through. At this point you are getting closer to the developers who you can
|
|
||||||
# contact at the mailing-list gnucash-devel@gnucash.org. There may be a workaround. Maybe the problem can only be fixed by changing SWIGs input
|
|
||||||
# files to correctly translate the c-source. Feel free to post a question at the developers list. It may awaken the interest of someone who creates
|
|
||||||
# some more beautiful python-interfaces.
|
|
||||||
#
|
|
||||||
# @section Thisorthat When to use which api ?
|
|
||||||
#
|
|
||||||
# The start would surely be the high-level api for you can be quite sure to have something working and you will maybe find
|
|
||||||
# explanations in the example-scripts. If you search for something that is not yet implemented in that way you will have to
|
|
||||||
# take your way to the c-style-api.
|
|
||||||
#
|
|
||||||
# @section pydoc (Further) documentation
|
|
||||||
#
|
|
||||||
# @li The documentation you just read uses doxygen. It collects documentation in GnuCash's sources. Besides that there is
|
|
||||||
# @li the classic python-documentation using help() and docstrings. Have a look at both.
|
|
||||||
# @li There is a page in the GnuCash wiki at https://wiki.gnucash.org/wiki/Python
|
|
||||||
# @li You may also have a look into the archives of gnucash-devel@gnucash.org.
|
|
||||||
# @li On Bugzilla there is also some interesting talk regarding the development process.
|
|
||||||
# @li Then you can use the abilities of git to see the history of the code by @code git log @endcode done in the directory of the python-bindings.
|
|
||||||
#
|
|
||||||
@@ -282,7 +282,6 @@ set(engine_EXTRA_DIST
|
|||||||
README
|
README
|
||||||
README.query-api
|
README.query-api
|
||||||
SX-book-p.h
|
SX-book-p.h
|
||||||
TaxTableBillTermImmutability.txt
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (NOT WIN32)
|
if (NOT WIN32)
|
||||||
|
|||||||
@@ -335,3 +335,293 @@ gboolean SXRegister (void);
|
|||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/** \page loanhandling Handling loan repayment in GnuCash::Scheduled Transactions
|
||||||
|
* \sa The original email thread at <https://lists.gnucash.org/pipermail/gnucash-devel/2002-July/006438.html>.
|
||||||
|
*
|
||||||
|
* July, 2002 - jsled@asynchronous.org
|
||||||
|
*
|
||||||
|
* API: \ref SchedXaction
|
||||||
|
*
|
||||||
|
* We define loan repayment values in the following terms:
|
||||||
|
*
|
||||||
|
* Identifiers:\n
|
||||||
|
* P : the original principal. This is the overall principal afforded by the
|
||||||
|
* loan at the time of it's creation.\n
|
||||||
|
* P' : The beginning principal. This is the principal at the time of entry
|
||||||
|
* into GnuCash.\n
|
||||||
|
* I : The interest rate associated with the loan. Note that this may change
|
||||||
|
* over time [based on an addition to the Prime rate, for instance], at
|
||||||
|
* various frequencies [yearly, monthly, quarterly...]. Ideally, we can
|
||||||
|
* use the FreqSpec mechanism to facilitate the interest rate adjustment.\n
|
||||||
|
* N : The length of the loan in periods.\n
|
||||||
|
* m : The minimum periodic payment.\n
|
||||||
|
* n : The current period of the repayment.
|
||||||
|
*
|
||||||
|
* Functions:\n
|
||||||
|
* PMT : Total equal periodic payment, as per Gnumeric/Excel's definitions
|
||||||
|
* [see end for more detail].\n
|
||||||
|
* IPMT : Monthly payment interest portion, ""\n
|
||||||
|
* PPMT : Monthly payment principal portion, ""
|
||||||
|
*
|
||||||
|
* [ NOTE: 'PMT(I,N,P) = IPMT(I, n, N, P) + PPMT(I, n, N, P)' for 0 <= n < N ]
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* The formula entered into the SX template for a loan may then look like:
|
||||||
|
*
|
||||||
|
* Example 1:
|
||||||
|
* \verbatim
|
||||||
|
* Desc/Memo | Account | Credit | Debit
|
||||||
|
* ----------+-----------------------------+----------------+-------------------
|
||||||
|
* Repayment | Assets:Bank:Checking | | =PMT(I,n,N,P)
|
||||||
|
* | | | + fixed_amt
|
||||||
|
* Interest | Expenses:Loan_Name:Interest | =IPMT(I,n,N,P) |
|
||||||
|
* PMI | Expenses:Loan_Name:Misc | fixed_amt |
|
||||||
|
* Principal | Liabilities:Loan_Name | =PPMT(I,n,N,P) |
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
* \endverbatim
|
||||||
|
*
|
||||||
|
* Or, in the case where an escrow account is involved [with thanks to warlord
|
||||||
|
* for the review and fixes]:
|
||||||
|
*
|
||||||
|
* Example 2:
|
||||||
|
* \verbatim
|
||||||
|
* Desc/Memo | Account | Credit | Debit
|
||||||
|
* ---------------+-----------------------------+----------------+--------------
|
||||||
|
* Repayment | Assets:Bank:Checking | | =PMT(I,n,N,P)
|
||||||
|
* | | | + escrow_amt
|
||||||
|
* | | | + fixed_amt
|
||||||
|
* | | | + pre_payment
|
||||||
|
* Escrow | Assets:Loan_Escrow_acct | escrow_amt |
|
||||||
|
* Interest | Expenses:Loan_Name:Interest | =IPMT(I,n,N,P) |
|
||||||
|
* PMI | Expenses:Loan_Name:Misc | fixed_amt |
|
||||||
|
* Principal | Liabilities:Loan_Name | =PPMT(I,n,N,P) |
|
||||||
|
* | | + pre_payment |
|
||||||
|
* \endverbatim
|
||||||
|
*
|
||||||
|
* FreqSpec = 1 month
|
||||||
|
* \verbatim
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Desc/Memo | Account | Credit | Debit
|
||||||
|
* ---------------+-----------------------------+----------------+--------------
|
||||||
|
* Insurance | Assets:Loan_Escrow_acct | | insurance_amt
|
||||||
|
* Insurance | Expenses:Home_Insurance | insurance_amt |
|
||||||
|
* \endverbatim
|
||||||
|
*
|
||||||
|
* FreqSpec = 1 year
|
||||||
|
* \verbatim
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
* Desc/Memo | Account | Credit | Debit
|
||||||
|
* ---------------+-----------------------------+----------------+--------------
|
||||||
|
* Taxes | Assets:Loan_Escrow_acct | | taxes_amt
|
||||||
|
* Taxes | Expenses:Property_Taxes | taxes_amt |
|
||||||
|
* FreqSpec = Quarterly
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
* \endverbatim
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \section guidpractical Practical questions regarding the implementation of this facility are:
|
||||||
|
*
|
||||||
|
* | 1. The transactions as in Example 2 are not going to be scheduled for the\n
|
||||||
|
* | same day; are their values linked at all / do they need to share the\n
|
||||||
|
* | same var bindings?
|
||||||
|
*
|
||||||
|
* Yes, they would want to be linked. More precisely, the insurance/tax amounts
|
||||||
|
* are very likely linked to the escrow_amt in Ex.2. Unfortunately, these are
|
||||||
|
* very likely separate SXes...
|
||||||
|
*
|
||||||
|
* -----
|
||||||
|
* | 2. How does this effect the SX implementation of variables?
|
||||||
|
*
|
||||||
|
* Vastly.
|
||||||
|
*
|
||||||
|
* It becomes clear that multiple SXes will be related. While they'll have
|
||||||
|
* separate FreqSpecs and template transactions, they'll share some state. For
|
||||||
|
* both visualization [i.e., the SX list] and processing [credit/debit cell
|
||||||
|
* value computation] we'll want some manner of dealing with this.
|
||||||
|
*
|
||||||
|
* It becomes clear as well that the nature of variables and functions needs to
|
||||||
|
* be more clearly defined with respect to these issues. We probably want to
|
||||||
|
* institute a clear policy for the scoping of variables. As well, since the
|
||||||
|
* SXes will have different instantiation dates, we'll need a method and
|
||||||
|
* implementation for the relation of SXes to each other.
|
||||||
|
*
|
||||||
|
* A substantial hurdle is that if a set of SXes are [strongly] related, there
|
||||||
|
* is no-longer a single instantiation date for a set of related SXes. In fact,
|
||||||
|
* there may be different frequencies of recurrence.
|
||||||
|
*
|
||||||
|
* One option -- on the surface -- to relate them would be to maintain an
|
||||||
|
* instance variable-binding frame cache, which would store user-entered and
|
||||||
|
* computed variable bindings. The first instantiated SX of the set would create
|
||||||
|
* the frame, and the "last" instance would clean it up. First "last" instance
|
||||||
|
* is defined by the last-occurring SX in a related set, in a given time range.
|
||||||
|
*
|
||||||
|
* For example: a loan SX-set is defined by two monthly SXes ["repayment" and
|
||||||
|
* "insurance"], and a quarterly "tax" SX. The first monthly SX would create a
|
||||||
|
* frame, which would be passed two the second monthly SX. This would occur for
|
||||||
|
* the 3 months of interest. The Quarterly SX would get all 3 frames for it's
|
||||||
|
* creation, and use them in an /appropriate/ [read: to be defined through a lot
|
||||||
|
* of pain] way. As the time-based dependency relationship between the frames
|
||||||
|
* plays out, the frame can be removed from the system.
|
||||||
|
*
|
||||||
|
* Another option is to toss this idea entirely and instead let the user DTRT
|
||||||
|
* manually.
|
||||||
|
*
|
||||||
|
* A related option is to add the necessary grouping mechanism to the SX
|
||||||
|
* storage/data structure: immediately allowing visual grouping of related SXes,
|
||||||
|
* and potentially allowing a storage place for such frame data in the future
|
||||||
|
* with less file-versioning headache. This is the option that will be pursued.
|
||||||
|
*
|
||||||
|
* Another element implicit in the original requirements to support
|
||||||
|
* loans/repayment calculations is implicit variables. These are symbolic names
|
||||||
|
* which can be used and are automagically bound to values. The known implicit
|
||||||
|
* variables to support loan/repayment are:
|
||||||
|
*
|
||||||
|
* P [loan principal amount], N [loan repayment periods], I [interest], m
|
||||||
|
* [minimum payment] and n [current period]. Some of these [P, N, I, m] are
|
||||||
|
* fixed over many instances; some [n] are rebound specific to the instance.
|
||||||
|
* See the 'variable-scope-frame' below for a method of handling these
|
||||||
|
* variables.
|
||||||
|
*
|
||||||
|
* And yet-another element implicit in the original requirement is support for
|
||||||
|
* detecting and computing the result of functions in the template transaction's
|
||||||
|
* credit/debit cells. Changes to the src/app-utils/gnc-exp-parser.[hc] and
|
||||||
|
* src/calculation/expression_parser.[ch] to support functions would be
|
||||||
|
* necessitated. It is conceivable that after parsing, the parsed expression
|
||||||
|
* could be passed to scheme for evaluation. Hopefully this would make it
|
||||||
|
* easier to add support for new functions to the SX code via Scheme.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* | 3. How do we deal with periodic [yearly, semi-yearly] updating of various\n
|
||||||
|
* | "fixed" variables?
|
||||||
|
*
|
||||||
|
* Another change in the way variables are used is that some SXes -- especially
|
||||||
|
* loan-repayment -- may involve variables which are not tied to the instance of
|
||||||
|
* the SX, but rather to variables which:
|
||||||
|
* - are also involved in another SX
|
||||||
|
* - change with a frequency different than the SX
|
||||||
|
* - are represented by a relationship to the outside world ["prime + 1.7"]
|
||||||
|
*
|
||||||
|
* A partial fix for this problem is to provide multiple levels of scope for
|
||||||
|
* variable bindings, and expose this to the user by a method of assigning
|
||||||
|
* [perhaps time-dependent] values to these variables. Variables bound in this
|
||||||
|
* manner would absolve the user of the need to bind them at SX-creation time.
|
||||||
|
*
|
||||||
|
* An added benefit of this would be to allow some users [see Bug#85707] have
|
||||||
|
* "fixed variable" values for a group of SXes.
|
||||||
|
*
|
||||||
|
* In combination with the SX Grouping, this would provide most of a fix for the
|
||||||
|
* problem described in #2, above. The variable_frame could be used to provide
|
||||||
|
* the shared-state between related SXes, without imposing quite the same
|
||||||
|
* burden. This approach is slightly less flexible, but that allows it to be
|
||||||
|
* implemented more readily, and understood more easily.
|
||||||
|
*
|
||||||
|
* A question which comes up when thinking about yearly-changing values such as
|
||||||
|
* interest rates is if the historical information needs to be versioned. For
|
||||||
|
* now, we punt on this issue, but hopefully will provide enough of a framework
|
||||||
|
* for this to be reasonably added in the future.
|
||||||
|
*
|
||||||
|
* We define four types of variables supported by this scheme:
|
||||||
|
*
|
||||||
|
* implicit : provided only by the system
|
||||||
|
* e.g.: 'n', the current index of the repayment
|
||||||
|
*
|
||||||
|
* transient : have user-defined values, bound at instantiation time.
|
||||||
|
* e.g.: existing ad-hoc variables in SXes.
|
||||||
|
*
|
||||||
|
* static : have a user-defined values, and are not expected to change with
|
||||||
|
* any measurable frequency. The user may change these at their
|
||||||
|
* leisure, but no facility to assist or encourage this is
|
||||||
|
* provided.
|
||||||
|
* e.g.: paycheck amount, loan principal amount
|
||||||
|
*
|
||||||
|
* periodic : have user-defined values which change at specific points in
|
||||||
|
* time [July 1, yearly]. After the expiration of a variable value,
|
||||||
|
* it's re-binding will prevent any dependent SXes from being
|
||||||
|
* created.
|
||||||
|
* e.g.: loan tax amount, loan interest rate
|
||||||
|
*
|
||||||
|
* | 4. From where do we get the dollar amount against which to do the [PI]PMT\n
|
||||||
|
* | calculation?
|
||||||
|
*
|
||||||
|
* The user will specify the parameters of the Loan via some UI... then where
|
||||||
|
* does the data go?
|
||||||
|
*
|
||||||
|
* - KVP data for that account?
|
||||||
|
* - KVP data for the SX?
|
||||||
|
* - Do we have a different top-level "Loan" object?
|
||||||
|
* - Present only in the SX template transactions/variable-frames?
|
||||||
|
*
|
||||||
|
* I believe that the only location of the data after Druid creation is in the
|
||||||
|
* variable-binding frames and the formulae in the template transactions. The
|
||||||
|
* Druid would thus simply assist the user in creating the following SX-related
|
||||||
|
* structures:
|
||||||
|
*
|
||||||
|
* - SXGroup: Loan Repayment
|
||||||
|
* - variable_frame
|
||||||
|
* - P [static]
|
||||||
|
* - N [static]
|
||||||
|
* - n [implicit]
|
||||||
|
* - I [periodic]
|
||||||
|
* - pmi_amount [periodic]
|
||||||
|
* - tax_amount [periodic]
|
||||||
|
* - pre_payment [periodic]
|
||||||
|
* - insurance_amount [periodic]
|
||||||
|
* - SX: Payment
|
||||||
|
* - Bank -> { Escrow,
|
||||||
|
* Liability:Loan:Principal,
|
||||||
|
* Expense:Loan:Interest,
|
||||||
|
* Expense:Loan:Insurance }
|
||||||
|
* - SX: Tax
|
||||||
|
* - Escrow -> Expense:Tax
|
||||||
|
* - SX: Insurance
|
||||||
|
* - Escrow -> Expense:Insurance
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \section loansreference Reference
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \subsection loanssoftware Other software:
|
||||||
|
*
|
||||||
|
* Gnumeric supports the following functions WRT payment calculation:
|
||||||
|
*
|
||||||
|
* - PMT( rate, nper, pv [, fv, type] )
|
||||||
|
* PMT returns the amount of payment for a loan based on a constant interest
|
||||||
|
* rate and constant payments (ea. payment equal).
|
||||||
|
* @rate : constant interest rate
|
||||||
|
* @nper : overall number of payments
|
||||||
|
* @pv : present value
|
||||||
|
* @fv : future value
|
||||||
|
* @type : payment type
|
||||||
|
* - 0 : end of period
|
||||||
|
* - 1 : beginning of period
|
||||||
|
*
|
||||||
|
* - IPMT( rate, per, nper, pv, fv, type )
|
||||||
|
* IPMT calculates the amount of a payment of an annuity going towards
|
||||||
|
* interest. Formula for IPMT is:
|
||||||
|
* IPMT(per) = - principal(per-1) * interest_rate
|
||||||
|
* where:
|
||||||
|
* principal(per-1) = amount of the remaining principal from last period.
|
||||||
|
*
|
||||||
|
* - ISPMT( rate, per, nper, pv )
|
||||||
|
* ISPMT returns the interest paid on a given period.
|
||||||
|
* If @per < 1 or @per > @nper, returns #NUM! err.
|
||||||
|
*
|
||||||
|
* - PPMT(rate, per, nper, pv [, fv, type] )
|
||||||
|
* PPMT calculates the amount of a payment of an annuity going towards
|
||||||
|
* principal.
|
||||||
|
* PPMT(per) = PMT - IPMT(per)
|
||||||
|
* where: PMT is payment
|
||||||
|
* - IPMT is interest for period per
|
||||||
|
*
|
||||||
|
* - PV( rate, nper, pmt [, fv, type] )
|
||||||
|
* Calculates the present value of an investment
|
||||||
|
* @rate : periodic interest rate
|
||||||
|
* @nper : number of compounding periods
|
||||||
|
* @pmt : payment made each period
|
||||||
|
* @fv : future value
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
/**
|
|
||||||
\addtogroup Business
|
|
||||||
@{
|
|
||||||
\addtogroup ImmutableTaxTableBillTerm TaxTable and BillTerm immutability tracking
|
|
||||||
|
|
||||||
Derek Atkins <warlord@mit.edu>
|
|
||||||
Version of October 2003
|
|
||||||
|
|
||||||
The gncTaxTable and gncBillTerm business objects have parent, child,
|
|
||||||
refcount, invisible field in their structures that deserve some
|
|
||||||
explanation:
|
|
||||||
|
|
||||||
- a child is a 'frozen' instance of a parent. For example, the tax
|
|
||||||
percentage in a particular tax table may change over time, but you
|
|
||||||
dont want that change to affect already-posted invoices... So you
|
|
||||||
make sure there is an immutable 'copy' (read: child) of the tax
|
|
||||||
table when you post the invoice and repoint at the child.
|
|
||||||
|
|
||||||
- a parent can have many children, but it will only have a 'child'
|
|
||||||
pointer if the parent has not been modified. Think of this as a
|
|
||||||
copy-on-write mechanism. posted invoices will continue to use the
|
|
||||||
_same_ child until the parent is modified, at which point a new
|
|
||||||
child will be created.
|
|
||||||
|
|
||||||
- invisible means "dont show this in the list". It's so you dont
|
|
||||||
get all the children in the tax table list -- you only see parents.
|
|
||||||
I suppose this flag could also be called "is-child" as I believe that
|
|
||||||
only children can be invisible, and ALL children are invisible.
|
|
||||||
|
|
||||||
- refcount is a listing of how many objects are referencing it.
|
|
||||||
Basically, it's letting you know how many customer, vendor, entries,
|
|
||||||
etc are referencing e.g. a particular tax table object. mostly this
|
|
||||||
was done to make sure you cannot delete an in-use taxtable.
|
|
||||||
|
|
||||||
- children don't use refcounts, only parents do.
|
|
||||||
|
|
||||||
- A child always points to its parent (it can have only 1).
|
|
||||||
- A parent has a list of all children.
|
|
||||||
- A parent has a pointer to the current 'replica child', if one exists.
|
|
||||||
|
|
||||||
*/
|
|
||||||
@@ -194,3 +194,438 @@ GNCLot * gnc_lot_make_default (Account * acc);
|
|||||||
#endif /* GNC_LOT_H */
|
#endif /* GNC_LOT_H */
|
||||||
/** @} */
|
/** @} */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/** \page lotsoverview Lots Architecture & Implementation Overview
|
||||||
|
|
||||||
|
Linas Vepstas <linas@linas.org>
|
||||||
|
Last Revised May 2004
|
||||||
|
|
||||||
|
API \ref Lot
|
||||||
|
|
||||||
|
One often needs to know that the item 'bought' in one transaction
|
||||||
|
is the same one as the item 'sold' in a different transaction.
|
||||||
|
Lots are used to make this association. One Lot holds all of the
|
||||||
|
splits that involve the same item. A lot is typically formed when
|
||||||
|
the item is bought, and is closed when the item is sold out.
|
||||||
|
A lot need not be a single item, it can be a quantity of the same
|
||||||
|
thing e.g. 500 gallons of paint (sold off a few gallons at a time).
|
||||||
|
Lots are required to correctly implement invoices, inventory,
|
||||||
|
depreciation and stock market investment gains.
|
||||||
|
|
||||||
|
'Lots' capture a fundamental accounting idea behind AR/AP, billing,
|
||||||
|
inventory, capital gains, depreciation and the like. The basic idea
|
||||||
|
is that a set of items is tracked together as a 'lot'; the date of
|
||||||
|
creation of the lot helps determine when a bill is due, when depreciation
|
||||||
|
starts, or the tax rate for capital gains on a stock market investment.
|
||||||
|
|
||||||
|
\section lotsdefines Definition
|
||||||
|
|
||||||
|
In GnuCash, a 'lot' will consist of a set of splits identified with
|
||||||
|
a unique lot number. Any given split can belong to one lot and one
|
||||||
|
lot only. All splits in a lot must also belong to the same account.
|
||||||
|
Lots have a 'balance': the sum of all the splits in the lot. A lot
|
||||||
|
is 'opened' when the first split is assigned to it. The date of that
|
||||||
|
split is the 'opening date' of the lot, and its quantity is the
|
||||||
|
'opening balance'. A lot is 'closed' when its balance is zero;
|
||||||
|
once closed, a lot cannot be re-opened. Open lots are always carried
|
||||||
|
forward into the current open book; closed lots are left behind in the
|
||||||
|
book in which they were closed.
|
||||||
|
|
||||||
|
\section How Lots Are Used
|
||||||
|
|
||||||
|
The following sections review how lots are used to implement various
|
||||||
|
accounting devices, and some of the related issues.
|
||||||
|
|
||||||
|
\subsection Billing
|
||||||
|
|
||||||
|
Tracking lots is the 'definition' of A/R and A/P. You want to be able
|
||||||
|
to say that this bill is 120 days old, and its balance has been partly
|
||||||
|
paid off; and you want to be able to do this whether or not there are
|
||||||
|
also other bills, of different ages, to the same company. In GnuCash,
|
||||||
|
a 'bill' is tracked as a lot: The 'billing date' is the opening date
|
||||||
|
of the lot, and the 'balance due' is the balance of the lot. When the
|
||||||
|
bill is 'paid in full', the lot is closed. The average age of
|
||||||
|
receivables can be computed by traversing all lots, etc. Additional
|
||||||
|
information about bills, such as a due date or payment terms, should
|
||||||
|
be stored as kvp values associated with the lot.
|
||||||
|
|
||||||
|
\subsection Billing Example
|
||||||
|
|
||||||
|
Normally, there is a one-to-one correspondence between bills and
|
||||||
|
lots: there is one lot per bill, and one bill per lot. (Note: this
|
||||||
|
is not how gnucash invoices are currently implemented; this is a
|
||||||
|
proposed implementation.)
|
||||||
|
|
||||||
|
For example:
|
||||||
|
\verbatim
|
||||||
|
invoice #258 customer XXX
|
||||||
|
Order placed 20 December 2001
|
||||||
|
quant (10) gallons paint $10/each $100
|
||||||
|
quant (2) paintbrushes $15/each $30
|
||||||
|
sales tax $8.27
|
||||||
|
------------
|
||||||
|
Total due $138.27
|
||||||
|
|
||||||
|
Payment received 24 january 2002 $50 Balance Due: $88.27
|
||||||
|
Payment received 13 february 2002 $60 Balance Due: $28.27
|
||||||
|
Payment received 18 march 2002 $28.27 PAID IN FULL
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
In this example, the lot encompasses four transactions, dated
|
||||||
|
December, January, February and March. The December transaction
|
||||||
|
opens the lot, and gives it a non-zero balance. To be precise,
|
||||||
|
the lot actually consists of four splits, belonging to four
|
||||||
|
different transactions. All four splits are a part of an imagined
|
||||||
|
"Accounts Receivable-Billing" account. The first split is for
|
||||||
|
$138.27, the second split is for $50, the third split is for $60,
|
||||||
|
and the fourth split is for $28.27. Note that the sales-tax
|
||||||
|
split, and th paint/paint-brush splits are *NOT* a part of this
|
||||||
|
lot. They are only a part of the transaction that opened this lot.
|
||||||
|
|
||||||
|
Note also that this example might also encompass two other lots:
|
||||||
|
the transfer of paint may belong to a lot in the "Paint Inventory"
|
||||||
|
account, and the split describing the paintbrushes might be a part
|
||||||
|
of a lot in the "Paintbrush Inventory" account. These lots should
|
||||||
|
not be confused with the invoice lot.
|
||||||
|
|
||||||
|
\subsection lotsinventory Inventory
|
||||||
|
|
||||||
|
The correct way of handling inventory under GnuCash is to have a
|
||||||
|
separate account for each widget type. The account balance represents
|
||||||
|
how many widgets there are in the warehouse. Lots offer an additional
|
||||||
|
level of detail that can be useful when, for example, the widgets have
|
||||||
|
an expiration date (e.g. milk) or vary slightly from batch to batch
|
||||||
|
(e.g paint), and creating a new account to track these differences
|
||||||
|
would be too heavy-weight.
|
||||||
|
|
||||||
|
In order to track widgets as single units (and prohibit fractional
|
||||||
|
widgets), set the currency denominator to 1. This will prevent
|
||||||
|
fractional widgets from being transferred into/out of an account.
|
||||||
|
|
||||||
|
Note that using accounts to track the inventory of a grocery store
|
||||||
|
causes an explosion of accounts, and this explosion would overwhelm
|
||||||
|
many of the account GUI's in GnuCash. The GUI should probably be
|
||||||
|
modified to treat inventory accounts in a special way, e.g. by
|
||||||
|
not listing them in account lists, and providing an alternate
|
||||||
|
management GUI.
|
||||||
|
|
||||||
|
\subsection Capital Gains
|
||||||
|
|
||||||
|
In the United States, gains on stock investments are taxed at different
|
||||||
|
rates depending on how long they were held before being sold. By using
|
||||||
|
lots with an investment account, it becomes easy to track when any given
|
||||||
|
share was bought or sold, and thus, the length of time that share was
|
||||||
|
held.
|
||||||
|
|
||||||
|
Note, however, that using lots might cause some confusion for naive
|
||||||
|
users, since some transactions might be split across different lots.
|
||||||
|
For example, the user may have conceptually made the following
|
||||||
|
transactions:
|
||||||
|
|
||||||
|
\verbatim
|
||||||
|
> Date Desc Buy Sell Price Value
|
||||||
|
> 18/1/01 XCORP 500 $10.00 $5000.00
|
||||||
|
> 21/3/01 XCORP 500 $12.00 $6000.00
|
||||||
|
> 14/7/02 XCORP 750 $20.00 $15000.00
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
However, the two buy transactions create different lots (because
|
||||||
|
you can't add to a stock-investment lot after its been created, because
|
||||||
|
the purchases occurred on different dates). Thus, when the shares are
|
||||||
|
sold, the sale is split across two lots:
|
||||||
|
|
||||||
|
\verbatim
|
||||||
|
> Date Desc Lot Buy Sell Price Value
|
||||||
|
> 18/1/01 XCORP 187 500 $10.00 $5000.00
|
||||||
|
> 21/3/01 XCORP 188 500 $12.00 $6000.00
|
||||||
|
> 14/7/02 XCORP 187 500 $20.00 $10000.00
|
||||||
|
> 14/7/02 XCORP 188 250 $20.00 $5000.00
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
In the above, lot 187 was closed, and lot 188 has a balance of 250
|
||||||
|
shares. Note that we used a FIFO accounting method in this example:
|
||||||
|
the oldest shares were sold first.
|
||||||
|
|
||||||
|
Note also, that by using lots in this example, we are able to accurately
|
||||||
|
compute the gains in this transaction: it is 500*($20-$10) + 250*($20-$12)
|
||||||
|
= $5000+$2000 = $7000. If we had used LIFO accounting, and sold the
|
||||||
|
youngest shares first, then the profits would have been 500*($20-$12)
|
||||||
|
+ 250*($20-$10) = $4000 + 2500 = $6500. Thus, different accounting
|
||||||
|
methods do affect income, and thus the tax rate.
|
||||||
|
|
||||||
|
Note that the two ledgers, the 'without-lots' and the 'with-lots'
|
||||||
|
ledgers look different, even though the conceptual transactions are
|
||||||
|
the same. If a naive user was expecting a 'without-lots' ledger,
|
||||||
|
and is shown a 'with lots' ledger, they may get confused. I don't
|
||||||
|
know of any simple way of dealing with this. In order to have lots
|
||||||
|
work (thereby allowing cap gains reports to work correctly), the GnuCash
|
||||||
|
engine *must* use the 'with-lots' representation of the data. If the
|
||||||
|
GUI wants to hide the fact that there are lots under the covers, it
|
||||||
|
must figure out a way of doing this (i.e. re-combining splits) on
|
||||||
|
its own.
|
||||||
|
|
||||||
|
\section lotsclosing Closing of Books
|
||||||
|
|
||||||
|
A few words on lots and the closing of books. Without lots, there
|
||||||
|
is really no way of correctly implementing book closing. That is
|
||||||
|
because some reports, such as the capital-gains report, need to know
|
||||||
|
not only the account balance, but also the purchase dates. Lots
|
||||||
|
provide the natural mechanism for storing this information.
|
||||||
|
|
||||||
|
When a book is closed, any open lots must be moved into/kept with
|
||||||
|
the open book. Since the splits in a lot belong to transactions,
|
||||||
|
and transactions are 'atomic', this means that the associated
|
||||||
|
transactions must be moved into the open book as well. A lot
|
||||||
|
is considered closed when its balance is zero; when a book is closed,
|
||||||
|
all of the lots that were closed stay with that book. That is,
|
||||||
|
closed lots are not propagated forward into the currently open book.
|
||||||
|
|
||||||
|
Actually, its slightly more subtle than that. Not only must open
|
||||||
|
lots stay with the open book, but so must all transactions that
|
||||||
|
have splits that participate in the open lot, and, by extension,
|
||||||
|
all closed lots that participate in these 'open transactions',
|
||||||
|
ad infinitum.
|
||||||
|
|
||||||
|
\section lotsdouble The "Double Balance" Requirement
|
||||||
|
|
||||||
|
The following is a proposal for how to handle both realized
|
||||||
|
and unrealized gains/losses by means of "adjusting transactions."
|
||||||
|
It works for simple cases, but has issues for more complex cases.
|
||||||
|
|
||||||
|
|
||||||
|
Canonical transaction balancing: If all splits in a transaction
|
||||||
|
are in the same 'currency' as the transaction currency, then the
|
||||||
|
sum of the splits *must* equal zero. This is the old, existing
|
||||||
|
double-entry requirement as implemented in Gnucash, and doesn't
|
||||||
|
change.
|
||||||
|
|
||||||
|
If some splits are in one commodity, and others in another, then
|
||||||
|
we can't force a zero balance as above. Instead, we will force
|
||||||
|
a different requirement, the 'double-balance' requirement:
|
||||||
|
|
||||||
|
- All splits that are *not* in the transaction currency C
|
||||||
|
must be made a part of a lot. (Thus, for example,
|
||||||
|
the transaction currency C is dollars, whereas the split
|
||||||
|
commodity is 'S', shares of RHAT. If a transaction
|
||||||
|
has C in dollars, and 'S' in RHAT, then the S split must
|
||||||
|
be made a part of a Lot.)
|
||||||
|
- The lot will have a designated 'lot currency' L that must
|
||||||
|
be the same as the C of every split in the lot. One
|
||||||
|
cannot enter a split into the lot if C != L. (That is,
|
||||||
|
if I'm working with a Lot of RHAT shares, then *all*
|
||||||
|
splits in the lot must belong to dollar-denominated
|
||||||
|
transactions.)
|
||||||
|
- When a lot is closed, we must have the 'double-balance'
|
||||||
|
condition: The sum total of all 'S' is zero, and the
|
||||||
|
sum total of all 'C' is zero. Thus, if I buy 100 shares
|
||||||
|
of RHAT for $5 and sell 100 shares of RHAT for $10, then
|
||||||
|
I *must* also add an 'adjusting transaction' for zero
|
||||||
|
shares of RHAT, at $500. If there is no adjusting transaction,
|
||||||
|
then the lot cannot be closed. If sum 'S' is zero,
|
||||||
|
while sum 'C' is not zero, then the lot is declared to
|
||||||
|
be 'out-of-balance', and an 'adjusting transaction' must
|
||||||
|
be forced.
|
||||||
|
|
||||||
|
It is only by 'closing a lot' that one is able to regain
|
||||||
|
'perfect balance' in the books. That is, the 'double-balance'
|
||||||
|
requirement is the generalization of the 'double-entry'
|
||||||
|
requirement for stock accounts.
|
||||||
|
|
||||||
|
Note that because the 'adjusting transaction' has one split
|
||||||
|
in dollars, and another split in RHAT shares (albeit for zero
|
||||||
|
RHAT shares), it evades the old double-entry requirement,
|
||||||
|
and will not be flagged as 'out of balance'. Note also
|
||||||
|
that because the 'adjusting transaction' contains a split
|
||||||
|
holding S (albeit zero S), it *must* be a part of a Lot.
|
||||||
|
|
||||||
|
|
||||||
|
The above seems to work for simple stock-transactions, but
|
||||||
|
fails in other more complex cases. Here's an example.
|
||||||
|
|
||||||
|
Imagine 'S' is in euros, instead of 'RHAT'. So I sell
|
||||||
|
100 dollars, and buy 110 euros. This causes a lot to open
|
||||||
|
up for the euros, with the lot currency 'L' in dollars.
|
||||||
|
Now I try to transfer the euros to other euro accounts.
|
||||||
|
What happens to the lot? Do I have to give up on it?
|
||||||
|
How can I save this bad situation?
|
||||||
|
|
||||||
|
A similar problem occurs for more complex stock transactions:
|
||||||
|
If I buy 100 shares of RHAT with Schwab, and transfer them
|
||||||
|
to another account with Etrade, then I have the same lot
|
||||||
|
closing problem. There's an even worse scenario, where
|
||||||
|
I move to Brazil, and take my RHAT stock (purchased in dollars)
|
||||||
|
to my Brazilian broker (who will sell them for cruzeiros).
|
||||||
|
|
||||||
|
Is the correct answer to just 'punt' in these cases?
|
||||||
|
How is the closing of books to be handled in such a case?
|
||||||
|
|
||||||
|
GUI Elements:
|
||||||
|
- The user should be able to specify a default 'realized-gain'
|
||||||
|
account that is associated with a stock account.
|
||||||
|
- The user should be able to specify a default 'unrealized-gain'
|
||||||
|
account that is associated with a stock account.
|
||||||
|
|
||||||
|
\section lotsfifo FIFO's
|
||||||
|
|
||||||
|
What is a FIFO ? A FIFO is a type of accounting policy where
|
||||||
|
income from selling inventory is accounted by selling the oldest
|
||||||
|
inventory first. Thus, the profit/loss of the sale corresponds
|
||||||
|
to the difference in price between when it was bought and sold.
|
||||||
|
FIFO's are also used in depreciation schedules, and in other places.
|
||||||
|
|
||||||
|
Currently the only policy that is implemented in the cap-gains
|
||||||
|
code is the FIFO policy. I believe that it's been abstracted
|
||||||
|
properly, so that it should be easy to add other policies,
|
||||||
|
e.g. LIFO. See policy.c for what would need to be implemented.
|
||||||
|
|
||||||
|
\section lotsimplement Implementation
|
||||||
|
|
||||||
|
Every split has a pointer to a lot (which may be null). A lot has a list
|
||||||
|
of splits in it (so that the other splits in the lot can be easily found).
|
||||||
|
A lot does not need to maintain a balance (this is easy enough to calculate
|
||||||
|
on the fly). A lot has a kvp tree (for storage of lot-related date, such
|
||||||
|
as due dates for invoices, etc. A lot has a GUID.
|
||||||
|
|
||||||
|
From the memory-management and data-base management point of view, lots
|
||||||
|
belong to accounts. The GnuCash account structure maintains a list of
|
||||||
|
lots so that all lots belonging to an account can be quickly retrieved.
|
||||||
|
(In principle, the lots can be found by scanning every split in the
|
||||||
|
account, but this is a painful process.)
|
||||||
|
|
||||||
|
\section lotscapgains Implementing Cap Gains (Is a Pain in the Neck)
|
||||||
|
|
||||||
|
Although Lots provide a good conceptual framework for determining
|
||||||
|
gains or losses when a lot is closed, cap-gains on half-open
|
||||||
|
lots present additional complexities. Consider the following
|
||||||
|
stock purchase and subsequent sale of half the stock:
|
||||||
|
|
||||||
|
Account A is a stock account
|
||||||
|
|
||||||
|
Account B is a bank account
|
||||||
|
|
||||||
|
Account C is an income account
|
||||||
|
\verbatim
|
||||||
|
Acct A Txn Acct B Acct C
|
||||||
|
Date Action Amt Prc Value Amt Amt
|
||||||
|
1/1/01 buy 100s $10 $1000 ($1000) -
|
||||||
|
2/2/02 sell (50)s $25 $1250 $1250 -
|
||||||
|
2/2/02 gain - - $750 $750
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
The gain, shown in the third line, is computed as a straight
|
||||||
|
sum of purchase price to sale price.
|
||||||
|
|
||||||
|
Should the above be represented as two transactions, or as three?
|
||||||
|
One could, in principle, combine the second and third lines into
|
||||||
|
one transaction. However, this has some drawbacks: computing
|
||||||
|
the overall balance of such a transaction is tricky, because
|
||||||
|
it has so many different splits (including, possibly, splits
|
||||||
|
for brokerage fees, tax, etc. not shown). The alternative
|
||||||
|
is to represent each line as a separate transaction. This has
|
||||||
|
other drawbacks: If the date, amount, price or value is adjusted
|
||||||
|
for the second transaction, the corresponding values must be
|
||||||
|
adjusted for the third, and vice-versa.
|
||||||
|
|
||||||
|
Both schemes pose trouble for the register display: we want
|
||||||
|
the stock register to show the gain as if it were a part of
|
||||||
|
the stock sale; but the third line is a pair of splits, and
|
||||||
|
we want to show only one of these two splits. Whichever method
|
||||||
|
is chosen, the register has to filter out some of the splits
|
||||||
|
that it shows.
|
||||||
|
|
||||||
|
The implementation that seems best is to represent the sale
|
||||||
|
with two separate transactions: one for the sale itself, and a
|
||||||
|
separate one for the gains. This makes computing the balance
|
||||||
|
easier, although it makes the logic for setting the date
|
||||||
|
more complex. Ughh..
|
||||||
|
|
||||||
|
\section loanscapnotes Cap Gains Implementation Notes
|
||||||
|
|
||||||
|
Cap Gains will be handled by GnuCash as described above, using
|
||||||
|
two distinct transactions. These transactions will be marked up
|
||||||
|
using KVP, pointing to each other, so that the one can be found
|
||||||
|
from the other. Implementation in src/engine/cap-gains.c
|
||||||
|
|
||||||
|
Quick API Overview:
|
||||||
|
- xaccSplitGetCapGains(): Returns the capital gains associated with
|
||||||
|
a split. Split must have been a sale/purchase in a previously
|
||||||
|
opened lot.
|
||||||
|
- xaccSplitAssignToLot(): If a split is not already in a lot,
|
||||||
|
then it places it into a lot, using a FIFO accounting policy.
|
||||||
|
|
||||||
|
\section lotscapimplement Cap Gains Actual Implementation
|
||||||
|
|
||||||
|
Cap Gains are noted by creating a separate transaction with two
|
||||||
|
splits in it. One of the splits is as described above: zero
|
||||||
|
amount, non-zero value. There is a GUI requirement that when
|
||||||
|
the looking at a gains transaction, certain things need to be
|
||||||
|
kept in sync with the transaction that is the source of the gains.
|
||||||
|
In order to accomplish this, the engine uses a set of 'dirty'
|
||||||
|
flags, and a pair of pointers between the gains split and the
|
||||||
|
source split, so that the one can be quickly found from the other.
|
||||||
|
|
||||||
|
Things kept in sync:
|
||||||
|
- date posted
|
||||||
|
- value
|
||||||
|
- void status
|
||||||
|
- other things ?
|
||||||
|
|
||||||
|
Things not kept in sync:
|
||||||
|
- kvp trees
|
||||||
|
- description, memo, action.
|
||||||
|
|
||||||
|
The posted date is kept in sync using a data-constraint scheme.
|
||||||
|
If xaccTransactionSetDatePosted() is called, the date change is
|
||||||
|
accepted, and the split is marked date-dirty. When the transaction
|
||||||
|
is committed (using xaccTransCommitEdit()), the date-dirty flag
|
||||||
|
is evaluated, and, if needed, the date changes are propagated/rolled
|
||||||
|
back on the appropriate gains splits. Currently, one can only change
|
||||||
|
the date on the gains-source transaction; the date on the
|
||||||
|
gains-recording split cannot be changed.
|
||||||
|
|
||||||
|
The value recorded by the gains transaction is updated whenever
|
||||||
|
the value of the source changes. The actual update is done by
|
||||||
|
the xaccSplitComputeCapGains() routine, via xaccScrubLot(), which
|
||||||
|
is called at the time of xaccTransCommitEdit(). Note that two
|
||||||
|
different things can affect the gains: a change in the value of
|
||||||
|
the sale, and a change of the value of the purchase. A set of
|
||||||
|
dirty flags are used to track these.
|
||||||
|
|
||||||
|
If the amount of a split changes, then the lot that its in becomes
|
||||||
|
potentially unbalanced. This requires the lot membership to be
|
||||||
|
recomputed; this in turn may require the split to be split into
|
||||||
|
pieces, or to be recombined into one from several pieces.
|
||||||
|
|
||||||
|
\section lotsconversion Conversion
|
||||||
|
|
||||||
|
As Lots are put into production, old GnuCash datasets
|
||||||
|
will need to be converted. Conversion will be done by running
|
||||||
|
all splits in an account through an accounting policy (currently,
|
||||||
|
there is only one policy, a FIFO). The goal of the policy is to
|
||||||
|
match up purchases and sales so that these can be assigned to a Lot.
|
||||||
|
|
||||||
|
The conversion algorithm will work as follows:
|
||||||
|
\verbatim
|
||||||
|
for each account {
|
||||||
|
loop over splits {
|
||||||
|
// perform the 'double-balance' check
|
||||||
|
if (split commodity != transaction currency) account needs conversion
|
||||||
|
}
|
||||||
|
if account needs conversion
|
||||||
|
for each split {
|
||||||
|
If (split amount > 0) create new lot, put split in lot.
|
||||||
|
If (split amount < 0) find oldest lot, put split in that lot
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
See the file Scrub2.h for details of the low-level API, and Scrub3.h
|
||||||
|
for the high-level API.
|
||||||
|
|
||||||
|
There is a bit of a problem with this conversion procedure: If the
|
||||||
|
user had previously recorded cap gains using a 'handmade' version of
|
||||||
|
lots, those cap gains will be ignored and will throw off balances.
|
||||||
|
User will need to hand-edit to recover.
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|||||||
@@ -27,9 +27,47 @@
|
|||||||
* @author Copyright (C) 2002 Derek Atkins
|
* @author Copyright (C) 2002 Derek Atkins
|
||||||
* @author Derek Atkins <warlord@MIT.EDU>
|
* @author Derek Atkins <warlord@MIT.EDU>
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
@page ImmutableTaxTableBillTerm Some notes on tracking fields in gncBillTerm and gncTaxTable objects
|
||||||
|
|
||||||
|
The gncTaxTable and gncBillTerm business objects have parent, child,
|
||||||
|
refcount, invisible field in their structures that deserve some
|
||||||
|
explanation:
|
||||||
|
|
||||||
|
- a child is a 'frozen' instance of a parent. For example, the tax
|
||||||
|
percentage in a particular tax table may change over time, but you
|
||||||
|
dont want that change to affect already-posted invoices... So you
|
||||||
|
make sure there is an immutable 'copy' (read: child) of the tax
|
||||||
|
table when you post the invoice and repoint at the child.
|
||||||
|
|
||||||
|
- a parent can have many children, but it will only have a 'child'
|
||||||
|
pointer if the parent has not been modified. Think of this as a
|
||||||
|
copy-on-write mechanism. posted invoices will continue to use the
|
||||||
|
_same_ child until the parent is modified, at which point a new
|
||||||
|
child will be created.
|
||||||
|
|
||||||
|
- invisible means "dont show this in the list". It's so you dont
|
||||||
|
get all the children in the tax table list -- you only see parents.
|
||||||
|
I suppose this flag could also be called "is-child" as I believe that
|
||||||
|
only children can be invisible, and ALL children are invisible.
|
||||||
|
|
||||||
|
- refcount is a listing of how many objects are referencing it.
|
||||||
|
Basically, it's letting you know how many customer, vendor, entries,
|
||||||
|
etc are referencing e.g. a particular tax table object. mostly this
|
||||||
|
was done to make sure you cannot delete an in-use taxtable.
|
||||||
|
|
||||||
|
- children don't use refcounts, only parents do.
|
||||||
|
|
||||||
|
- A child always points to its parent (it can have only 1).
|
||||||
|
- A parent has a list of all children.
|
||||||
|
- A parent has a pointer to the current 'replica child', if one exists.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
|
||||||
#ifndef GNC_BUSINESS_H_
|
#ifndef GNC_BUSINESS_H_
|
||||||
#define GNC_BUSINESS_H_
|
#define GNC_BUSINESS_H_
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,13 @@
|
|||||||
/** @addtogroup Business
|
/** @addtogroup Business
|
||||||
@{ */
|
@{ */
|
||||||
/** @addtogroup TaxTable
|
/** @addtogroup TaxTable
|
||||||
|
Define an object to track tax properties for invoices.
|
||||||
|
|
||||||
|
@note A tax table added to an invoice is immutable, that is it
|
||||||
|
can't change any more. To achieve that a tax table is copied when
|
||||||
|
added to an invoice. This uses some internal fields to track this which
|
||||||
|
are explained in @ref ImmutableTaxTableBillTerm.
|
||||||
|
|
||||||
@{ */
|
@{ */
|
||||||
/** @file gncTaxTable.h
|
/** @file gncTaxTable.h
|
||||||
@brief Tax Table programming interface
|
@brief Tax Table programming interface
|
||||||
|
|||||||
Reference in New Issue
Block a user