Doxygen - drop several txt files that were included in

docygen_mainpage.c

None of them had useful information describing actual
implementation concepts or details.
This commit is contained in:
Geert Janssens 2024-05-19 19:46:06 +02:00
parent 3c860737f1
commit 58b4ee35f0
25 changed files with 2 additions and 3642 deletions

View File

@ -4,34 +4,16 @@ endif()
add_subdirectory(xml)
set(doc_FILES
backup.txt
books.txt
budget.txt
callgrind.txt
constderv.html
# constraints.txt
currencies.txt
doxygen.cfg.in
doxygen_main_page.c
# engine.txt
finderv.html
finutil.html
# g2-architecture.txt
generic-druid-framework.txt
# gnc-numeric-example.txt
guid.txt
loans.txt
lots.txt
multicurrency-discussion.txt
# prices.txt
python-bindings-doxygen.py
qif.txt
README
# sx.rst
tax.txt
TODO-schedxactions
TODO-sixtp
user-prefs-howto.txt
)
set_local_dist(doc_DIST_local CMakeLists.txt ${doc_FILES})

View File

@ -1,584 +0,0 @@
Author: jsled@asynchronous.org
Main Scheduled Transaction todo list
------------------------------------
. Bug#102311...
. As per comment 2004-01-05T16:31, there is an issue when other pieces of
the system change accounts that SXes depend on. We have two options:
1: handle change at account-deletion time ["remove this account will
affect this scheduled transaction ... what to do?"]
2: break out of SX since-last-run processing ["this account was removed;
{edit,delete} SX?"].
##################################################
### To-Do
###
### '.' = to-do, 'X' = done, '?' = jsled verify
###
##################################################
. Meta
. fulfill everything on http://linas.org/linux/gnucash/projects.html#alerts
. FreqSpec.c
. xaccFreqSpecGetFreqStr [display] needs to go away [?]
X create a template register
X store account and amount data in kvp_frames.
. find a way to list multiple registers for template transaction purposes.
. this is a "normal" general journal + a "stock" general journal
. warlord's business stuff may extend this to more ledgers...
. this is going to be: a tabbed notebook in which the tabs contain
the number of transactions the GL they hold contain.
. register macro-widget [src/register/ledger-core/gnc-regWidget.{h,c}]
. should support
. toolbar
. Close
. Enter
. Cancel
. Delete
. Duplicate
. Schedule
. Split
. Blank
. Jump
. Transfer
. Find
. Report
. Print
. popup menu
. elts
. Enter
. Cancel
. Delete
. Duplicate
. Schedule
. Split
. Blank
. Jump
. extended to support previously-menu-accessible options in embedded case
. status bar
. configurable UI elts [menu, toolbar, status]
. re-configurable UI elts
. menu: the register itself should provide a sub-menu for inclusion
into other menus [the window-register, for instance]
. toolbar: As seen above, certain toolbar elts are common, some are
appl.-specific.
. status: the status bar is sort-of a boolean option; applications
may wish to place the status bar in a more acceptable location.
. default callbacks
. override-able
. can "orverridable" mean "[gtk-style-]signal-based"?
. bitmask of supported functionality
. !"Schedule..." for the embedded-in-SX-editor case => gray-out
. shouldn't [necessarily] support
. date range [may be fixed/irrelevant by caller]
. style changes [caller may enforce]
. NOTES/ISSUES
. pass in prefix for gnc_reg_save_size(...)
? Hook into 'book data changed' save-on-exit decision
. GNCFrequency
. bugs
. Bi-weekly / Once
. Add dupe of start-date control[s]
. Precedent: monthly, yearly, &c.
. Bi-weekly, quarterly <= x < yearly
. Add example[s] -- perhaps wait for dense-calendar widget.
. yearly-only?
. if month > current month, choose previous year in start date?
. Add 'today' button for startDate?
X transitioning to a new tab doesn't correctly setup the agreement
between the startdate and the page elements.
X why does the accounts window go crazy when we change the FreqSpec parameters?
X probably component-manager related... yup; FreqSpec Malloc/Free
generates events, which cause GUI refreshes.
X Example calendar month change isn't handled correctly/doesn't refresh the
marks.
X fixed by removing any ability to change the example calendar.
X "Inappropriate FreqSpec type" on new-SX editing.
X "new; weekly: click on day, click off day: GLib-CRITICAL **: file gdate.c: line 1236 (g_date_to_struct_tm): assertion `g_date_valid (d)' failed."
. no longer reproducible
. SX list
. add a big calendar [gnome-pim? evo?] to SXaction List/overview
. tab order
X "** CRITICAL **: file dialog-scheduledxaction.c: line 570
(row_select_handler): assertion `event' failed." when key-navigating sx
list.
. SX editor
. tab order
. Can't click-out of the register
B 'ESC' while editing template register causes window to go away badly
B Can't reliably edit the split values of an added split to a from-trans
created transaction -- the values get nulled after split-change.
B Note that this doesn't hold true for just-created splits on a fresh
SX...
X attempting to create a Weekly SX with no days selected causes a segfault.
X the user should be prevented from doing this.
X composite SX shouldn't segfault when asked to getFreqSpecStr for this
X should use regWidget
X Size/space issues [?]
X auto-shrink on window create [the register is too wide, leading to too
much whitespace on the two top panels -- sometimes].
X Un-selecting "End Date" leaves calendar widget sensitive
X 'Cancel' button should auto-cancel ledger changes
. make-from-transaction
. bugs
. general: there's going to be all sorts of interaction issues like these
between these things [SX-from-trans, SX list, SX editor] that should be
handled.
B creating a SX from trans with the SX list open does not update the SX
list
X you can delete a freshly-from-trans'd SX from the list with the
from-trans dlg still open, then 'ok' the dlg to get a segfault.
X you can generally manipulate SXes into bad/weird states since both
dialogs are open.
X So since Advanced editing entails "Simple" editing, it should just
replace that window. Then, with some CM hookup between the List and
the Editor, all is well.
X 20020419 - Wilddev manages to create two SXes from one; the first is
okay, but the second is h0rk3d [deleting it causes segfault, though it
can be instantiated correctly].
X number-of-instances in 'simple' results in "Warning:
sxftd_advanced_clicked: something bad happened in sxftd_compute_sx"
. tab-order
. better frequency guess?
[ related... ]
. match existing transactions for long-time users
. based off template-transaction data, some big existing-transaction
scanning code.
X credit/debit pull-over issues
X need to remove '-' from printed credit value.
X pull accounts over.
X pull initial SX name from the Transaction name?
X need start-date on Make dialog
X [initially starts as the next occurrence after the created-from SX,
which may not be the Right Thing]
. need "since-last-run" UI for instanatiation.
. need nifty visual style for druid.
. use color-setting code in src/gnome-utils/druid-utils.[ch]
. support sorting in various clists
. tab-order
. variable-binding table:
. tab through variables -- if on last one: ( if something's unfilled,
tab back to there, else, tab back to clist:( if no more unfilled
entries, then tab down to back/next/cancel. ))
. Double-clicking on auto-create list should jump to transaction
. register of first split?
. Need some way to defer to-create SXes?
. need some configuration for constantly-running GnuCash users of when to
pop up the 'new scheduled transactions' dialog [option, time-of-day]
. fix first/last page issues.
. bugs
. tab-order on variable-entry window isn't always correct.
B initial "To-Create Transactions" varbinding table doesn't setup table correctly.
B correct "Back" button behavior in Druid paradigm
B created SXes are put in GL forever. :(
B But this is true of manually-created transactions, too ... is this
actually correct behavior?
B creating a bunch [FIXME:define "bunch"] of transactions takes too long
X with no progress indication.
B cancelling a bunch [FIXME:define "bunch"] of xactions takes too long
B no progress indication.
X twunder reports [2002.01.29] register growing a little bit at a time if
tab is hit to switch between register fields -- started with update on
1/21.
X I _bet_ this is fixed with magic gnc-regWidget sizing fix -- 2002.04.15
X "0" and "0.0" don't work for variable values?
X correct "Cancel" behavior in Druid
X reset SX state to before creation
X delete any created SXes.
X restore any obsolete-n-deleted SXes.
X variable expressions don't get re-eval'd [as formula]?
X need to do this only on tab-out of the field.
X need effective cancellation support
X Change from dialogs to druid
X/O create transactions
X numeric
X formula
X need variable fill-in UI...
X re-use gnome-sheet code for a variable-binding table? -- ended up
using GtkTable [for now?]
X variables should default to '0', and '0' should be acceptable.
X need way to expire/purge scheduled transactions which have no chance of
being created [outside their end date; once-scheduled and past].
X infrequent enough that a dialog should suffice.
X need 'reminders' of upcoming scheduled transactions during since-last-run
X Is it sufficient to look at the next instance of ea. transaction only?
I think not... we probably want to look out until the transaction is
outside the reminder range.
X Should deal with "nothing-to-do" better [not even show up in the worst
[read: no auto-notify/to-create/reminders] case].
X don't load/init/create the GUI if we're not about to use it.
X this is different between the auto-invoked since-last-run dialog [show
nothing] and the menu-invoked since-last-run [show a dialog to the user
stating there's nothing to do].
X double-clicking a reminder should [probably] move it up to the to-create
list.
X Easy UI way of moving through the SXes which need variable bindings.
[This presently is: click "Ok" and the next clist row which needs
bindings is selected.]
X any [horizontal] window size change height-grows the top/auto-create GL.
X always goes one date past the instantiation date.
X credit and debit seem reversed at instantiation time...
X this is fixed, but is the fix correct?
. register mods?
. to see upcoming xactions, modifying future balance?
. to note which are "recurring"
. the mozilla "reload" glyph is kinda neat...
. prolly should use existing PIM "recurring" glyphs
. Differently-colored "not-yet-created" entries for a configurable
time window?
. Context menus/sensitive toolbar button/menu item for creation of
not-yet-created transactions?
. The ability to turn a non-recurring transaction into a recurring one...
X [see from-trans section]
. inactive cells
X date
. recn?
. deal better with formulas in template transactions [real FormulaCell]
. actually do something with the result of the balancing computation
/ recognize purely numeric template transactions and balance at
template-creation time.
/ balance transaction with vars?
. GNCFrequency
. initial-settings synchronization [start date, optionmenus]
. only a couple left; which ones?
. backend support
. SQL
. others?
##################################################
### Done
### ... don't put stuff here ... just move it to the bottom of the
### appropriate list, above, and 'X' it -- jsled
##################################################
X add the ...GetFreqStr() code for the complex composite FreqSpecs
X fix the ...GetNextInstance() code
X XMLv2 I/O
X need policy for start-dates in GNCFrequency
X fix GetNextInstance and GetInstanceAfter, mostly for composite FreqSpecs
X also needs to deal with >28-mday values WRT last-occur date + multipliers
X Engine ...Init() functions should be private.
X would like "don't even tell me you instantiated it, just fscking do
it!" option for non-manual-conf SXes
---------------
Random Notes
. SX Creation...
. Creation occurs due to a variety of circumstances:
. A user opens a register with future transactions in it; they manually
force the creation of the [perhaps not immediately next [though this
seems a bit weird]] one.
. A user is reminded of something which hasn't come due, but will w/in a
configurable amount of time, and thus they pay/create it.
X GnuCash starts and hasn't been run in some length of time; the
transactions which have "come due" since the last run are available for
creation.
. Configuration options...
. Overall
X Size of template register window
. color of future register entries
. conrad's desires
X policy
X create for N days in advance
X show for N days in advance, create when come-due
X defaults
X create/show for 'N' days in advance
X remind me 'M' days in advance
X just create
X notify when created
X Per-SX
X just create/notify
X create/show
X lead-time
X reminder
X lead-time
. [NOTES] Dealing with SX state-changes
. Create-into-future vs. create-normal
. into-future -> normal : no change; the last_occur date will be
appropriate, and will catch up eventually [unless the have-been-created
transactions should go away]
. normal -> into-future : should create immed, or wait for user?
. into-future [t_0] -> into_future [t_1]
. frequency
. in presence of create-into-future?
. transaction
. in presence of create-into-future?
##################################################
### Bugs
##################################################
X General
X Date l10n.
. GNCFreqency
. Since-last-run
. SX-from-trans
##################################################
### Enhancements
##################################################
. SX name should be default value for template transaction description
. loan/repayment SX's
. integrate "Financial Calculator"
. auto-determine number of occurrences/end condition from liability
account amount.
. SX since-last-run should be able to sort by Date [conditional on the dialog
staying around].
. There probably wants to be a multi-month "example" View which the
GNCFrequency can work with.
. jalapeno/ben has some thoughts on this...
. Evolution calendar integ.
. Evolution To-Do list integ. [SX reminders]
========================================
Template Registers/Transactions
Template-option registers are used for users to enter the template
transaction to be created when the scheduled transaction comes due.
Most fields will be copied directly, but certain fields will need to
be modified upon instantiation, and the template version of these
transactions will need to contain the information necessary to do that
instiantion. For some fields, this will be a derivable quantity, and
for others the user will need to be prompted. This will show up
mostly for the amount of variable-amount transactions; perhaps the
amount is then derivable from some external source. These amounts
will then be represented by a variable, a function, or a formula
including both.
Examples...
Verizon bill: "108.83 +- x"
. x: tax amounts [user-input]
Power: "seasonal_util_gas( 'OAK_CA', '100 therms' ) + seasonal_util_elec( 'OAK_CA', '220 kwhrs' )"
. seasonal_util_gas( loc, amt ): regional/seasonal power price
. seasonal_util_elec( loc, amt ): regional/seasonal electricity price
Rent: 1900
Phone: "26"
Internet: "80 - 40 - 10" [3 splits]
Daily: "4 + 6 (+ 26)"
. 4: cigarettes
. 6: avg lunch
. (opt) 20: wine
Gas: "regional_auto_gas( 'BERK_CA', 'premium', 14 gal +- 2 )"
. regional_gas( loc, type, formula )
. loc: location
. type: subclass of gasoline
. formula: formula to use for user-query
TROA: "220.14"
User-input
When user input is required for scheduled transaction instantiation,
we should have some sort of simple, spreadsheet-like UI for the entry
and verification of values. This would allow the entry of all values
necessary for the formula to be calculated.
We also need a way to defer instantiation of a scheduled transaction
until the information can be obtained.
Example...
type | date | formula | variable | value | total
+---------------------------------------------------------------------------+
| PG&E | 2001.04.12 | lookup(x) + lookup| | | 184 |
|---------------------------------------------------------------------------|
| | | | x | 142 | |
|---------------------------------------------------------------------------|
| | | | y | 42 | |
|---------------------------------------------------------------------------|
| gas | 2001.03.01 | cost/gal * gal | | | |
|---------------------------------------------------------------------------|
| | | | cost/gal | 1.949 | 14.27 |
|---------------------------------------------------------------------------|
| | | | gal | 12.32 | |
|---------------------------------------------------------------------------|
| gas | 2001.03.12 | cost/gal * gal | | | |
|---------------------------------------------------------------------------|
| | | | cost/gal | 1.959 | 15.39 |
|---------------------------------------------------------------------------|
| | | | gal | 13.43 | |
+---------------------------------------------------------------------------+
** Of course, "cost/gal" is going to be interpreted as division; perhaps we
can a) not handle it or b) have a heuristic. :(
I believe this means we can use the existing gnc-sheet/register-style
thingy.
We probably want to defer the lookup-based stuff until
1.8/2.0/gnumatic-provided network backing for this.
Stocks/recurring share purchases can make use of this, as well. The
idea is then, probably, that the user will have a fixed amount with
which to buy as many shares as possible; the num-shares, then, is a
formula based on a lookup at the given time [the share price],
involving the function FLOOR.
It'd be nice if this formula could be either a simple infix syntax for
normal people, or a sexp for Schemers.
=================================================
Instantiation Notes
-------------------
<jsled> Wilddev, conrad: Something that came out of Aaron's mail [see my reply to -devel] that I'd like your comment on:
<jsled> How do you intend to use scheduled transactions?
<jsled> Do you intend to use it to create things have should be in there since you last ran GnuCash?
<jsled> Or, do you intend to use it to create future transactions [perhaps a weeks worth] before they occur?
<jsled> Or, just primarily the former, but use the fact that the future transaction will be in the register to remind you to pay things, &c.?
<conrad> Personally, I'd be looking at future transactions as a reminder thing. But then, I run gnucash every day.
<jsled> conrad: Do you re-invoke it every day, or leave it running?
<conrad> I can see other people wanting case 1 though.
<conrad> I leave it running.
<jsled> conrad: Interesting. You'd want some sort of "new-day" check/timer, then, to re-display the "create new transactions" dialog... or do you want to control it?
<jsled> the idea is that upon startup, if there are new transactions to create, the dialog will come up [configurable, but that should be the default].
<conrad> I think a further configurable sub-option should be "redisplay on change of day" (possibly with an "at time <blah> option?)")
<conrad> without that option, it will not do what I'm counting on it to do - remind my I'm supposed to pay my bills.
<jsled> Yup yup.
Summary...
conrad wants to use this to remind him to pay his bills. He runs GnuCash
continuously, and thus wants an option to "pop-up on day change [at time
HH:MM]". He's interested in seeing future transactions as well as what's
being created ATM.
--------------------
window-register notes:
. RegWindow *regWindowSimple (Account *account)
. RegWindow *regWindowAccGroup (Account *account)
. functionality should remain, probably in reg mwidget
. I now disagree; this should be the caller [for templates, especially]
. void gnc_register_raise (RegWindow *regData)
. probably should remain here; if the reg mwidget has knowledge of it's
containing window, then it can go there.
. void gnc_register_jump_to_split(RegWindow *regData, Split *split)
. void gnc_register_jump_to_split_amount(RegWindow *regData, Split *split)
. should be part of mwidget
. static void gnc_register_change_style (RegWindow *regData, SplitRegisterStyle style)
. static void gnc_register_style_(ledger|auto_ledger|journal|double_line)_cb (GtkWidget *w, gpointer data)
. mwidget [no]
. static void gnc_register_sort_(standard|date|date_entered|date_reconciled|num|amount|memo|desc)_cb(GtkWidget *w, gpointer data)
. static void gnc_register_sort (RegWindow *regData, sort_type_t sort_code)
. mwidget? -- actually seems like container's responsibility.
. then, need some way to get the ledger->query for manip.
. some of these may not make sense in embedded applications
. static time_t gnc_register_(min|max)_day_time(time_t time_val)
. eh? This should probably be a util function somewhere
. static void gnc_date_range_set_sensitivities(RegWindow *regData)
. static void gnc_register_set_date_range(RegWindow *regData)
. static void gnc_register_date_cb(GtkWidget *widget, gpointer data)
. static void show_all_cb(GtkWidget *widget, gpointer data)
. static void gnc_register_today_cb(GtkWidget *widget, gpointer data)
. static void gnc_register_date_toggle_cb(GtkToggleButton *toggle, gpointer data)
. static void gnc_register_date_changed_cb(GtkWidget *widget, gpointer data)
. static void gnc_register_show_date_window(RegWindow *regData)
. static RegDateWindow *gnc_register_date_window (RegWindow *regData, gboolean show_all)
. need DateWindow policy/decision.
. decision: caller's responsibility.
. static GtkWidget *gnc_register_create_tool_bar (RegWindow *regData)
. mwidget
. should use passed-in toolbar, with clear contract about how the caller
should add/manip the [modified] toolbar provided.
. static void gnc_ui_find_transactions_cb (GtkWidget *widget, gpointer data)
. necessary for embedded applications? [nope]
. static GtkWidget *add_summary_label (GtkWidget *summarybar, const char *label_str)
. mwidget [option]
. eh?
. static GtkWidget *gnc_register_create_summary_bar (RegWindow *regData)
. static GtkWidget *gnc_register_create_status_bar (RegWindow *regData)
. mwidget [options]
. void gnc_register_jump_to_blank (RegWindow *regData)
. helper for various callbacks
. mwidget
. static void expand_trans_check_cb (GtkWidget *widget, gpointer data)
. static void new_trans_cb (GtkWidget *widget, gpointer data)
. static void jump_cb(GtkWidget *widget, gpointer data)
. static GtkWidget *gnc_register_create_menu_bar(RegWindow *regData, GtkWidget *statusbar)
. mwidget
. should take menubar as param
. static GtkWidget *gnc_register_create_popup_menu (RegWindow *regData)
. mwidget
. should take popup as param
. static void gnc_register_destroy_cb(GtkWidget *widget, gpointer data)
. needs to integrate more nicely
. RegWindow *regWindowLedger (GNCLedgerDisplay *ledger)
. Creates the ledger :)
. Sets up the data struct :)
. Creates a gtk_window_new :(
. Creates a gnc_register_date_window :I
. Creates the statusbar, toolbar, popup, menubar :/
. recalls saved window_size from prefix [param]
. static gnc_numeric gnc_account_present_balance (Account *account)
. static GNCPrice *account_latest_price (Account *account)
. mwidget? [nope ... in fact, not even in window-register]
. static void startRecnCB(GtkWidget * w, gpointer data)
. recn: configurable behavior
. static gboolean gnc_register_include_date(RegWindow *regData, time_t date)
. date-range stuff.
. static gboolean trans_has_reconciled_splits (Transaction *trans)
. util
. static DeleteType gnc_transaction_delete_query (GtkWindow *parent, Transaction *trans)
. default is probably good; mwidget
. ideally have way to customize text
. static void gnc_register_check_close(RegWindow *regData)
. should be mwidget util fn
. static void report_helper (RegWindow *regData, SCM func, Query *query)
. mwidget util

View File

@ -1,33 +0,0 @@
bust this file up into several. Its *way* too big to deal with.
create common funcs for repeated "types" of parsers. i.e. a common
func for handling guid, gnc_numeric, etc. parsers - just pass in
string->data and data->string funcs.
change sixtp_child_result to sixtp_result?
add generic accumulate chars node constructor - takes end_handler
as argument - same as for timespec parser...
document that right now parsing is *extremely* anal - no whitespace
surrounding data.
need to add a way to propagate error data upward...
do we need a way to pass an object up through the tree along with
its lower level destructor?
CHECK TO SEE IF WE ALWAYS DTRT IN THE END TAG HANDLER - IE DO WE
CLEANUP PROPERLY SINCE AT THAT POINT THE FRAME CLEANUP HANDLER WILL
**NOT** BE CALLED.
CHECK TO SEE THAT WE'RE SETTING SHOULD CLEANUP TO FALSE EVERYWHERE
WE SHOULD (i.e. when we use the result)!
DAMN, why didn't I think of this before. I should have added a
parent "after-child" hook. I think that might have greatly
simplified some of the nodes...
Do we also want "before/after" chars handlers?

View File

@ -1,38 +0,0 @@
/** \page backuppolicy Backup Design
API: \ref Backend
Currently, backups and log files are automatically stored by the engine
with date/time stamps every time the user hits 'save' in the gui.
(The actual file writing is done by xaccWriteAccountGroupFile() in
in src/engine/FileIOP.h)
\section backupchanges Proposed design changes:
-# Allow user to configure which directory backups should be put into.
(currently, this is same as current directory). Requires changes to
engine FileIOP.h as well as GUI.\n
One possible default is ~/.gnucash/data/ (Which is supposed to
be the place where files are saved if no directory is specified.!?)
-# Prompt the user to make a backup every third save. Make this number
configurable. If no default backup path set, prompt to set it,
with suggested path being ~/.gnucash/backups/
-# If save format was XML text, then could use RCS ...
Alternately,
For those that don't know, xdelta is like RCS, but it's designed to
handle any kind of data, including binary, is supposed to work really
well, and transparently handles gzipped data with some form of MD5sum
verification. It's also available in library form. Like RCS it would
give us the ability to do cool things like snapshot the data every so
often for nearly no cost. Want to see what things looked like 6
months ago? Just enter the right date into the "time-warp" dialog :>\n
For those on Debian systems, just install the xdelta and
libxdelta2-dev packages. Others can get the source from
ftp://www.xcf.berkeley.edu/pub/xdelta/, or just go to
ftp.debian.org:/pub/debian/dists/unstable/main/source/utils/xdelta*.tar.gz
-# Could monitor how many changes (records altered) the user has made,
and could prompt for more frequent saves if lots of editing has
occurred...
*/

View File

@ -1,427 +0,0 @@
/** \page bookperiods Books / Accounting Periods
API: \ref Book\n
\section periodsintro Implementation Overview
Linas Vepstas <linas@linas.org> December 2001
Last Updated August 2003
A top, unimplemented request for GnuCash is the ability to 'close
the books', that is, to add support for 'accounting periods'.
Partial support for books has been added to the GnuCash engine;
and a GUI is partially finished. This file reviews the
implementation design choices and the current design status.
\subsection periodsdefines Definition
An accounting period or 'book' is a set of accounts and transactions
that, once closed, must never be modified again. Books are typically
closed once a quarter, or once a year. Generating a report from a
closed book tells you how well you did for that year (or quarter).
The provision against modifying a closed book helps ensure correctness,
and discourages cheating. Note that the closing balances of a closed
book must be carried forward as the opening balance in the next book.
(But only for asset, liability and equity accounts. Opening balances
are zeroed for income and expense accounts.)
Note that the correct handling of depreciation, capital gains and
other similar accounting concepts requires 'Lots' to be correctly
handled. Lots are a way of identifying that an item bought in one
transaction is the same as that sold in another transaction.
When a book is closed, the entire lot must be brought forward,
and not just the account balance, because depreciation, capital
gains, taxes, etc. depend on the dates of the originating
transaction. See 'lots.txt' for details.
API: \ref Lot
\subsection periodsrequired Requirements
Must have good performance (large data files usually mean poor performance).
Use the idea of 'books' to prevent file bloat. Must have access to
historical data. Must be able to create bar-charts, graphs, reports
of multi-year data (i.e. create reports spanning multiple books).
\ref Period
\subsection periodsstatus Status
The top-level structure that holds references to all of the data in
a book is implemented in src/engine/qofbook.c. The routines to
split one book into two, automatically setting account balances,
etc. are implemented in src/engine/Period.c. The actual
implementation used is "Plan A" from the list of choices
below. The actual implementation is not yet complete, see
"Implementation Notes" at bottom for the current status.
\section periodssolution Possible Solutions
API: \ref Query
Listed in order from worst to best:
\subsection periodsdelete Plan F:
Simply 'delete' old transactions, and adjust the equity to make up for
this. More specifically: Split one file into two, with only 'old'
transactions in one, and only 'new' transactions in the other.
I believe that this can be 'easily' coded by creating a second instance
of a qofbook structure in memory, copying all the account info
into it, and using Query.c to copy in only the 'old' transactions.
(and v.v. using Query.c to delete the old transactions in the other copy.)
Then, look up the ending balance on all asset/liability accounts
in the 'old' book, and create new transactions in the 'new' book
that transfers that balance amount to an equity account.
The transfer description is, of course, 'opening balance'.
Balances of income/expense accounts are zeroed out.
I believe this code would be easy to write in C or scheme. There may be
a few bugs/difficulties lurking in qofbook that might trip things up.
Also, at a minimum, there needs to be a GUI dialog, asking for the
date on which to close the books.
(A fancy but optional GUI dialog/wizard might ask 'which equity
account to transfer the opening balances, and what the description
should say. This GUI is optional, since, after all, these can be
tweaked by hand, and its only done once a year or once a quarter.)
(An even fancier GUI would remember how often the books should close:
1,2,3,4 times a year, 12 times a year, whatever, and 'remind' you
when that happens.)
(Another 'fancy' feature might be to not allow user to close book until
all 'old' transactions have been cleared/reconciled. But that might be
a bit much for non-bank accounts).
API: \ref Transaction
\subsection periodsf Pros & Cons of plan F:
- pro: simple. The simplest option.
- pro: truncated file loads much faster
- pro: old/irrelevant accounts can be safely deleted from newest file
(while still being preserved in old files).
- con: impossible to generate 5 year reports, multi-year graphs. This
would really hurt, esp, when tracking stocks/mutual funds/retirement
accounts over a number of years.
I think this last one is the Achilles heel, the torpedo in the rudder
that sinks the boat.
\subsection periodspland Plan D
As above, but instead of deleting, add a kvp to each transaction stating
'/book/closed-on=12.31.2000'. Then modify the default query for the
registers so that the only displayed transactions are those that are *not*
part of a closed book. Modify the Query GUI dialog to add 'book' as
a query parameter.
- pro: easy access to historical record
- con: slow loads; file size not reduced.
- con: dealing with opening balances, equity, is icky.
- con: can't delete/hide old/stale accounts.
We move on....
\subsection periodsplanc Plan C
As in plan F, but instead of creating two books, clone the account tree
into two: 'old' and 'new'. The old and new accounts are identical,
except that they get different guid's. Every account in the old
tree gets a kvp in it: '/book/closed-on=12.31.2000'. We don't copy
or delete any transactions; instead, we reclassify them: Old transactions
are transfers between old accounts, new transactions are transfers
between new accounts.
The account summary needs to be modified to show only 'new' accounts
by default. The transfer-from pop-down needs to be modified to show
only 'new' accounts only, and never the old accounts.
Transfers between closed and open accounts are never allowed (this is
validated/forced in the engine). Opening balances are handled just as
in plan 'F'. User can only view data in closed books, and not change
it.
If we allow books to be re-opened, then the 'starting balance' equity
transfers must be deleted. We can save 're-opening' for some future
day.
The 'starting balance equity transfers' must have a kvp pair in them:
'/book/closing-balance-of-account-guid=0xdeadbeef'.
This way, we know that this transaction is associated with the closure
of the book on some specific account, and that way, we can find this
transaction someday in the future, if we ever need to.
Each new account needs to point back at the copy that is its 'old' self.
(these don't have to be C pointers, they could be some suitably clever
kvp: '/book/previous-guid=0xdeadbeef') This continuity is needed in order
to be able to create reports that scan over multiple books. The Query.c
interface needs to be modified so that it searches only new accounts,
or it searches new accounts *and* their corresponding 'old' copies.
(There are three ways to deal with this account continuity issue:
- don't deal with it in query.c: force various GUI dialogs to explicitly
formulate queries involving the /book/previous-guid string.
but this gets messy in the GUI's. May lead to excess cut-n-paste
of similar code between different GUI's.
- 'hide' the distinction between 'old' and 'new' in query.c:
the users of query.c need only to specify a boolean flag: search
closed books: yes/no. However, this is conceptually ugly, and
prevents query from doing low-level queries on specific
books.
- create query utility wrapper/pre-processor that takes a query,
and then modifies it to search through closed books as well.
This is the 'cleanest' solution. ??
- All these are delicate, and need a little more thought and
exploration. Goal is to simplify queries, not burden the system
with cryptic, complex code.
)
I believe that if we can deal with the account-continuity issue in query.c
or in a wrapper thereto, that there are no remaining issues with
reporting. i.e., for any given report, we are either reporting
data in closed books, or not. Different reports should have different
defaults. e.g. income/expense pie chart never looks at old books.
asset-value-over-time-bar-chart always looks at closed books.
- pro: safer than plan F, since we really can enforce the 'you aren't
allowed to edit closed books' rule.
- pro: solves the old-account/new-account problem, since new accounts
can be edited/deleted without damaging old account.
- pro: solves the historical reporting problem.
- con: queries are potentially slow, loading of file is potentially slow.
But now we have enough info to propose the final solution:
\subsection periodsplana Plan A:
The kvp markup of plan C coupled to the multi-file solution of plan F.
In initial startup of GnuCash, only the 'current' book is loaded.
If user asks for a report that requires data from old books, then
we have to pause to load one or more of the older books.
If the books are stored as separate files, then the 'current' book
needs to somehow know the filenames of the old books. I recommend
against storing the books as different sections of one file, for
many reasons:
- risk of corruption of old books
- bloated file size
- the single-file solution would need to invent a 'directory' so
that the location of the old books in the file can be quickly
found and lseek()'ed or mmap()'ed. But why invent a directory?
Unix already provides directories!
I recommend that every book get a unique guid. The current book
would know the guid's if its closed book progeny. The filename
would incorporate some compressed version of the guid (and/or
the date of closure).
Optional:
every book gets not only a unique guid, and also stores some
meta-information (as book-level kvp's):
/book/title=some-user-supplied-name\n
/book/notes=user-supplied-descriptive-comments\n
/book/start-date=xxx\n
/book/end-date=xxx\n
/book/previous-book-guids=(list 0xa 0xb 0xc)\n
/book/accounting-period=enum {none, week, month, quarter, trimester, year}
\subsection periodsaprocon Pro's & Con's
I am not aware of any con's to plan A at this point.
\section periodsoverview Implementation Overview
Plan A has been implemented in the engine. To quickly summarize:
- Partitioning involves splitting one book into two, called the
"old, closing book", and the "current open book".
- Accounts are copied between old and new books. One of the copies
is issued new GUID's, but the rest of the account data is copied.
KVP pairs are then added so that each copy points at the other,
and can thus be easily found. The "gemini" KVP keyword is used.
The opening balance is zeroed for income accounts. A transaction
is created to set the correct opening balance on asset accounts.
The transaction is a transfer from equity. An equity account is
created automagically, if needed.
- Transactions. Transactions are partitioned, and end up either
in the old or the new book. Splits move with transactions.
Note that some transactions, associated with open lots, may be
kept in the new book (See below).
- Lots. If a transaction has a split in an open lot, then that
transaction is not moved to the closed book. It needs to stay
with the open book. If a lot is closed, and all of the other
lots associated with all of the transactions in this lot are
also closed, then the lot may be moved to the closed book
(and all of the other associated lots must then also be moved).
- Prices. Prices are sorted into the new and old books according
to the date on the price.
- Scheduled transactions/recurring transactions. These are left
in the new book, untouched. They are not copied into the old
book, and no trace of their existence is left in the old book.
- Business Objects. Not implemented.
\section periodsnotes Implementation Notes
- src/engine/Period.[ch]
Implements the main logic to split one book into two, and populate
it with the appropriate keys, markup, etc. and to carry balances
forward, etc.
- src/engine/gnc-lot.[ch]
Implements accounting Lots.
- src/engine/Scrub2.[ch]
Implements simple FIFO for lots. Data is scrubbed with respect to
this FIFO before the books are closed. Commodity accounts (e.g.
stock accounts) must have a coherent Lots structure before books
can be closed. The scrubber makes sure there's nothing hanging
out.
- src/gnome/druid-acct-period.[ch]
Implements a druid interface to allow user to specify book closing
dates, add a title and notes to a book, and walk through the process.
Uses FreqSpec.[ch] and the widget in gnc-frequency.[ch] to allow
the user to specify the frequency of book closings.
- The XML-file backend can store multiple books in one file. There
is currently minimal support for writing out multiple books,
one per file (this enables faster load, by not loading old books).
There is currently no support for loading multiple books from multiple
files.
- (Details about the dbi backend are missing.)
\section periodsannounce ANNOUNCE: Book Closing Beta 2
Books AKA Accounting Periods can now be closed by going to the 'Action'
menu on the main window, and selecting 'close books'. This will popup
a druid that will allow you to select closing dates. Books are closed
one at a time: after each one, you can go back and alter the close date.
A book is 'closed' by moving transactions and prices earlier than the
indicated date to a separate file.
As a side-effect of book closing, capital gains (losses) will be
automatically computed using a FIFO accounting method. Stocks
or other non-cash assets that haven't been sold will remain in the
currently open book, even if the purchasing transactions were made
a long time ago.
The biggest drawback to the automatic computation of the gains/losses
is that there is no GUI to specify alternate accounting methods
(e.g. LIFO, or hand-picked lots, etc.) There is basically no practical
way to 'undo' the results of the gain/loss computations.
The other main drawback to book closing is that this will prevent
multi-year (multi-period) reports & graphs from being generated.
The old data will be in separate files, and there is currently no
way to load several files at once.
\section periodsissues Open Issues/Questions that Need Discussion:
- How to handle business objects? e.g. vendors, customers should be
copied into both old and new books. But invoices should be in one
or the other. Need to document which is which.
Copy:
customer -- ok, has guid, has for-each
employee\n
No-op:
address -- do nothing
- Discussion Q: What should the naming convention be for the different
books? When the XML file backend is used, different books need to be
stored as different files (in order to avoid the performance
penalty of a large file load). Currently, what's implemented is\n
book-1dc750aa3e6fd045c13ac8afb1a9ac03-my-gnucash-file.xac.gml\n
where the number is the GUID of the closed book (needed to be able to
quickly find the book/file) and 'my-gnucash-file.xac' is the name of
the original file whose books were closed.\n
Need to change the name to include the word "archive".
- Discussion Q: When saving books, make the book title part of the
book name (user convenience).
- Should closed books be allowed to have unreconciled transactions?
Answer: probably. Should there be a warning?
\section periodstodo Open Issues / ToDo
- Change GUI to allow user to specify a default equity account
for dealing with opening balances. Should be done with kvp markup.
- Fix crash when exiting gnucash after closing books.
- The filename of the old, closed books should probably be saved
in the KVP tree of the current open book. This need be done only
from the file backend.
- Need to mark closed book as unalterable, and respect that markup.
I think there's a 'closed' flag in the book, but I don't think its
respected.
- The book closing GUI (druid-acct-period.c) needs to save/restore
period end date (the FreqSpec) to KVP on open book. This would be
easy once we have a freq-spec-to-kvp and freq-spec-from-kvp routines.
- Handling of lots in book closing is implemented but is poorly tested.
Need to write test cases. Also test cases for prices in book
closing.
- price-saving in the SQL backend is probably broken, its certainly
untested. Need to remove old deprecated price-lookup mechanism,
and replace w/ qofquery.
- Need to provide for loading of closed books, because this is needed
for reports.
- Handling of multi-book reports ??? Need to work out the recommended way
of making this happen....
- Have some way of remembering the quickfill text from older books.
- Possibly neat idea:
Book closing, as currently implemented in the GUI, is driven entirely
by the date-posted. There is no (planned) interface to allow you to
exclude some certain transactions from a particular closing (although
it would be 'easy' to add this: right before I close a book, I have a
list of transactions which can be added to/removed from).
- add 13-period support to FreqSpec and the FreqSpec widget.
e.g. from the mailing list:
One of the calendars my company uses is like this:
13 periods
1st period begins jan 1st, partial first week plus 4 weeks.
2nd - 13th period begins on a sunday every four weeks.
13th period - 4th week may be less than full week because it ends on 12/31.\n
For 2003:\n
01. 01/01 - 02/01\n
02. 02/02 - 03/01\n
03. 03/02 - 03/29\n
04. 03/30 - 04/26\n
05. 04/27 - 05/24\n
06. 05/25 - 06/21\n
07. 06/22 - 07/19\n
08. 07/20 - 08/16\n
09. 08/17 - 09/13\n
10. 09/14 - 10/11\n
11. 10/12 - 11/08\n
12. 11/09 - 12/06\n
13. 12/07 - 12/31\n
*/
=========================== end of file ========================

View File

@ -1,225 +0,0 @@
/** \page budgetplan Some Thoughts about GnuCash Budgeting
API: \ref Budget
Bob Drzyzgula
18-April-1998
\section budgetabstract Abstract
At this point, this document contains my personal thoughts about possible
design criteria for a budgeting engine in GnuCash. These should not
at this writing be taken as consensus opinion, and may in places be
at odds with conventions inside GnuCash code (and with general accounting
principals... I am in no way an accountant), and thus may not be practical.
However, I believe that they provide a self-consistent view of how
one might do this, and I hope that this document will serve to continue
the discussion that began on the GnuCash/Xacc mailing list.
\section bugettoc tableofcontents
\subsection budgetdefines Definitions
As with any design paper, we'll need a few definitions. I'll try to
stick as close to possible to the Xacc usage of these terms, but I'm
not intimately familiar with the code, so I may have made some errors
here.
- Journal A journal is a simply a list of transactions with minimal
characterization. For the purposes of this paper, the journal is
defined to include only transactions that have already occurred,
i.e., expected or up-coming expenses would not appear in the journal.
- Calendar For the purposes of this paper, the calendar as a list of
fully-defined future transactions, organized by date. A transaction
would only appear in the calendar if there was a low likelihood
that it would change. Future transactions that would only change
by surprise (e.g. the cable TV bill) could appear in the calendar,
but utility bills such as from the natural gas company would appear
in the calendar only after receipt.
- Template A template is in effect a partially defined transaction,
possibly containing constraints. For example, one might have a template
that would identify the price, payee, description, asset account
and expense account (but not the date) for buying a Value Meal #4
at the corner McDonald's, so every time you get the Value Meal #4
you could pull it out of a GUI pick list and just specify the date.
Alternatively, one could have a template that specified much of
the data for the natural gas bill but not the amount, so that (a)
entering the transaction when the bill came could be simplified,
and (b) the partial information could be recorded, in effect as
a reminder. A template could include such information as a confidence
interval, so that, for example, if you and your family go out to
dinner every Friday night and it usually costs $20-50, you could
create a template that had $35 +/- $15 as the amount. Such templates
could be extremely useful in making projections. Quicken, of course,
has similar things called ``memorized transactions,'' but Quicken
gives less control over their creation, meaning and use.
- Schedule The schedule is a supplement to the calendar that contains
only dated references to templates, which could be further narrowed
as part of the reference, e.g. an undated template could be given
a date but not a firm value when referenced from the schedule.
- Ledger The ledger is in effect documentation of the journal, in that
it describes the meaning of the transactions with respect to the
balances in the various accounts. In Xacc, this appears also to
be known as the register. It isn't clear to me that Xacc maintains
the journal and the ledger separately. The ledger could easily be
expanded to include documentation of the calendar transactions,
but it is less clear that one would want to include the template
references from the schedule directly in the ledger; it may make
more sense for the schedule to be a ledger unto itself.
- Budget A budget is an allocation of monetary flows. As funds enter
the system through the income accounts, they must be transferred
to other accounts; a direct deposit would be a transfer to an asset
account, a loan payment through payroll deduction a transfer to
a liability account, and tax withholding a transfer to an expense
account. Of course, secondary transfers - check payments to credit
card accounts, for example - are expected. The budget must cover
a certain time period; one year is typical but not necessary. Typically
one begins with the expected income over the budget period and describes
what is expected to become of the money. In addition, it is typically
the case that one will begin a budget period with initial assets
and liabilities, that assets may be transferred to expense and liability
accounts, and that new liabilities may be created as a way to obtain
additional assets or cover expenses. It is not necessary and is
in fact (in my view) undesirable for the budget to make specific
reference to any transactions or templates; it is not even necessary
to describe the precise path of the funds through accounts. Thus,
while the budget documents one's goals for where the funds wind
up, the schedule, calendar, journal and ledger describe the actual
mechanics of the process. Finally, it should be noted that, in addition
to describing the endpoints of the budget period, one typically
will set a certain checkpoint frequency in the budget so that (a)
the time dependence of the various flows is more obvious, and (b)
one can conduct periodic verification of the accounts' status with
respect to the budget. Most often this checkpoint frequency is either
monthly or per-four-weeks. The former might be referred to as ``budgeting
on a monthly basis.''
\subsection budgetdocs Documenting the Budget
One possible way to document a budget might be as a classic ``input-output
table''. Consider the following table:
\verbatim
+---------+----------+---------+-----+------+------+-----+------+------+
| | Checking | Savings | MMA | Cash | Visa | Tax | Food | Rent |
+---------+----------+---------+-----+------+------+-----+------+------+
+---------+----------+---------+-----+------+------+-----+------+------+
|Checking | x | 3 | 2 | 7 | 3 | | | 5 |
+---------+----------+---------+-----+------+------+-----+------+------+
|Savings | | x | 1 | | | | | |
+---------+----------+---------+-----+------+------+-----+------+------+
| MMA | | | x | | | | | |
+---------+----------+---------+-----+------+------+-----+------+------+
| Cash | | | | x | | | 6 | |
+---------+----------+---------+-----+------+------+-----+------+------+
| Visa | | | | 8 | x | | 7 | |
+---------+----------+---------+-----+------+------+-----+------+------+
|Paycheck | 20 | | | | | 5 | | |
+---------+----------+---------+-----+------+------+-----+------+------+
|Interest | | 2 | 3 | | | | | |
+---------+----------+---------+-----+------+------+-----+------+------+
\endverbatim
The first five data columns and the first five data rows have the same
names. These are the asset and liability accounts. The last three
columns are the expense accounts, and the last two rows are the income
accounts (When I learn a little more SGML I'll try to make the table
a little more readable). Notice:
- If you sum across the income rows, you obtain the total income for
each account: $25 from paychecks and $5 from interest, for a total
of $30. If you sum down the expense rows, you obtain the total expenses
for each account: $5 for taxes, $13 for food, and $5 for rent (OK,
so we eat a lot). Just looking at these two figures, we can immediately
see that we expect to make $30 and spend $23 of it.
- The sense of each amount is positive from the row account to the
column account. Thus, $20 of pay is direct-deposited to the checking
account, and the remaining $5 is withheld for taxes. $1 is transferred
from the savings account to the money market account. We plan to
use the Visa card to buy $7 worth of food and to take a $8 cash
advance. We also plan to pay Visa bills totalling $3 from the checking
account.
- If you sum down an asset/liability column, you will obtain the total
amount we expect to add to that account (e.g. $6 added to the MMA,
$20 added to checking, $3 to Visa). If you sum across an asset/liability
row, you will obtain the total amount we expect to remove from that
account (e.g. none from the MMA, $20 from checking, $15 from Visa).
Thus, if you subtract the row sum from the column sum for a single
asset or liability account, you may obtain the planned net change
in that account for the budget period. Thus, we expect checking
to be a wash, the MMA to grow by $6, and to go $12 further in the
hole on our Visa card.
- Again, what is documented here is the planned account-to-account
flow across the entire period, not individual transactions.
\subsection budgetcontrib Contributing Data
(to be done)
================================================================
Where I'm headed for the rest of it is this:
- I expect to point out that the Journal, Calendar and
Ledger as I have described them are only tangentially
related to the budget. They are the empirical data and
the Budget and the Schedule are the models. The goal
would be to have an engine that would allow one to
measure the deviation of the empirical data from
the model in various ways.
- I expect to talk about the task of generating both
the schedule and the budget. When one prepares this
stuff, one usually has a rather diverse collection of
data to work with. Bi-weekly paychecks, monthly
interest income, quarterly dividends, five-day-per-week
lunch charges, etc. What I would very much like to do
is describe a mechanism whereby one could simply enter
all these kinds of data into the engine, and it will
digest it all into the budget and/or schedule formats.
I expect to do this by preparing projected transactions
as "templates", and then specifying a time series of
instantiations of the templates.
- I expect to describe a design for a sort of OO
time series engine, where "time series" is a class.
Instances of "time series" will have begin dates,
end dates, frequencies, and the data series itself.
Time series arithmetic will be defined, and these may
entail frequency conversions to force the operand series
to commensurate frequencies before combination. Thus,
explicit conversion functions, say "monthly_to_daily"
will need to be defined.
- Once these pieces are in place, then one should be
able to use the time series engine to digest the
scraps of paper with scribbles saying "Katie's lunch,
$2.30 every Monday through Thursday except only
$0.40 on Friday because they have burritos on
Friday and she hates them and brings her lunch but
still needs milk" into something usable as a
budget -or- as a schedule (these being two separate
outputs).
- While I expect that such an engine would be extremely
useful for about 80% of the data that would go into
a budget, there will of course be other data for which
this would be overkill or cumbersome. Like "$85 each
February and October for spraying the hemlocks with
dormant oil". I can't imagine that anyone would rather
make up some bogus time series for this than to open
up a spreadsheet and type in two numbers, or even
add a couple of records to an input data file. Thus, there
should be some mechanism for this, where hand-entered
data can be merged into the final budget or schedule.
it should not, however, be implemented as hand edits to the
draft table coming out of the time series engine,
because one will want to be able to iterate on this.
- Nonetheless, it probably remains true that users
would wish to take the final budget output of all this
automated stuff, and hack it up into something
that somehow pleases them better. Thus it probably
*does* make sense to allow hand edits at the final
stage, and/or to simply enter an entire budget by
hand if that is what you want to do.
- So far, I don't see any simple way to implement
something like Quicken's SuperCategories. Maybe this
is related to why it works so poorly in Quicken. :-)
*/

View File

@ -1,98 +0,0 @@
/** \page financeconstraints Financial Constraints in GnuCash
Linas Vepstas <linas@linas.org>
September 2003
\section financeoverview Overview:
The GnuCash Engine implements a set of financial constraints so
that a set of basic/core accounting rules are obeyed. The best
known example is the "double-entry" constraint: the total value
of a transaction must always be zero. A more mundane example
is that cap gains are recorded on the date that they occur: or,
more plainly: the posted date on the transaction that records
cap gains is the same as the posted date of the transaction that
caused the gains. At this time, these constraints are
implemented in an ad-hoc manner. The goal of this document is
to list and document as many of these constraints as possible,
and to review the framework in which they operate. A possible
future direction is to formalize the framework, so that it becomes
easier to add and work with new types of constraints.
\section financeintro Introduction:
There are three very different classes of constraints within GnuCash,
which should not be confused with each other. They work in very
different ways and have very different goals. First, there are
the "GUI Constraints", which are implemented as events: they make
sure that the the GUI displays the data in the engine as it currently
stands. Next are the "Multi-User Constraints", which are implemented
in the Postgres SQL backend: They make sure that as one user alters
data, that it is reflected in what the other users see. Finally,
there are the "Financial Constraints", implemented in the engine,
that make sure that the financial data recorded in the engine meets
a set of core and extended accounting rules. This document deals
primarily with this third class.
Note that some financial constraints are so core, so key to GnuCash
that they are woven into the object design itself. For example, the
posted date is a part of the transaction: different splits cannot
possibly have different posted dates, as there is no mechanism to
represent this. All splits get their posted date from their parent
transaction.
The constraints that we are most interested in are the ones that
are implemented as 'triggers' or 'scrubbers': these are not reflected
in the core structure, but are rather implemented as routines that
run at specific times and alter the data to be self-consistent in
certain ways. The 'double-entry' constraint belongs to this class:
it computes the total value of all the splits in a transaction, and
adds one, if needed, to bring the total to zero. This constraint
runs when the transaction is committed. Although this is an important
constraint, there is no (easy) way to reflect it directly in the
object design; thus, it acts as a rule that must be periodically
imposed.
At this time, the financial constraints within gnucash are impelmented
in an ad-hoc manner, with no governing framework. This may change,
as there is pressure to support more complex constraints that vary
by region/country, by account type, by industry, etc.
\section financelazy Why Not 'Lazy Evaluation'?
Lazy evaluation is superficially like constraints, but differs in an
important way. With lazy evaluation, when something changes (e.g.
the posted date) it is marked dirty. Later, when something else needs
something (e.g. the posted date on a gains split), the dirty flag
is examined, and, if dirty, the new/corrected value is computed and
returned.
Simple/ad-hoc lazy evaluation works well when data dependencies are
simple, but it breaks down when there are too many/circular
relationships. It becomes all too easy to get trapped in infinite
loops of corrections. The goal of moving to a formal constraint
system is to introduce specific, well-defined sync points where
constraint checking can be done, without incuring circular
deopendencies. At this time, the sync point is the xaccTransCommitEdit()
subroutine.
\section financelist List of Constraints
The following is a list of the constraints that are currently
implemented in the GnuCash Engine, with a short description of what
they are, and how they work.
- Double Entry
- Double-Balance
- Date Posted of Gains Transaction
The posted date of the gains transaction is kept in sync with the
posted date on the transaction that is the source of the gains.
See the document 'lots.txt', section 'Cap Gains Actual Implementation'
for details.
- Value of Gains Transaction
The value recorded by the gains transaction is kept in sync with
the value
*/

View File

@ -1,58 +0,0 @@
/** \page currencies Currency Issues
API: \ref Commodity
From Bill Gribble <grib@billgribble.com>
Tue, 3 Oct 2000 11:09:54 -0500
We need to fix a single way of dealing with this that
addresses all of the concerns. Maybe we should list the
problems/requirements to make sure we are talking about the same
thing. I know I've repeated several times that I believe the
"eliminate Currency accounts" problem-set is separable from the
"global A=L+E" problem-set; I'll list them all together here, because
I think it's just a "feature" of some particular solutions that they
are separable.
- we want to eliminate the need for currency trading accounts. From
a user interaction perspective, this means we need to allow
transfers directly between accounts denominated in different
commodities.
- we want transactions to have clear and unambiguous balancing
semantics.
- we want to store the actual amounts of commodities involved
transactions rather than price and quantity.
- we want to be able to globally check and display the terms of the
accounting equation (and all account balances) in a
user-selectable functional currency.
I think the following bits will address the first three issues above.
Basically I'm just agreeing with your last suggestion, Dave; Rob and I
hammered on it on a white board and weren't able to poke any holes.
- Eliminate the 'currency' from the Account structure. Add a
'currency' to the Transaction structure. Each transaction's
'currency' is by definition the balancing common currency for the
splits in that transaction.
- Eliminate the 'share price' field from the Split structure and
replace it with a 'value' field. The 'value' is a translation of
the Split's 'damount' (which is the amount of the Account's
security involved) into the Transaction's balancing currency.
The balancing semantics of this approach are unambiguous, no existing
balanced gnucash transactions would be disallowed (the transaction's
common currency just gets saved in a pointer) and the fuzzy
distinction between the account's currency, security, damount, value
is cleared up.
About the last point, the global accounting equation. Evaluating this
equation requires the computation of current asset values and
unrealized gains/losses. I believe this is possible in a
straightforward way using the reporting framework, a user-selectable
functional currency, accepted accounting policies, and a historical
price database. There has been discussion about moving to a
report-based main window; if that were to be the case, we could make
the accounting equation readily visible to the user.
*/

View File

@ -30,28 +30,12 @@ src/doc/design, but this is even more outdated.
Where possible, each overview is dated - take care to review older texts
in relation to existing code.
- \ref backuppolicy
- \ref bookperiods
- \ref currencies
- \ref deprecated
- \ref engine
- \ref backendold
- \ref financeconstraints
- \ref druidframework
- \ref guid
- \ref gnome2
- \ref loanhandling
- \ref kvpvalues
- \ref lotsoverview
- \ref multicurrency
- \ref pricedocs
- \ref gnucashextension
- \ref python_bindings_page
- \ref qif
- \ref budgetplan
- \ref taxnotes
- \ref todo
- \ref userprefs
Each overview in this section is generated directly from the
source files using Doxygen but some topics need updating.

View File

@ -1,45 +0,0 @@
/** \page engine Engine Framework
API: \ref Engine
Additional engine API documentation can be found in the src/doc/design/engine.texinfo file.
This file contains some extra meta-information that is not directly relevant
to the API documentation.
\section firstclass First Class Objects (C structs) vs. Storing Data in KVP Trees
API: \ref KVP
Suppose you have a neat idea for a new feature for the GnuCash engine.
Should you create a C structure (a "first class object") and all
of the required machinery for it (e.g. an SQL backend), or should you
just put all of the data in a suitable KVP (Key Value Pair) frame
somewhere?
The answer depends on whether the concept requires extensive
pointer chasing between different types of existing C structs,
or whether it more naturally can hang with some existing object.
If it seems to be an independent concept, it can still be placed
in the KVP tree of the book, which gives it a 'top-level' existence.
If the concept is used only infrequently, then it probably belongs
in a KVP tree. If the concept has performance-critical requirements,
then it is better to implement it as a C struct, and similarly
design an appropriate SQL table around it, so that the database
can be queried efficiently and rapidly.
\subsection terms Terminology:
- First-class object: something that has a C struct associated with it,
and has its own specialized backend infrastructure for storing/querying
it.
- Second-class object: something that lives entirely in a KVP tree.
Note, however, that not all data in a KVP tree deserves to be called
an 'object'. Some things in a KVP tree are merely 'attributes'.
If you push on this point, there is indeed a gray area between
second-class objects and attributes.
*/

View File

@ -1,161 +0,0 @@
/** \page gnome2 GnuCash Gnome2 architecture
\section gnome2names Naming
g1 - The gtk1 and gnome1 libraries.
g2 - The gtk2 and gnome2 libraries.
\section gnome2primer GTK2 Primer
In gtk2, an "action" is a g_object that represents some action that
the user might want to perform. This object could represent opening a
file, toggling the toolbar, etc. The action itself has *no* gui
component. There is no way to directly display an action to the user.
To do that, you assign the action to one or more proxy items. These
proxy items are the regular menu items, toolbar buttons, etc. that you
are familiar working with. There are several advantages to this new
system. The first is that you no longer have to write multiple action
routines; one for a menu selection and another for a button click.
There is a single code fragment written for when the action fires,
regardless of how it fired. The second advantage is that you no
longer have to enable/disable the individual menu items and buttons.
Enabling/disabling the action itself causes all proxy items to assume
the same state. For example, if an account isn't selected in the
account tree window, a single function call disables the "Open
Account" command in the main application menus, the "Open Account"
popup menu command, and the "Open Account" toolbar button.
A gtk2 "menu merge" takes descriptions of two sets of menus and merges
them into a single menu that is displayed on the screen. The first
menu must contain attachment points in it. These attachment points
are specified in the seconds set of menus and control where in the
combined menu the items from the second menu appear. This second
"merged" set of menus can easily be removed at any time.
Gtk2 has deprecated the clist and ctree widgets. The replacement is a
combination of a GtkTreeModel/GtkTreeView pair of objects.
In G1, most objects were based on a gtk_object, and were created,
destroyed, signaled, etc. using functions on this base object. In g2
the base object was moved from gtk2 to glib2, so most objects now need
to be based on the g_object object. There are still compatibility
functions on in gtk_object but you cannot mix and match calls to
g_object and gtk_object. You must use one function set or the other
for any given item.
\section gnome2windows Windowing Architecture
In the gtk1/gnome1 (hereafter g1) version of Gnucash, the windowing
was based on the "Multiple Document Interface" of g1. This code was
hard to use in the first place, and has been deprecated in g2.
The g2 version of gnucash is a series of plugin modules designed
around the g2 concepts of "actions" and "menu merging". These
concepts will be integrated into gtk2.4 release.
The first level of this architecture is an object representing a
"pluggable" window. This object is responsible for:
-# the window itself
-# providing a framework for plugins
-# providing a base set of menus (and actions)
Plugins can be one of two types. The first type is simply called a
"plugin" (e.g. gnc-plugin-register.c) and is used to add functionality
to the base window. This plugin provides only a menu/toolbar
description, and a way to create the second type of plugin. The
second type of plugin is called a "plugin page"
(e.g. gnc-plugin-page-register.c) and provides both a menu/toolbar
description, but also a widget that is displayed in the containing
window. This widget may be an account tree, a register, etc. The
plugin page must also provide a standard set of functions to interact
with the plugin manager code.
\section gnome2model Model/View Architecture
API: \ref GuiTreeModel
As mentioned above, the ctree widget has been deprecated in g2. Some
parts of gnucash have been converted to the new style using either a
GtkTreeModel/GtkTreeView pair of widgets, or using a
GtkTreeModel/GtkTreeModelFilter/GtkTreeModelSort/GtkTreeView set of
stacked widgets. The account tree is presented here as example of the
latter.
In gnucash, all the accounts are stored in the engine. The account
tree "model" (a GtkTreeModel) provides a representation of these
accounts that can be used by one or more views presented on the user's
screen. This code is designed so that there is only one single model
for the accounts in a given book, and this single model drives all
views. (This code should be easily expandable to multiple sets of
books once engine support is added.) The filters and views are
completely independent of each other, even though they share a common
model, so you may see different accounts in each view, have different
accounts selected in each view, etc.
The account tree model is designed as a tree and contains a "pseudo"
account that is the root node of this tree. Whether the root node is
visible is a per-view setting. Also in the model is code to display
the contents of any row/column intersection in the tree. The
GtkTreeView code drives the actual display, and pulls numbers from the
account tree model as necessary to display them. For all intents and
purposes, the model is the sole gui representation of the account
tree. The overlaying filters and views simply limit what the user
sees to some subset of the information in the model. There are very,
very few instances where code interacts directly with the account tree
model. All interaction should be done through the account tree view
described later.
The next layer in the account tree is the GtkTreeModelFilter. This
filter is automatically created when the account tree view is created.
In most instances, this filter is used to install a "virtual root" on
the model that hides the top level "pseudo" account from the user. At
the time of this writing, only the account edit dialog leave this top
node visible (so the user can create a new "top level" account.) This
filter level is use in several places to install a visibility filter
onto the model, controlling which accounts are visible to the user and
which are hidden. These visibility decisions are made in real time as
the user clicks the disclosure triangle on an account to see what
sub-accounts it contains. This callback function for the visibility
filter is the only place where the code should interact directly with
the account tree model, and the only interaction should be to take the
provided model/iter pair and ask the account tree model for the
corresponding account. After that the callback may do whatever it
wants on the account and then return TRUE if it wants the account to
be visible, FALSE if not.
The next layer in the account tree is the GtkTreeModelSort. This
layer provides the capabilities needed by a GtkTreeView to allow
sorting by clicking on column headers. If a column has a
non-alphanumeric sort, the GtkTreeView implementation must provide a
sort function for each different type of sort. This function will be
called by the GtkTreeSortModel for each pair of items it needs to
sort. The account tree model provides seven different sort functions
that are used by various columns.
The top layer of the account tree is the account tree view. The
underlying GtkTreeView object provides all the standard tree
manipulation functions; opening accounts to see sub-accounts, selecting
an item, etc. The account tree view is the programming interface that
should be used to manipulate an account tree. It provides the
functions to create a new view, to set a filter on an existing view to
control the visible rows, to configure the columns visible in the
view, to get/set the selected account(s) in the view, etc. There is
also a selection callback function available from the view, that may
be used to decide whether or not the user can select an account in the
view. It is used in the new account dialog, for instance, to limit
the accounts the user may select for the opening balance to an account
that has the same currency as the account being created.
\section gnome2ref References
http://developer.gnome.org/dotplan/porting/index.html
http://developer.gnome.org/doc/API/2.0/glib/index.html
http://developer.gnome.org/doc/API/2.0/gobject/index.html
http://developer.gnome.org/doc/API/2.0/gtk/index.html
*/

View File

@ -1,300 +0,0 @@
/** \page druidframework Generic (Import) Druid Framework
Derek Atkins <derek@ihtfp.com>
2004-01-12
Work in progress
\section druidbackground Background
The GNOME Druid infrastructure wants to force you to be UI-driven.
What this means is that the druid is started and lives in gtk_main()
while the user responds to the displayed Druid page. When the user
clicks a button (Next, Back, Help, or something inside the Druid page)
it performs some operation and then returns control to the GUI. For
example, a user clicking "Next" forces a callback based on that
specific page. That callback can (and should) set the next druid page
before returning control to the GUI.
If we were to make the importer backend-driven instead of GUI-driven
we would necessarily require nested gtk_main()'s. The reason is
that the backend was originally executed from GUI callback, so what
should happen is that the initialization sets up the import process
and then returns control so we dont have a nested gtk_main().
Nesting gtk_main() can result in crashes. If the originating window
is destroyed then when control returns we've jumped back into invalid
data space. This has happened on numerous occasions within the
gnucash code over time and has caused numerous bugs. For example, the
'Save while saving crashes gnucash' bug was due to a nested gtk_main
caused by the progress-bar. Consequently, the best way to avoid this
problem is not to introduce this problem and avoid nested gtk_main()
whenever possible. This means the importer should be GUI-driven, not
backend-driven.
\section druidproblem The Problem
For a generic importer druid, we want to create a single druid (or set
of druid components) that all importers can use. Moreover, this
framework should be UI-widget independent. The problem is that
different importer backends have different requirements for the UI.
For example, the QIF importer needs to map QIF Categories to GnuCash
Accounts, but OFX or HBCI have no such mapping requirement.
Another issue is that some sub-processes of the importing process
require multiple druid pages. If this sub-process is repeatable, it
means the druid needs to be able to jump back to the beginning of the
sub-process. For example, the process to choose files to import
should allow users to import multiple files at one time.
Moreover, even when a backend may sometimes require access to
particular druid sub-process, it may need to skip that sub-process
sometimes. For example, the QIF importer may have an ambiguity in the
date format for a file, requiring the user to choose the actual date
format. However if the imported file is not ambiguous this
sub-process of the druid can be skipped.
All of this means the druid framework should be able to rotate across
a subset of the pages for a sub-process or skip pages for a
sub-process based on the requirements of the backend.
In addition the framework should allow a global setting to enable or
disable "documentation pages" (c.f. the Show QIF Documentation
preference). Each sub-process can have a set of doc pages available
which can be displayed (or not) based on a user preference.
\section druidmain The Druid Framework
In order to refrain from pulling Gnome and GTK into the backend
implementations, we need a GUI-independent UI framework for Druids.
The framework is broken into Providers and the Druid Builder. A
Provider supplies a set of druid pages and the appropriate callbacks
for the backend to retrieve the user's data. The Druid Builder is the
process the backend uses to combine the various Providers into the
ultimate druid and set up all the callbacks to properly hook the druid
and backend together.
Each provider implements the Provider API and Provider Registrar API
and registers itself with the druid provider registry. The Provider
Registrar API defines the minimal set of functions and methods to
instantiate a provider and place a set of one or more pages into a
druid instance. The Provider API is used to set up the callbacks to
hook that provider into the backend.
In addition to the standard Provider API, each provider must define a
private API for use with the backend. Each provider is going to
interact with the backend differently, so there is no way to define a
common API for this interaction. On the other hand, the backend
already knows a priori which providers it needs to use, so it can know
the provider-dependent API and use that interaction.
The druid provider registry allows the Druid Builder to combine the
providers in the requested order when a backend asks to build a druid.
It uses the Provider Registrar API to instantiate a Provider and hook
it into the Druid, and then uses the Provider API to connect the
Provider to the backend using the data provided by the backend.
This leaves the importer backend blissfully unaware of the actual
Druid GUI/toolkit implementation (i.e. it doesn't need to know that
the Druid is actually a GnomeDruid -- it could be some other UI
toolkit). The backend calls the Druid Builder to put together the
druid with the appropriate providers and supplies the
provider-specific callback information necessary to hook into the
druid.
In order to initiate an import for a particular backend, the GUI calls
into the "start import" routine which builds an import context, builds
the import druid, and then returns control let the GUI run. This
means the import backend should be completely callback-based,
including the cleanup code in case the user interrupts the import.
\section druidprocess Druid Sub-Process Providers
In order to abstract the Druid from the various importer backends, the
import process is broken into a set of sub-processes. Each
sub-process is implemented as a Provider in the Druid framework. The
Provider implements a set of Druid pages that can be added to the
running druid and provides a set of callbacks to supply that input to
the import backend. For example, one sub-process could be "select the
file(s) for import" and another is "choose the date/number format".
The interface between the Provider and the Builder is obviously
toolkit-specific because the builder need to piece together the actual
druid pages (e.g. GnomeDruidPageStandard). The druid builder requests
an instance of a provider (and its pages) and supplies the provider
with the backend callbacks requests. The provider instance creates
the druid pages and connects the passed-in callback data so it can
call the backend appropriately.
Each provider necessarily requires its own callback interface (because
each provider needs to supply different data to the backend in
different ways). This is implemented by subclassing the basic
callback storage type. Because the importer backend knows the
providers being used, it can provide the required callback storage
type when it builds the druid.
When a user fills in a druid page and clicks on "Next" the druid will
call the next-page callback and supply the provided data (as defined
in the particular provider callback API). The backend then acts on
the callback data, sets the next page in the druid, and returns
control. Similar operations occur when the user clicks "Back", a
back-page callback, or any other callbacks required by the specific
provider.
\section druidtogether Putting the Druid Together
In order to build the druid, the import backend builds the list of
providers and passes that list to the Druid Builder. The Builder
creates the base druid and then pulls the druid pages from each
provider and inserts them into the druid. Finally, the builder
displays the druid and starts the process.
\section druidbackend Linking into the Backend
When supplying the list of providers to the builder, the backend also
provides a set of callbacks. Since the backend knows what providers
it wants, it can set up the appropriate callbacks. Each callback,
when called, passes in the user-input data in the callback function.
The callback function should process the data, set the next druid
page, and then return.
\section druidcore Core GncDruid Types
\subsection druidpage GncDruidPage
Opaque (toolkit-specific) type: a druid page. Used to pass an
opaque object from the provider, through the backend, to the druid
system (e.g. in order to set the druid page).
\subsection druidcallback GncDruidCB
Base type of a druid callback. Minimum information is the backend context.
Members:
gpointer backend_ctx;
\subsection druidobject GncDruid
The context object of a druid. This object contains all the
necessary data to maintain the druid and reference all it's data.
Members:
void set_page(\n
GncDruid,\n
GncDruidPage);
Set the current page of the druid to the GncDruidPage.
GncDruidProvider current_provider;\n
GncDruidProvider (*next_provider)(GncDruid);\n
GncDruidProvider (*prev_provider)(GncDruid);
\subsection druidproviderdesc GncDruidProviderDesc
The Druid Provider Description base class. This defines the minimal
information to name a provider and provide the interface required to
connect the provider to the backend. Each provider description
implementation should subclass this type. The backend should use
the subclasses.
Members:
const gchar *name;\n
gboolean (*provider_needed)(GncDruidCB);\n
gboolean (*next_cb)(GncDruid, GncDruidCB);\n
gboolean (*prev_cb)(GncDruid, GncDruidCB);
\subsection druidprovider GncDruidProvider
An instance of a Druid Provider. Still toolkit-independent (a
toolkit-specific subclass actually implements the functions
necessary for the builder) this interface allows the backend to
interface to the Provider to walk through the provider pages.
Members:
GncDruidPage (*first_page)(GncDruidProvider);\n
GncDruidPage (*next_page)(GncDruidProvider);\n
GncDruidPage (*prev_page)(GncDruidProvider);
\section druidapi The Druid Builder API
GncDruid gnc_druid_build(\n
GList *providers,\n
gpointer backend_ctx,\n
void (*end)(gpointer))
Build a druid using the supplied list of providers descriptions
(GncDruidProviderDesc). The provider list also contains all the
callback information necessary to hook the backend into the druid.
The backend_ctx and end() parameter are used to end the session in
the case of the user clicking "cancel". It cleans up the backend
context.
\section druidinternal The Basic (internal) Provider APIs
GncDruidProvider gnc_provider_get_instance(\n
GncDruid druid_ctx,\n
GncDruidProviderDesc description,\n
gpointer backend_ctx)
Obtain an instance of a Druid Provider based on the Provider
Description. This is used by the druid builder to obtain a Provider
Instance given the Provider Description.
void gnc_provider_register(\n
const gchar* name,\n
gnc_provider_get_instance);
Register a Provider Implementation of the provided name. Provide a
creation function that gnc_provider_get_instance() can use to obtain
a fully initialized provider object.
\section druidproviderapi Specific GncDruidProviderDesc APIs
Each provider needs to create its own subclass of GncDruidProviderDesc
that defines its specific interface to the backend. The following
sections show some example interfaces. In addition to the
ProviderDesc object, each provider can also provide a subclassed
GncDruidCB object for use in the callbacks.
GncDruidProviderDescChooseFmt
A provider that allows the user to choose a format in the case of
ambiguous input.
Members:
void (*get_ambiguity)(\n
gpointer be_ctx,\n
GncImportFormat* choices,\n
GncImportFormat* last_choice);
GncDruidChooseFmtCB
Members:
GncImportFormat choice;
GncDruidProviderDescSelectFile
A provider that allows the user to select the file(s) to import.
Members:
gboolean multi_file;\n
gchar* last_directory;\n
GList * (*get_files)(gpointer be_ctx);\n
const gchar* (*get_filename)(GncImportFile file);\n
void (*remove_file)(gpointer be_ctx, GncImportFile file)
GncDruidSelectFileCB
Members:
gchar* filename;
*/

View File

@ -1,48 +0,0 @@
/** \page gncnumericexample gnc_numeric Example
\section example EXAMPLE
The following program finds the best ::gnc_numeric approximation to
the \a math.h constant \a M_PI given a maximum denominator. For
large denominators, the ::gnc_numeric approximation is accurate to
more decimal places than will generally be needed, but in some cases
this may not be good enough. For example,
@verbatim
M_PI = 3.14159265358979323846
245850922 / 78256779 = 3.14159265358979311599 (16 sig figs)
3126535 / 995207 = 3.14159265358865047446 (12 sig figs)
355 / 113 = 3.14159292035398252096 (7 sig figs)
@endverbatim
@verbatim
#include <glib.h>
#include <qof.h>
#include <math.h>
int
main(int argc, char ** argv)
{
gnc_numeric approx, best;
double err, best_err=1.0;
double m_pi = M_PI;
gint64 denom;
gint64 max;
sscanf(argv[1], "%Ld", &max);
for (denom = 1; denom < max; denom++)
{
approx = double_to_gnc_numeric (m_pi, denom, GNC_RND_ROUND);
err = m_pi - gnc_numeric_to_double (approx);
if (fabs (err) < fabs (best_err))
{
best = approx;
best_err = err;
printf ("%Ld / %Ld = %.30f\n", gnc_numeric_num (best),
gnc_numeric_denom (best), gnc_numeric_to_double (best));
}
}
}
@endverbatim
*/

View File

@ -1,60 +0,0 @@
/** \page guid Globally Unique Identifiers: Design Issues
Linas Vepstas November 2003
API: \ref GUID
\section guidsummary Summary
GUID's are meant to uniquely identify a GnuCash object. However,
when that object is backed up (by copying a gnucash data file),
the identified object is no longer unique. Book closing is a
formalized means of saving older data. If a GnuCash data set
is large, and SQL is the storage backend, then making copies
of old data can be very wasteful of storage space. However,
book closing, by definition, must retain a copy of the data
'as it once was', as an (auditable) historical record. This
document debates different alternate schemes resolving the
uniqueness, searchability, copies and storage-space issues
that come up when handling GUID's on book closing.
\section guidintro Introduction
GUID's are meant to be a way of identifying a given GnuCash entity.
Accounts, transactions, splits, prices and lots all have GUID's.
GUID's can be used as a reference: by knowing a GUID, the matching
entity can be found. Because GUID's are 128 bits long, one could
have a billion different GnuCash users in a million different solar
systems without worrying about accidentally assigning the same
GUID to two different objects. So, given a GUID, one should be able
to come up with the object uniquely identified by it, right?
One practical problem is that backup copies of files containing
GnuCash data will have the same GUID's as the 'live data'. Because
the user may have modified the object, if one looked at the backup
copy, one would find more-or-less the same object, but it might
have different values (for the amount, the value, the date, the
title, etc.) Thus, a single value for a GUID can be associated
with several different but similar 'objects'.
A related practical problem occurs with the 'closing of books',
which is a certain formalized way of making a kind of backup.
After one has accumulated a lot of financial data, one has to
periodically make a permanent record of that data, and then
weed through it to throw away old (no longer interesting)
transactions. The 'closed book' contains all of the old
transactions, while the 'open book' looks just like it (has the
same accounts, etc), but doesn't have the old transactions.
\section guidissue The Issue
The current book-closing code makes a copy of the account tree,
and sorts all transactions, by date, into the new or the old
account tree. With the goal of not confusing the new and the
old account trees, the book closing code issues the old accounts
a new set of guids. The Pro's & Con's of this scheme:
Pro: The 'old', closed accounts can be uniquely accessed according
to their GUID's, without causing confusion with similar/same.
*/

View File

@ -1,281 +0,0 @@
/** \page multicurrency Multicurrency Discussion
<cstim> goonie: well...
<goonie> How about this:
<cstim> goonie: You can print each value as a gnc-monetary
goonie: this?
<goonie> cstim: don't worry, go on with your outline.
<cstim> How are you printing balances right now?
I guess you plug a \a gnc-numeric into the html code.
If you do a s/\a gnc-numeric/\a gnc-monetary/
... then everything would be multi-currency compliant
Of course the \a gnc-monetary needs the actual currency specified.
Would that lead to problems?
Definition of \a gnc-monetary is in src/scm/gnc-numeric.scm
<goonie> Cool.
<cstim> Right now every \a gnc-monetary is printed like $500.23, DEM 123.45, CHF 456.32
<goonie> I think that should work fine.
<cstim> but the formatting of \a gnc-monetary could be modified by any style sheet.
<goonie> You also had some code for calculating totals in multiple currencies?
<cstim> goonie: ouch. Yes. But that gets complicated quickly.
<goonie> Yes, it does.
<cstim> goonie: You will need to use a commodity-collector from report-utilities.scm
<goonie> OK, cool, I think I can figure it out.
<cstim> If you want the total of only one commodity, you can use the 'getpair action of commodity-collector...
but if you want to show (correctly) all of the currencies, you will have a lot of trouble.
Basically, I have the "reference implementation" in html-utilities.scm .
<goonie> OK, excellent.
<cstim> You can see how I print just one balance...
in the big function \a gnc:html-build-acct-table, line 297, where I print the total sum.
That would be a starting point to see how a balance with a bunch of commodities gets printed.
<goonie> cstim: taking it up a level for a second, how would you prefer a total for a
collection of splits in different currencies to be displayed?
<cstim> what do you mean by "total for splits"?
<goonie> OK, consider a transaction report for the account Expenses:Beer for the period
1/1/2001 to 2/1/2001 (UK date format ;)
and let's say I've had beer in Australia, the US, Germany, and Hong Kong during that period.
further, let's assume that my "native currency" is AUD.
cstim: try some of the Australian specialty beers.
<cstim> yes
<goonie> cstim: but even VB or Carlton Draught is an improvement on soap suds . . . er, Budweiser.
but back to Gnucash matters . . .
<cstim> yes
<goonie> now there's several possibilities for doing the totals here . . .
<cstim> wait wait
what accounts and what splits are you thinking of?
or in other words, what are your sorting/account/viewing parameters?
<goonie> Only one account selected, sorted by date, say (we'll discuss subtotals in a sec).
<cstim> goonie: One account means that there is only one currency, right?
<goonie> dave_p: hang on, let me just check . . .
s/dave_p/cstim
<cstim> oh
<goonie> dave_p: what's the status of currency-in-transaction?
<cstim> s/dave_p/???/
<goonie> nope, really dave_p this time :)
<cstim> dave_p is away: I'm doin' stuff
AFAIK an account has a commodity and a transaction has a commodity.
<goonie> correct.
<cstim> \a gnc:account-get-commodity, \a gnc:transaction-get-commodity
<goonie> However, read the comments in TransactionP.h
\verbatim
* The common_currency field indicates the currency type that
* all of the splits in this transaction share in common. This
* field is going to replace the currency field in the account
* structures.
\endverbatim
<cstim> yeah, that's right.
<goonie> So, in the short term, your assumption is correct.
In the long term, not the case.
<cstim> What I would usually call the "currency" of an account is in Gnucash acctually called "security".
\a gnc:account-get-commodity will return this security of the account.
<goonie> Gotta love terminology.
The reason for the differentiation is for stock/mutual fund accounts, if I recall correctly.
<cstim> The more recent comments about commodities are in Transaction.h, line 229 ff.
or Account.h, line 203ff.
<goonie> Yep, so the situation I described above can't happen right now, but will be possible
in the near future. Which brings us back to how should we display things:
A total for each currency.
<cstim> What account would that be?
<goonie> The account Expenses:Beer.
<cstim> What security will it have?
<goonie> AUD
<cstim> okay.
<cstim> go ahead
<goonie> OK, say that there's only four transactions in that account for the period in question:
$2 in AUD, 5 USD, 1 EURO, and 12 HKD being the values. What should we display as the total(s)?
Or more to the point, what options do we need to offer?
<cstim> waitwait. Expenses:beer has security AUD.
So there is one Transaction between Cash:USD and the beer.
And one between Cash:Euro and the beer.
And one between (what the heck is) Cash:HKD and the beer.
<goonie> Hong Kong Dollar, BTW.
<cstim> And, say, those Transaction have the transaction-commodity according to the Cash:*
<goonie> yep.
<cstim> But the split which belongs to Exp:Beer has only one value
and that value represents the beer expense in AUD.
i.e. in the split's account's security.
<goonie> hang on . . . let me think this through carefully . . .
<cstim> ok, lets get things straight: Each split has two fields, value and damount
Quote from a grib posting last October:
\verbatim
- Eliminate the 'share price' field from the Split structure and
replace it with a 'value' field. The 'value' is a translation of
the Split's 'damount' (which is the amount of the Account's
security involved) into the Transaction's balancing currency.
\endverbatim
the last sentence is the one that matters.
<goonie>
\verbatim
* value is the amount of the account's currency involved,
* damount is the amount of the account's security. For
* bank-type accounts, currency == security and
* value == damount.
gnc_numeric value;
gnc_numeric damount;
\endverbatim
from src/engine/ TransactionP.h
<cstim> that's outdated.
In the long run: value is the amount of the transaction-commodity involved, damount is
the amount of the account-commodity involved.
<goonie> OK, but the value returned from \a gnc:split-get-value is the value rather than the damount.
sorry for the long delay, I was reading code to make sure I understood what was going on.
value being the one denominated in the transaction-commodity.
<cstim> That's right. \a gnc:split-get-value gives you the value, whereas
\a gnc:split-get-share-amount gives you the damount
Maybe that functions need some name change in the future.
<goonie> perhaps.
the trouble is that there are so many things that need names in gnucash, that you start to run out :)
<cstim> :)
We could \a gnc:split-get-share-amount => \a gnc:split-get-damount
whatever. My point for the Beer is let's have some.
<cstim> oops.
I would expect that the transaction report uses \a gnc:split-get-share-amount
which in this case gives you already the amounts exchanged into AUD and everything's fine.
<goonie> You would prefer that over the transaction-specific value, then?
<cstim> Well, if I want the list for one specific account, then I would expect all amounts to be
in that account's commodity, i.e. the account-commodity (formerly known as security :)
<goonie> yep.
But then the problem just arises in a different light if you have multiple accounts, sorted by date, say.
<cstim> I would recommend a name change for \a gnc:split-get-share-amount.
multiple accounts. okay, let's talk about that. what scenario do you think of?
<goonie> cstim: could you mail Dave wrt function renaming?
<cstim> I'll send a mail to the ML
<goonie> OK, let's say you've selected Expenses:Champagne (in Francs), Expenses:Saki
(in Yen), and Expenses:VB (in Aussie dollars), and you want a report for all those transactions
for the past month, sorted by date. You have Cash:Francs, Cash:Yen and
Cash:Aussie accounts with the expected currencies.
<cstim> what's VB?
<goonie> Victoria Bitter (Australian Beer).
<cstim> okay. well...
<goonie> If you want a distinctively Australian Alcoholic beverage, s/VB/Sparkling Red
<cstim> Lets have some. ( goonie offers cstim a glass of fine Rutherglen sparkling red. )
Transaction report: but it doesn't make much sense to show a total sum for that anyway, does it_
s/_/?/ oh well, it might.
<goonie> Option 1) display a total for each currency in the report.
<cstim> exactly.
Option 2) shows the total for only one currency, the report-currency.
Option 3) somehow gets the right exchange rate so that it also ends up with only one total.
I'd recommend option 2 for now. For option one you basically would have to copy the
code out of the html-build-acct-table function cited above.
<goonie> So, what happens to transactions not in the report-currency in option 2) - they aren't totalled?
<cstim> Maybe with the tons of comments it is do-able
goonie: yes, they dissolve in heat and aren't totalled.
<goonie> OK, I think I can implement 1) and 2). 3 (which might have to be split into 3a, 3b . . . )
can probably wait. Well, I could implement a "quickie" 3a that just grabs a current exchange
rate and does the conversion on it.
<cstim> again, for 1) you "just" have to copy ~100 lines of code from html-utilities.scm and
adapt them to your table structure.
<goonie> that has all sorts of problems, but might be useful if taken with a grain of salt.
OK.
<cstim> oh, a quick 3) costs you about 5 lines of extra cost.
<goonie> I think I can cope with that :)
<cstim> just look into pnl.scm and see how they (i.e. I) use gnc:make-exchange-alist and
\a gnc:make-exchange-function both from \a src/scm/commodity-utilities.scm
<goonie> OK, cool. Thanks for your help.
<cstim> what did you mean by "quickie" 3a that just grabs a current exchange rate "
a dialog box? a parameter? gnc-prices?
<goonie> gnc-prices. or a parameter.
something other than digging through a bunch of historical data trying to figure out what
the exchange rate was at the time of particular transactions.
<cstim> parameter: Bad. gnc-prices: Goood. I'd be happy if someone could implement that
to augment the current code in commodity-utilities.scm Oh, the exchange rate at the time
of a particular *transaction* is easy -- that's just the fraction value/damount .
<goonie> not always - what if the transaction is (say) yen/yen but you want to display in dollars?
for instance, our glass of saki, paid for in cash yen.
<cstim> Yes, right. currently the commodity-utilities stuff uses a weighted average over the
history. But using the last known exchange rate instead may be useful at times. Maybe I'll
implmement something like that maybe if i have time :)
<goonie>diff -up 'gnucash/src/engine/ Query.c' 'gnucash_transaction_report/src/engine/ Query.c'
*/

View File

@ -1,37 +0,0 @@
/** \page pricedocs Price Overview
The Prices and the Price DB overview is in src/doc/design/engine.texinfo
API: \ref Price
Below, a few meta-notes about how prices and the GUI (should) interact:
\section pricecompute Computing Prices
When a price is computed from the (value/amt) that a user entered
in a register, and this price is stored in the priceDB, then
both the register entry and the price must have links to each other
(via the KVP trees) so that each can be found from the other.
This is needed because if the user enters an incorrect amt or value
or date in the transaction register, and then corrects it later,
possibly weeks or months later, the corresponding price in the
priceDB must be fixed as well.
Similarly, if a user deletes a transaction (possibly because it
contains an error in date/amt/value), then it is advisable that
the corresponding priceDB entry must be deleted as well (since
it is not safe to assume that the price is 'correct').
\section Rounding errors
When doing price math in the register, one must be careful, because
round-off errors can make 'obvious' math inaccurate. Note that if
we define price as (value/amt), then we will find that
value != price * amt due to roundoff handling. One must be careful
and consistent in handling this in the register, as otherwise
users will be driven crazy by inconsistent behaviour.
(Linas Vepstas April 2003)
*/

View File

@ -1,198 +0,0 @@
/** \page qif QIF importer infrastructure.
Derek Atkins <derek@ihtfp.com>
2004-01-07
A work in progress....
API: \ref Import_Export
\section qifintro 0. Introduction
The existing qif importer in src/import-export/qif-import is both hard
to maintain and hard to re-integrate into the shared import
architecture. Similarly, the half-completed re-write in qif-io-core
is similarly hard to maintain (although it is arguably easier to
integrate). One problem with both of these solutions is that they are
written in Scheme, a language that many gnucash developers just don't
understand well. Another issue is that the code is not commented and
no documentation exists to help future developers track down bugs or
extend the importer as QIF changes over time (c.f. Memorized
Transaction import).
As much as "complete rewrite" tends to be a lot of work for little
gain, when few (if any) developers can understand the implementation
well enough to make changes, a complete re-write may make sense. This
document is an attempt to describe the architecture of the new
importer, implemented in C, and how it interfaces to the rest of the
import infrastructure.
\section qifarch 1. Importer Architecture
The importer is a multi-step, staged system that should implement a
read, parse, convert, combine, filter, finish process. The importer
starts with a clean import context and then each processing step
modifies it as per the user's requirements. A small set of APIs allow
the user to progress along the processing steps (and an internal state
machine makes sure the caller proceeds in the proper order).
The importer is driven by the UI code; the importer itself is just a
multi-stage worker. The UI code calls each step in the process. For
long-running operations the UI can provide a callback mechanism for a
progress bar of completion.
Each stage of the import process may require some user input. What
input is required depends on the stage of the process and what the
last stage returned. In some cases stages can be skipped. For
example, during the conversion phase if the date format is unambiguous
then no user input would be required and the "ask for date format
disamiguation" input can be skipped.
QUESTION: How does the importer relate the processing state back to
the UI? Simiarly, how does it pass back specific disambiguating
questions to ask the user (and how are those responses returned to the
importer)?
\section qifprocess 2. The Import Process
The import process starts when the UI creates a new import context.
All of a single import is performed within that context. The context
model allows multiple import processes to take place simultaneously.
The first step in the import process is selecting the file (or files)
to be imported. The UI passes each filename to the importer which
reads the file and performs a quick parse process to break the file
down into its component QIF parts. While the importer should allow
the user to iteratively add more and more files to the import context,
it should also allow the user to select multiple files at once
(e.g. *.qif) to reduce the user workload.
Each imported file may be a complete QIF file or it may be a single
QIF account file. In the latter case the UI needs to ask the user for
the actual QIF account name for the file. Similarly, each file may
need user intervention to disambiguate various data, like the date or
number formats.
QUESTION: If the user provides multiple files at once and each file
has internal ambiguities (e.g. the date format), should the user be
asked for each file, or can we assume that all the files have the same
format? Perhaps the UI should allow the user to "make this choice for
all files"?
Once the user chooses all their files (they can also remove files
during the process) the importer will combine the files into a common
import, trying to match QIF accounts and transactions from different
files. Part of this is duplicate detection, because QIF only includes
half a transaction (for any QIF transaction you only know the local
account, not necessarily the "far" account). If the importer sees
multiple parts of the same transaction it can (and should) combine
them into a single transaction, thereby pinning down the near and far
accounts.
The next series of steps maps QIF data objects to GnuCash data
objects. In particular, the importer needs the help of the UI to map
unknown QIF Accounts and Categories to GnuCash Accounts (the latter to
Income and Expense Accounts) and QIF Securities to GnuCash
Commodities. Finally the importer can use the generic transaction
matcher to map the existing transactions to potential duplicates and
also Payee/Memo fields to "destination accounts".
At the end of this process the accounts, commodities, and transactions
are merged into the existing account tree, and the import context is
freed.
\section qifobject 3. Importer Data Objects
\verbatim
QifContext
QifError
QifFile
QifObject
+-QifAccount
+-QifCategory
+-QifClass
+-QifSecurity
+-QifTxn
+-QifInvstTxn
\endverbatim
\subsection qifinternal Internal Data Types
QifHandler
QifData
\section qifapi 4. Importer API
\subsection qifcontexts QIF Contexts
\verbatim
/** Create and destroy an import context */
QifContext qif_context_create(void)
void qif_context_destroy(QifContext ctx)
/** return the list of QifFiles in the context. */
GList *qif_context_get_files(QifContext ctx)
/** merge all the files in the context up into the context, finding
* matched accounts and transactions, so everything is working off the
* same set of objects within the context.
*/
void qif_context_merge_files(QifContext ctx);
\endverbatim
\section qiffiles QIF Files
\verbatim
/**
* Open, read, and minimally parse the QIF file, filename.
* If progress is non-NULL, will call progress with pg_arg and a value from
* 0.0 to 1.0 that indicates the percentage of the file read and parsed.
* Returns the new QifFile or NULL if there was some failure during the process.
*/
QifFile qif_file_new(QifContext ctx, const char* filename,
void(*progress)(gpointer, double), gpointer pg_arg)
/** removes file from the list of active files in the import context. */
void qif_file_remove(QifContext ctx, QifFile file)
/** Return the filename of the QIF file */
const char * qif_file_filename(QifFile file);
/** Does a file need a default QIF account? */
gboolean qif_file_needs_account(QifFile file);
/** Provide a default QIF Account-name for the QIF File */
void qif_file_set_default_account(QifFile file, const char *acct_name);
/** Parse the qif file values; may require some callbacks to let the
* user choose from ambiguous data formats
* XXX: Is there a better way to callback from here?
* Do we need progress-bar info here?
*/
QifError qif_file_parse(QifFile ctx, gpointer ui_arg)
\endverbatim
\section qifstate 5. Importer State Machine
The state machine has the following structure. Named states (and substates)
must proceed in order. Some states (e.g. state b) have multiple choices.
For example you could enter substates b1-b2, or you can run qif_file_remove.
a. Create the context
- qif_context_create
b. Add/Remove files to be imported
b1. Add file
- qif_file_new
b2. Parse the added file
- qif_file_parse
Note that this needs to callback into the ui to handle ambiguities
- qif_file_remove
If the user wants to remove some files from the import context
- repeat (b) as necessary until user choses to move to (c)
c. Once all files are chosen, merge internally and continue the process
- qif_context_merge_files
d. map qif accounts to gnucash accounts
e. map qif categories to gnucash accounts
f. map qif securities to gnucash commodities
g. duplicate detection with existing gnucash txns
h. transaction matcher (map one-sided txns using Payee/Memo info)
*/

View File

@ -1,426 +0,0 @@
-*- mode: rst; buffer-file-coding-system: utf-8 -*-
Scheduled Transactions
======================
TODO
----
- meta
- [ ] GncSxListTreeModelAdapter: s/real/adapted/
- [ ] generic tree model adapter setup code
- [ ] move documentation into doxygen comments, here and in sources.
- [x] move files around
- [x] printf -> logging
- core
- ! [ ] @fixme-s
- ! [ ] after updating/merging new instances, ensure sx-instance-state consistency
- [x] sx list -> qof collection
- [x] sx engine events
- [x] sx list collection add/remove -- sx-list GNC_EVENT_ITEM_ADDED, _REMOVED
- [x] sx modified -- QOF_EVENT_MODIFY
- [x] sx upcoming instance model
- ! [x] implement sort model
- [x] rename, re-home gnc-sx-instance-model:sxsl_get_sx_vars
- [x] rename, re-home gnc-sx-instance-model:parse_vars_from_formula
- unit testing
- [ ] model updating in the face of change
- [ ] insert sx
- [ ] remove sx
- [ ] update sx
- [ ] add instances
- [ ] remove instances
- [ ] make "weird"
- [ ] ± disabled flag
- [x] ensure state consistency model is upheld
- [ ] check variables-unbound logic
- [ ] verify summary counts
- [ ] check "since last run" states
- [ ] specious datafile dirty-ing
- [ ] -autocreate[, ±notify]
- [ ] +autocreate, -notify
- [ ] +autocreate, +notify
- [ ] +autocreate, -notify, w/postponed
- [ ] +autocreate, +notify, w/postponed
- [ ] bugs
- [?] Expired scheduled transactions never run - <https://bugs.gnucash.org/show_bug.cgi?id=375892>
- remove
- [x] display-using src/gnome-utils/test/test-sx.c
- bugs
- ! [x] with SLR open (with instances), add variables to SX; only newly-created instances will have appropriate variable tables.
- ! [x] parse from 1.8 file doesn't setup start date correctly;
daily-auto-yes-notify.xac has start date of 2006-09-26, but new TXN is
for $today.
- [x] this causes phantom "SX has been changed, confirm cancel?" problems.
- [x] created/review txns disappear, eventual crash [ve20070303]_
- ! [x] auto-create (+notify) txns not in review list. [ve20070209]_
- [x] sx-from-trans: "unknown get.type [3]" [dh20070120]_
- ! [x] crash with two sx lists open and SX mutation
- I'm pretty sure this is due to SX lists not getting cleaned up on page close, somehow.
- [x] no way to clear a variable entry [ve20070209]_
.. [dh20070120] https://lists.gnucash.org/pipermail/gnucash-devel/2007-January/019667.html
.. [ve20070209] https://lists.gnucash.org/pipermail/gnucash-devel/2007-February/019834.html
.. [ve20070303] https://lists.gnucash.org/pipermail/gnucash-devel/2007-March/020069.html
- sx list page
- [/] make into split panel
- [ ] fix default slider position
- [ ] conf-save slider position
- ! [x] use gnc-tree-view
- ! [x] save/restore state
- sx editor
- [/] clean up source formatting
- [ ] move "non-editor" general app/ui code out of bottom of dialog-sx-editor.c
- [x] re-layout dialog
- tabs: "overview", "frequency", "template transaction" [, "estimation"]
- [ ] model-ize
- (check_consistent, especially...)
Notes::
GncSxEditModel* gnc_sx_edit_model_new(SchedXaction *sx);
gnc_sxed_check_changed( GncSxEditorDialog *sxed )
gnc_sxed_check_consistent( GncSxEditorDialog *sxed )
gnc_sxed_save_sx( GncSxEditorDialog *sxed )
gchar* gnc_sx_edit_model_get_name(GncSxEditModel *mdl);
void gnc_sx_edit_model_set_name(GncSxEditModel *mdl, gchar *new_name);
- gnc_dense_cal
- [ ] code cleanup
- [x] min-size
- [ ] change number-of-month properties to display-named properties (width, length)
- [ ] gconf setting for dense-cal font-size reduction
- [?] better transient/floating window
- [/] (re-format file)
- [x] eliminate the "couldn't find tag [1]" messages.
- ! [x] font handling: gdk -> pango
- [x] start-of-week := {sun,mon} (via locale)
- [x] {0, 1, 2, 3, 4, 6, 12} month selection for dense calendar
- [x] conf-save value
- [x] set_model(GncTemporalInstancesModel *mdl)
- [x] new interface creation.
- [x] register callbacks for signals
- [x] remove clist usage
- sx-from-trans
- [?] convert to GObject
- [x] hookup destroy/finalize
- FreqSpec
- [#] type+ui-type -> type
- use Recurrence instead of FreqSpec
- ! [x] load druid
- ! [x] sx-from-trans, <https://bugs.gnucash.org/show_bug.cgi?id=412633>
- ! [x] XML migration, handling
- xml:freqSpec -> obj:Recurrence
- [x] none (Recurrence doesn't support)
- [x] once
- [x] if once, fix Recurrence date to be SX start date. :p
- [x] daily
- [x] daily [m-f] (composite)
- [x] weekly, single
- [x] weekly, multiple (composite)
- [x] monthly (+quarterly, tri-anually, semi-annually, yearly)
- [x] semi-monthly (composite)
- [x] write Recurrences into new-version SX
- gnc-frequency
- ! [x] Support Recurrence
- [x] in
- [x] out
- ! [x] Support 'last-day-of-month'
- [x] simplify
- [x] remove daily [m-f] (-> weekly)
- [x] remove biweekly page (-> weekly)
- [x] remove > monthly pages (-> monthly)
- [x] clean up, reformat source
- gnc-plugin-page-sx-list
- [x] gnc_plugin_page_sx_list_cmd_new
- dialog-sx-editor
- [x] gnc_sxed_check_changed
- [x] gnc_sxed_check_consistent
- [x] gnc_sxed_update_cal
- [x] gnc_sxed_save_sx
- sx list
- [x] recurrence_cmp(...)
- [x] More compact recurrenceListToString(...).
- [ ] remove FreqSpec code
- [x] don't write FreqSpecs out.
- [ ] SX code
- [ ] engine
- [ ] backend
- [ ] gnc-frequency
- [ ] gnc-dense-cal-store
- [x] src/gnome/druid-acct-period.c
- gnc_frequency
- [ ] 'every x months' spin button makes large jumps::
<andi5> jsled: another topic: you have probably seen the "every x months" spin button make jumps greater than one, right? ... this seems to be due to a spin button timeout event which controls "fast-forward" spinning... it is run because the changed(?) signal handler is too slow
- [ ] support nth-weekday Recurrence period.
- [x] Freq=none doesn't work::
* 17:00:29 CRIT <gnc.engine.recurrence> recurrenceListNextInstance: assertion `rlist && ref && next && g_date_valid(ref)' failed
* 17:00:36 CRIT <gnc.engine.sx> gnc_sx_set_schedule: assertion `sx && schedule' failed
- since-last-run
- [ ] "reminder" instances should show number of days until due
- [ ] "Find unfinished" button; count; sensitize Ok as function of unfinished.
- [ ] bold SX names [tw20070614]_
- [ ] checkbox/option to show/hide reminders [tw20070614]_, or a multi-part tree [tw20070619]_
- [ ] filter/remove SXes that don't have any instances in the list [tw20070614-2]_
- [ ] remove tree expand controls, except for non-to-create instances with variables [tw200070614-2]_
- [x] text changes [tw20070614]_
- "Sx, Instance, Variable" -> "Transaction"
- "Instance State" -> "Status"
- "Variable Value" -> "Value"
- ! [x] save/restore dialog window size
- [x] remove split pane
- [x] "auto" scrollbars
- ! [x] rewrite adapter (re-)population logic
- [x] move "effect_change" up to app-utils/, test.
- [x] move state-change up to app-utils
- [x] move variable-setting up to app-utils
- [x] move summarization up to app-utils
- [x] add reminders, postponed to SxInstanceModel
- [x] add mutation support to sx instance model
- [x] state machine
- [x] add variable state to sx instance model
- [x] handle (hidden/system not for editing) variables.
- [x] add sx_upcoming_instance_model()
- [x] add effect_auto_create()
- [x] add some sort of "ready to go" flag and api
- [x] variable setting, primarily
- [x] some sort of commit_changes()
- [x] add variable table to instances
- [x] ui: add 'review created transactions' checkbox to SLR dialog
using txn search.
.. [tw20070614] https://lists.gnucash.org/pipermail/gnucash-devel/2007-June/020718.html
.. [tw20070614-2] https://lists.gnucash.org/pipermail/gnucash-devel/2007-June/020729.html
.. [tw20070619] https://lists.gnucash.org/pipermail/gnucash-devel/2007-June/020757.html
- destroy/cleanup, notes:
- dispose: break references; callable multiple times
- finalize: complete destruction; just before free; only called once
Pedantic Todo
-------------
- s/SchedXaction/Scheduled/
- s/temporal_state/instance_sequence_context/
- change instance variable from 'i' to '__i' or something
============================================================
(eventually real documentation... (?))
Since Last Run
--------------
+------------------+------------------+------------------+
| Thing | State | Value |
+------------------+------------------+------------------+
| - Foo | | |
+------------------+------------------+------------------+
| - 2006-08-27 | [Postponed|v] | |
+------------------+------------------+------------------+
| - variable-a | | 42 |
+------------------+------------------+------------------+
| - variable-b | | 75 |
+------------------+------------------+------------------+
| - 2006-08-27 | [To-Create|v] | |
+------------------+------------------+------------------+
| - variable-a | | 31 |
+------------------+------------------+------------------+
| - variable-b | | (value needed) |
+------------------+------------------+------------------+
The since-last-run dialog is a key user interface. More frequently than the
SX list or editor, the user will be in the process of creating transaction
instances through this interface.
The old SLR dialog has the following stages:
- Reminders
- can be promoted to "to-create"
- Auto-created, with notification
- To-Create
- postponed, to-create
- ignore state.
- Created review
- Obsolete SX cleanup
The new SLR dialog will have the following:
- Creation (treemodel consisting of)
- auto-created
- reminder
- postponed
- to-create
- [obsolete SX]?
There is no separate to-review page, however the user may (optionally) want
to see the created transactions. This is done using the transaction-search
functionality over the created transactions by ID.
Upcoming instance states
------------------------
- reminder -> to-create
- postponed -> to-create
- to-create -> postponed
- to-create -> ignore
- to-create -> created [terminal]
Definitions:
reminder
a transient upcoming transaction that will not be created.
postponed
a historical to-create transaction that the user has explicitly deferred.
to-create
an upcoming SX instance that should be created.
ignore
a scheduled instance the user has explicitly prevented the instantiation of.
created
the instance has been created in this interaction cycle.
Formula Parsing
---------------
A SXes formula is parsed in the context of:
- the template transaction
- the accounts of the splits
- the sequence number
- the date of the transaction
- a variable-binding table.
Testing Notes
-------------
- auto-create
- auto-create with postponed instances shouldn't destroy postponed
instances
- basic sequence stuff
dialog-sxsincelast.c: ~L1241:
"Handle an interesting corner case of postponing or
ignoring the first instance. We only want to increment the
counters for newly-discovered-as-to-be-created SXes."
- auto-create
- auto-create transactions can be created w/o user interaction
- their state is transitioned to 'created', which is not modifiable
- auto-create (+notify) transactions should be displayed, even if they are
the only transactions created.
- auto-create (-notify) transactions should not be displayed, unless there
are other transactions.
- Scenarios
- only auto-create (-notify): no SLR, info dialog w/count (***)
- only auto-create (+notify): SLR dialog, already created
- others, auto-create (-notify): SLR dialog, incl. created
- others, auto-create (+notify): SLR dialog, incl. created

View File

@ -1,21 +0,0 @@
/** \page taxnotes Some notes about taxes
From: Jon Kaare Hellan <Jon.K.Hellan@item.ntnu.no>
Norwegian rules are more or less as follows:
You pay income tax on
(sale price - commission) - (adjusted purchase price + commission)
Adjusted purchase price?? That's what makes us different.
Each Jan. 1., the cost base of stocks you hold is adjusted by some
amount. How it is computed does not matter here, but the idea is that
once the company has paid tax on a profit, a corresponding amount of
capital gains becomes tax free to the stockholders. Theoretically
attractive, difficult in practice.
So I need a way to keep track of these adjustments register for each
stock in a portfolio.
*/

View File

@ -1,63 +0,0 @@
/** \page userprefs User Preferences HOWTO
Well, since I just explained this issue to Benoit on IRC, I thought I could
just post it here. If somebody (Benoit?) considers it helpful, you might add
it somewhere to CVS.
\section userprefsadd How to add a preferences option
This text explains how to add options to the global preference dialog
from a module. The text uses the example of one simple boolean option
in the import-export/hbci module ("Cache password in memory?").
The option is created in the file src/import-export/hbci/hbci.scm,
with the following function call as a top-level function in that file:
\verbatim
(gnc:register-configuration-option
(gnc:make-simple-boolean-option
(N_ "Online Banking & Importing") (N_ "HBCI Remember PIN in memory")
"b" (N_ "Remember the PIN for HBCI in memory during a session")
#f))
\endverbatim
The actual option is created by the function call to
gnc:make-simple-boolean-option. Its first (string) argument is the
tab (page) name. If the option is supposed to appear on an existing
tab (page), the string has to match *exactly* the string used in
src/app-utils/prefs.scm. The second (string) argument above is the
actual option name. For lookup, this *exact* string will need to be
used again.
For other (more complex) types of options, look up the
gnc:make-xyz-option function to create your favorite option type in
src/app-utils/options.scm. Also, if one or more options are supposed
to go on a *new* tab/page, simply specify a tab/page name that didn't
exist yet. It will automatically be added.
During the actual program run, the option is looked up only once, in
src/import-export/hbci/hbci-interaction.c line 53:
\verbatim
cache_pin =
gnc_lookup_boolean_option(N_("Online Banking & Importing"),
"HBCI Remember PIN in memory",
FALSE);
\endverbatim
The third argument here is the default value in case the lookup
fails. The C function prototypes for lookup of other options can be found in
src/app-utils/global-options.h. A lookup of a global preference in
Scheme can be seen e.g. in src/report/reports/standard/register.scm
line 556:
\verbatim
(gnc:option-value (gnc:lookup-global-option "User Info" "User Name"))
\endverbatim
I.e., the option itself has to be looked up first by
gnc:lookup-global-option (from src/app-utils/prefs.scm), and then the
function gnc:option-value returns the actual value of the option
(defined in src/app-utils/options.scm).
*/

View File

@ -276,8 +276,6 @@ install(TARGETS gnc-engine
install(FILES ${engine_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gnucash)
set(engine_EXTRA_DIST
design.txt
extensions.txt
iso-4217-currencies.xml
iso-currencies-to-c.xsl
kvp_doc.txt

View File

@ -62,6 +62,8 @@ GType gnc_split_get_type(void);
/** @name Split Reconciled field values
These define the various reconciliations states a split can be in.
If you change these
be sure to change gnc-ui-util.c:gnc_get_reconciled_str() and
associated functions

View File

@ -1,431 +0,0 @@
/** \page backendold Engine Architecture (old)
API: Backend
\section oldintro Introduction
This document is becoming obsolete. Please refer to the design
documentation in src/doc/design for a complete description of the
Engine architecture.
The only remaining architecture flaw is related to the GnuCash XML v2
backend modularisation. QofSession includes a dynamic method of loading
a QofBackend that supersedes the use of gnc_module_load that currently
loads the module using guile/scheme. When the old XML backend is replaced
by Sqlite, this will be resolved.
Note that this flaw <b>does not appear in QOF</b> itself. The C code
enabling the entire guile/scheme load mechanism is GnuCash only.
\subsection oldflaw Architecture Flaw
What does Architecture Flaw really mean? There is a Soviet joke from the 1960's:
A westerner in Moscow stops a man to ask him the time. The man puts
down his breifcase, and flicks his wrist to look at his watch. "The
time is 7:03, the temperature is 12 degrees C, the air presssure is
950 mmHg and falling." The westerner remarks with considerable
interest, "Why, that's a mighty fine watch you have there! We don't
have anything like that in the America!" The Soviet responds, "Why
yes, this demonstrates the superiority of Soviet engineering over
decadent captalist design." Stooping to pick up his briefcase,
he mumbles half to himself, "If only these batteries weren't so heavy."
There is only one place where the engine requires the use of guile.
This is the remaining architecture flaw, see above.
\section oldreview Accounting Engine
This document reviews the operation of, and various design points
pertinent to the GnuCash accounting engine. The latest version
of this document can be found in the engine source-code directory.
\section enginestock Stocks, non-Currency-Denominated Assets
The engine includes support for non-currency-denominated assets,
such as stocks, bonds, mutual funds, inventory. This is done with
two values in the Split structure:
double share_price;
double damount;
"damount" is the number of shares/items. It is an "immutable" quantity,
in that it cannot change except by transfer (sale/purchase). It is the
quantity that is used when computing balances.
"share_price" is the price of the item in question. The share-price is
of course subject to fluctuation.
The net-value of a split is the product of "damount" and "share_price".
The currency balance of an account is the sum of all "damounts" times
the latest, newest share-price.
Currency accounts should use a share price of 1.0 for all splits.
To maintain the double-entry consistency, one must have the following
hold true:
0.0 == sum of all split values.
If all splits are in the same currency, then this becomes:
0.0 == sum of all ((split->damount) * (split->share_price))
Thus, for example, the purchase of shares can be represented as:
source:\n
debit ABC Bank for $1045 (1045 dollars * dollar "price" of 1.00)
destination:\n
credit PQR Stock for $1000 (100 shares at $10 per share)
credit StockBroker category $45 in fees
If the splits are in mixed currencies and securities, then there must
be at least one common currency/security between all of them. Thus,
for example:
source:\n
debit ABC Bank for $1045 (1045 dollars * dollar "price" of 1.00)
destination:\n
credit VolkTrader for 2000 DM (1000 dollars at 2.0 mark per dollar)
credit Fees category $45 in fees
If the "currency" field is set to "DM" for the VolksTrader account,
and the "security" field is set to "USD", while the currency for ABC bank is
"USD", then the balancing equation becomes:
0.0 = 1045 * $1.00 - $1000 - 45 * $1.00
Note that we ignored the price when adding the second split.
\subsection enginestock Recoding a Stock Price
A stock price may be recorded in a brokerage account with a single
split that has zero value:
(share price) * (zero shares) == (zero dollars)
This transaction does not violate the rules that all transactions must
have zero value. This transaction is ideal for recording prices. Its
the only transaction type that may have a single split; everything else
requires at least two splits to balance. (at least when double-entry
is enabled).
\subsection engineplit Recording a Stock Split
Stock splits (i.e. when a company issues x shares of new stock for every
share already owned) may be recorded with a pair of journal entries as
follows:
(-old num shrs) * (old price) + (new num shrs) * (new price) == 0.0
where each journal entry credits/debits the same account.
Of course (new num shrs) == (1+x) * (old num shrs)
and the price goes inversely.
\section enginestock Stock Options
Stock options are not currently supported. To support them, the
following needs to be added:
A stock option is an option to purchase stock at a specified price.
Options have an expiration date. When you purchase an option it is
pretty much like buying stock. However, some extra information needs
to be recorded. To fully record an option purchase, you need to record
the underlying stock that the option is on, the strike price (i.e. the
price that the underlying stock can be purchases for), an expiration date,
and whether the option is a put or a call. A put option is the option
to sell stock at the strike price, and a call option is the option to
purchase stock at the strike price. Once an option is bought, it can
have one of three dispositions: it can be sold, in which case, it is
pretty much just like a stock transaction. It can expire, in which
case the option is worthless, and (IIRC) can be/is treated as a sale
at a zero price. Thirdly, it can be exercised, which is a single
transaction whereby stock is purchased at the strike price, and
the option becomes worthless.
Another point: with standardized options one option contract represents
the ability to purchase (with a call option) or sell (with a put option)
100 shares of the underlying stock.
\seection engineerror Error Reporting
The error reporting architecture (partially implemented), uses a globally
visible subroutine to return an error. In the naivest possible implementation,
the error reporting mechanism would look like this:
\verbatim
int error_num; // global error number
int xaccGetError (void) { return error_num; }
void xaccSomeFunction (Args *various_args) {
if (bad_thing_happened) error_num = 42;
}
\endverbatim
Many programmers are used to a different interface, e.g.
\verbatim
int xaccSomeFunction (Args *various_args) {
if (bad_thing_happened) return (42);
}
\endverbatim
Because of this, it is important to explain why the former design was
chosen over the latter. Let us begin by listing how the chosen design
is as good as, and in many ways can be better to the later design.
-# Allows programmer to check for errors asynchronously, e.g. outside
of a performance critical loop, or far away, after the return of
several subroutines.
-# (with the right implementation) Allows reporting of multiple, complex
errors. For example, it can be used to implement a trace mechanism.
-# (with the right implementation) Can be thread safe.
-# Allows errors that occurred deep in the implementation to be reported
up to much higher levels without requiring baggage in the middle.
The right implementation for (2) is to implement not a single
variable, but a stack or a ring (circular queue) on which error codes
are placed, and from which error codes can be retrieved. The right
implementation for (3) is the use pthread_getspecific() to define a
per-thread global and/or ring/queue.
\section engineisolation Engine Isolation
Goals of engine isolation:
- Hide the engine behind an API so that multiple, pluggable engines
could be created, e.g. SQL or CORBA.
- Engine users are blocked from being able to put engine internal
structures in an inconsistent state. Updates are "atomic".
Some half-finished thoughts about the engine API:
- The engine structures should not be accessible to any code outside
of the engine. Thus, the engine structures have been moved to
AccountP.h, TransactionP.h, etc.
The *P.h files should not be included by code outside of the engine.
- The down-side of hiding is that it can hurt performance. Even trivial data
accesses require a subroutine call. Maybe a smarter idea would be to leave
the structures exposed, allow direct manipulation, and then "copy-in" and
"copy-out" the structures into parallel structures when a hidden back end
needs to be invoked.
- the upside of hiding behind an API is that the engine can be
instrumented with extension language (perl, scheme, tcl, python) hooks
for pre/post processing of the data. To further enable such hooks, we
should probably surround all operations on structures with "begin-edit"
and "end-edit" calls.
- begin/end braces could potentially be useful for two-phase commit schemes.
where "end-edit" is replaced by "commit-edit" or "reject-edit".
\section enginereconcile Reconciliation
The 'reconcile' state of a transaction can have one of the following values:
\verbatim
// Values for the reconciled field in Transaction:
#define NREC 'n' // not reconciled or cleared
#define CREC 'c' // The transaction has been cleared
#define YREC 'y' // The transaction has been reconciled
#define FREC 'f' // frozen into accounting period
\endverbatim
(Note that FREC is not yet used/implemented ...)
The process of reconciliation works as follows:
-# User enters new transaction. All splits are marked 'n' for 'new'
or 'no, not yet reconciled'.
-# User believes that the transaction has cleared the bank,
e.g. that a cheque written out has been deposited/cashed.
User clicks in the 'R' column in the register gui,
marking the split 'c' for 'cleared'. User can freely
toggle this flag from the GUI with essentially no penalty,
no complaints. This is a 'safe' operation. Note that the
register shows the 'cleared' subtotal, which is, essentially,
a guess of the banks view of the account balance.
-# When user gets the bank statement, user launches the
reconcile dialogue. This dialogue is used to match transactions
on the bank statement with which is recorded locally.
Reconciled transactions are marked with a 'y'.
Note that once a transaction has been marked 'y', and the
user has 'finished' with the reconcile dialogue, then it
should be 'hard' to change the reconcile state from
the ordinary register dialogue. It should be sort-of
'set in stone'. (The engine does NOT enforce this,
only the gui enforces this.)
-# When the books are closed, all splits should be marked
'frozen', and become truly un-editable. The engine should
enforce 'frozen', and just plain not allow editing of closed
books, period. The only wat to change this would have been
to re-open the book. (and the reopening of a book would
change all 'f' to 'y'.)
About storing dates associated with reconcile:
\verbatim
> I think that there should be a date stamp attached to the reconciliation
> field so that as well as knowing that it has been reconciled, you also
> know *when* it was reconciled.
>
> This isn't so important for personal finances for the periodic user; I
> have in the past wanted to know when a particular transaction was
> reconciled. This is useful if you want to trace back from the
> electronic record to determine when the item actually cleared through
> the bank.
>
> This means that I can look at Cheque #428, written Jan 1/97, cashed in May
> 1997 (it sat in someone's desk for a while) in the computer system and say
> "Ah. It was marked as reconciled on June 12th/97. That was when I did the
> reconciliation of the May bank statements. Ergo, the cheque cleared in May,
> and that's the statement to go to to find a copy of the cheque..."
>
> It's not terribly important for cheques that get cashed right away; it *is*
> for things that hang around uncashed for a while.
\endverbatim
If the above is implemented, what date should be stored if the user
toggles the recn flag a few time? The date of the last toggle?
The very first date that it was recn'ed?
\section enginebackup Automatic Backup
The following has been implemented:
Have (by default) xacc create a backup file
filename-timestamp.xac on every save. This will eat up some disk
space until you go back and kill the older versions, but it's
better than not realizing that the data's subtly corrupt a week
later.
A lot of small-office/home systems do this. primarily useful as a
historical record, in case you accidentally wipe out something, and
don't spot it until later. Limited usefulness, but very nice in case
you accidentally delete an entire account.
To a limited degree, it provides atomicity/consistency/etc at the
course-grained account-group level.
\section enginetransaction Transaction Processing
There is a rudimentary level of "TP" build in, via the routines
xaccTransBeginEdit(), xaccTransRollbackEdit(), and xaccTransCommitEdit(),
which allow changes to be made to a transaction, and then committed,
or rejected at the end. Handy for the GUI, if the user makes a bunch
of changes which they don't want to keep; also handy for an SQL back end,
where the Commit() routine triggers the actual update of the SQL database.
Note: 'Commit' is sometimes called 'post' in other systems: The
act of 'committing' a transaction is the same as 'posting' the
transaction to the general journal.
Some important implementation details to understand: the GUI currently
uses begin/end as a convenience, and thus, may hold a transaction in
the 'edit' state for a portentially long time (minutes or hours).
Thus, begin/end should not map naively to a table-lock/unlock.
Instead, an optimistic-locking scheme, as below, is preferred.
The SQL back-end should implement posting entirely in the
'Commit()' routine. The pseudo-algorithms should look as follows:
\verbatim
BeginEdit () {
// save a copy of what it was before we start editing
old_transaction = this;
}
SetValue (float amount) {
// some example editing done here
this->value = amount;
}
Commit () {
LockTable();
current = QueryTransaction();
// check ton make sure that what the sql db stores
// is identical to what we have on record as the
// 'original' transaction. If its not, then someone
// got in there and modified it while we weren't
// looking; so we better report this back to user.
if (current != old_transaction) Error(); Unlock(); return err;
// otherwise, all is OK, we have successfully obtained
// the lock and validated the data, so now just update things.
StoreTransaction (new_transaction);
UnlockTable();
old_transaction = NULL;
}
Rollback () {
// throw away the edits
this = old_transaction;
old_transaction = NULL;
}
\endverbatim
The GUI should check to make sure that the Commit() routine didn't fail.
If it did fail, then the GUI should pop up a notice to the user stating
that the fundamental underlying data has changed, and that the user
should try doing the edit again. (It might be nice to indicate which
other human user might have changed the data so that they could
coordinate as needed.)
\section enginelogs Journal Logs
The following has been implemented; see TransLog.c for details.
Transaction logs. The idea was that every time a transaction
was called that would cause a data update, the information that
was updated would be dumped out into an "append only" log file.
This somewhat parallels what better database systems do to ensure
integrity; Oracle, for instance, has what is called an "archive log."
You have a copy of the database "synced up" as at some point in time,
and can apply "archive logs" to bring that old copy of the database
up to date should something go wrong to trash today's copy.
In effect, you'd have things like
\verbatim
=== 97/01/01 04:32:00 === Add Transaction ==== [whatever was added] ====
=== 97/01/01 04:32:02 === Delete Transaction ==== [whatever was deleted] ====
\endverbatim
It also is a useful debugging tool, as if you make sure that the
"log_transaction()" call starts by opening the log file, writes, and
then closes and syncs, you know what is going on with the data even if
horrible things happen to the "master" database file.
\section enginemanagement Session Management
To allow the user of the engine some guarantee of atomic updates,
serialized file I/O, related miscellany, the concept of a session
is supported. No file IO can be performed until a session has
been created, and file updates are not guaranteed atomic unless
performed within a SessionBegin/SessionEnd pair.
Note that (in the current implementation) data can be manipulated
outside of the session; its just that it cannot be saved/made persistent.
The goal of session management is to ensure that e.g. two users don't end
up editing the same file at the same time, or, e.g. that an automatic
stock-quote update daemon running under a different pid doesn't trash
data being currently edited by the user.
\section enginetodo Remaining Work Items
To find other remaining work items in the code, grep for the string
"hack alert".
See also the \ref todo.
\section engineenhance Ideas for engine enhancements:
-# Have (by default) gnucash immediately re-read a file after every
write, and compare the two resulting AccountGroups for equality.\n
During development, this is a good idea, as it will help uncover
thinko's more quickly, instead of letting them hide for weeks or months
(as the last one did). Its not a bad self-consistency check when
monkeying with the internals, damn the performance.\n
It can be removed/disabled for product versions.
\section olddate Needs updating.
This document is dated May 2000
Updated the architecture flaw section, June 2005.
*/

View File

@ -1,70 +0,0 @@
/** \page gnucashextension Proposed GnuCash Extensions
The following are proposals for various, as-yet-unimplemented
enhancements. The goal of this document is to understand some
of the changes that will come soon to the interfaces.
\section accountperiods Accounting Periods
Accounting periods are implemented by creating an object that
describes the accounting period, and then assigning every
transaction to at least one period.
\verbatim
typedef struct _accountingPeriod {
GUID guid; // id
char *name; // user-selectable name
int kind; // enum {none, week, month, quarter, year }
Timespec * start_date; //
Timespec * end_date;
AccountGroup *topgrp; // chart of accounts for this period.
} AccountingPeriod;
\endverbatim
The Transaction struct has to be extended with a period guid.
Every transaction can belong to at most one accounting period.
In addition, each chart of accounts needs to be extended with
an accounting period as well. This allows 'old' accounts to be deleted
from 'open books', without having to delete that same account from old
closed books. Basically, a new chart of accounts needs to be written
out/read from the engine for each new accounting period.
The xaccPeriodClose() subroutine performs the following:
- crawl over all transactions and mark them as being part of this
accounting period (actually, new transactions should by default be
getting put into the currently open period...)
- find the equity account (what if there is more than one equity account
?? what if equity has sub-accounts ?? )
- transfer all income/expense to equity (shouldn't the equity account
match the income/expense hierarchy?)
- return a new account group with new opening balances ...
\section transactionchanges Changes to Transaction Structure
Add an accounting period guid (see above).
\section splitchanges Changes to Journal Entry (Split) Structure
\subsection splitvoucher Voucher Reference
Add a char * voucher; This is a generic id string that somehow
identifies the piece of paper/electronic document(s) that indicate
where/how to find the paper trial for this entry. This list of id's
should probably be a list of key-value pairs, where the keys & values
can be completely configured by the user, and hold the needed data
that the user wants to store. For the SQL backend, this is a key
to a user-definable table.
\section bankingchanges Additional Banking Info
BankId -- routing & transit number (US) or Bankleitzan (DE) or Banque (FR)
BranchID -- Agence (FR), blank for other countries
AcctKey -- Cle (FR), blank in others
Account type enumerants:
bank account types:
checking, savings, moneymarket, creditline, cma (cash amangement account)
*/

View File

@ -36,8 +36,6 @@
addition and multiplication, but 64-bit rationals do not have
the dynamic range of floating point numbers.
See \ref gncnumericexample
@{ */
/** @file gnc-numeric.h
@brief An exact-rational-number library for gnucash.