mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
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:
parent
3c860737f1
commit
58b4ee35f0
@ -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})
|
||||
|
@ -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
|
@ -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?
|
||||
|
@ -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...
|
||||
|
||||
*/
|
@ -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 ========================
|
@ -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. :-)
|
||||
|
||||
*/
|
@ -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
|
||||
|
||||
*/
|
@ -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.
|
||||
|
||||
*/
|
@ -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.
|
||||
|
@ -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.
|
||||
|
||||
*/
|
@ -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
|
||||
|
||||
*/
|
@ -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;
|
||||
|
||||
*/
|
@ -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
|
||||
*/
|
@ -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.
|
||||
|
||||
*/
|
@ -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'
|
||||
|
||||
*/
|
@ -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)
|
||||
|
||||
*/
|
@ -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)
|
||||
*/
|
@ -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
|
@ -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.
|
||||
|
||||
*/
|
@ -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).
|
||||
|
||||
*/
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
*/
|
@ -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)
|
||||
|
||||
*/
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user