I've been playing around with designing structures to capture budgeting in GnuCash, and figure out how budgeting integrates with the rest of the program. When you get closer to the end, it starts to unravel a bit... it's in a weird state in my head at the moment... not quite coherent, definitly not finished. Hopefully getting this mail out and getting some feedback will help me to make a somewhat fresh pass at it in the next week... Cheers... ...jsled ---------- General Notes and Structures There are maybe a set of budgets which exist in GnuCash at any one time [maybe one real, and one hypothetical, and one for the coming quarter/after job change... whatever]. This necessatitaes a budget manager, or group of budgets, and some interface to creating, destroying and selecting a budget for manipulation. But, in order for GnuCash to interact the user [warning them they're over budget when they make a register entry, for instance [and should the user desire this, of course!]], only one budget can really be considered. Therefore we have the idea of a single "active" budget. struct BudgetManager { GList /* <Budget*> */ *budgets; GUID activeBudget; // or GUID-equiv of NULL. }; Budgets have a name and description. They have a start date, and maybe an end date. Since a budget is a mapping of incoming to outgoing cash flows, we have lists of recurring incomes and expenses... We also have a list of Savings Goals... they generally have an explicit "end" [when the goal is reached, no more contributions are necessary], and are a bit more fungible than something like rent, especially if they're low-priority [saving for a new stereo]. They might also just be a more general form of recurring expenses: one which has a limit... struct Budget { char *name; char *description; time_t startDate; time_t endDate; // or 0, if indefinite GList /* <BudgetCategory*> */ *recurringIncomes; GList /* <BudgetCategory*> */ *recurringExpenses; GList /* <SavingsGoal*> */ *savingsGoals; }; BudgetCategories [BCats] are the categorical entries of the budget, used for both income and expense. They have a name, and probably a description. A recurring income or expense, at least, has a frequency of recurrence: enum RecurrenceEnum { DAILY, WEEKLY, BI_WEEKLY, MONTHLY, QUARTERLY, YEARLY, }; BudgetCategories can be arranged in a tree; bcats themselves contain their children, if any. The _aount_ of the bcat may be fixed or variable... Currently, we will only support simple and seasonal variable expenses. Simple variable expenses are those which have a base value, and some plus/minus range in which they will be. Seasonal variable expenses are defined over the course of a year, one amount per month [useful for utilities bills]. Eventually, there will need to be a more complex representation here to do thorough analyses, and really help the user make personal financial decisions via analysis. There will be some accessor function which gets the correct amount for a given specific date from the bcat, insulating the weirdness of any recurrnce or variable amount specification [this becomes even more important when the types of variable expenses increases]. Bcats contain a template transaction, which allows for scheduled transactions and their instantiation [a seperate scheduled-transaction thing is not part of this plan, but might be, time-permitting [see below for updated thoughts on this -- jsled]]. Specification of the date of the template transaction depends on the frequency of the bcat. The amount[s] of the template transaction is probably symbolic for whatever the "right" amount at the time of instantiation is. Hopefully the general ledger/register can be forced into editing things in the right way. A seperate list of expense categories which relate to the bcat are also stored, which allow for more transient cash outflow events to be correctly ascribed to the correct bcat as well. These add to the list of expense categories involved in template/schedule transactions to create the set of expense categories which the bcat 'covers'. Ideally, all expenses categories will be covered by the budget. Note that this only allows one or multiple expense accounts to be combined into a single bcat; it does not allow multiple bcats to cover a single expense account... don't know if this is the right thing, but it's fine for now. struct BudgetCategory { char *name; char *description; RecurrenceEnum freq; Transaction *templateTransaction; GList /* <Account*> */ *expenseAccounts; }; Savings goals are special beasts, as they have some limit [both in time and total amount, usually], and maybe some priority. The latter is useful WRT determining what portion of available funds to allocate to a savings goal. Savings Goals also have multiple accounts in which the funds allocated to that acount may be stored. The budgeting system is responsible for keeping track of the total amount saved toward a goal, and will store some amount of data relating to contributions towards a given savings goal, and the total amount in each storage account for that goal. There may be no transaction associated with a contribution [paycheck direct-deposited into checking account, and savings for goal held in same account], or transactions into one or more accounts [savings toward goal is distributed, for whatever reason]. Another example of split savings is emergency funds, of which most is in an interest-bearing savings account, but some is in a checking account so that the checking account is always above the minimum [read: fee-incuring] balance. This obviously then affects the real notion of "available funds" in account[s]; some integration with the register should occur, here. struct SavingsGoal { char *name; char *description; time_t dueDate; gfloat totalAmt; guint priority; // restricted to type bank, cash, stock, mutual [?] GList /* <Account*> */ *savingsAccounts; GList /* <Contributions*> */ *contributions; }; // This could use some work, otherwise it gets verbose over time. // It's unclear we need to store _every_ contribution outside of some // window... maybe just the total after that point. struct Contribution { time_t date; gfloat amt; SavingsGoal *toward; Account *from; }; With bcat's, especially yearly, infrequent things [christmas-time gifts, random gadget purchases, books] should be dealt with gracefully. There should be some strategy contained w/in the bcat which specifies how it is handled. For instance, it may be nice to save when possible to support future sporadic gadget purchases, instead of drawing from available funds/credit... This begins to cross over into savings goals, so it might just be best to have the bcat be or contain an implicit savings goal for such things. [see below for more thoughts about this] Analysis There are many kinds of analyses the user would like to perform with the budgeting tool. One of these is the initial analysis when creating the budget. A very obvious help for developers and current users is that the budgeting system should determine the initial cut at the budget from existing data... this will also be true of future users who don't initially use the budgeting system, but read reports of it's awesome power, and decide to use it. Budget creation can be based on historical data, a previous budget, a druid or straight user bcat creation. The budgeting tool can also help in fixing the amounts for different categories in the budget, if we model the problem as a constraint-satisfaction problem [and include a solver :)]. For instance: given this set of income and recurring expenses and these savings goals with these constraints [date due, absolute/relative priority, minimum-payments, &c], figure everything out... scheduling payments such that they are covered by available funds is another interesting problem. The more important analysis is the historical one, comparing budgeting constraints to actual spending. The results of this are to indicate to the user where they (over/under)spend, either to improve the amounts of the budgeting categories or so the use can select an appropriate punishment for themselves [GnuCash-inflicted pain will not be part of the first-cut at budgeting. :) ] The period of this analysis may be: . since last run . last <<time range>> In either case, long-term data will need to be pulled in from the budget [progress toward savings goals, yearly-budgeted periodic expenses, &c]. Ideally, this analysis will be able to make suggestions so that the user can adjust their budget or spending appropriately. For instance, it would be nice to have the budgeting system recognize that long-distance spending or food [variable, _controllable_ expenses] is too large, and if cut back by X percent, then the budget would balance. Alternatively, if consulting income Y is a _controllable_ income, then more income could be generated. Analyses of this nature require more information than is current in the budgeting model. The controllable nature of expenses is not indicated. More importantly, the long-distance calling example above is not at all represented in the budgeting model, at present. I believe that at some point down the road [and perhaps sooner rather than later], some "expected" expense categories [food, phone, utils, &c.] will need to allow for a more detailed approach to be taken, such that this information can be captured, and these recommendations can be made. I say "allow" because it is lame to force the user into entering 5 numbers [or ranges] for their phone bill if a) they don't want to or b) their bill isn't structured that way; if they want to say phone bills are "x +/- y" per month, then so be it. However, lack of information input doesn't enable the budgeting subsystem to perform some useful functions. There is some graphing here: cash-flow based time-series thingy is what I want. Some may want a pie chart, so eventually that'll show up. ========== After this point are random notes I thought up this recent weekend... they need to be cleaned up, and some of them invalidate what was said above... Scheduled Transactions . budgeting wants a mechanism for scheduled transaction. . a scheduled xaction is a set of xactions which can be instantiated when due or upon request. . a particular xaction may involve multiple budget categories. . when used by the budgeting system, some schedule transactions are linked to their bcats; changes go both ways. . fixed xactions have a fixed amt. . var xactions have a strategy for payment: . even-pay . user-prompt with expected range . one interface is visa the register [calendar-like repitition on jentries] . another is a seperate list/dialog. . in order to seperate scheduled transactions from the engine, we need some filter/selector for register entries. . defined by the templates in the scheduled xaction editor. . notion of freq is shared w/the budget editor . editing facilities are shared Savings Goals Types of expenses: . fixed/var, recurring: immed come from income, when available . sporadic [estimated|limited for period, no fixed schedule]: save|debt|from available . long-term specific goals. --- . Where do "Christmas Gifts" come in? . expected . funds needed in November . total amount estimated . should save over appropriate time period [starting 6 mo before, after other expenses are dealt with, &c] . ...gadgets? . superfulous [wrt spending] . savings depends on the expectation value . wish-list, prioritized/in-active items . medium-term savings goal, debt-repayment . ... car maint? . unexpected... half-expected . straight savings goal? . ...Burning Man? . same as Christmas: . expected . fund needed in August . total amount estimated . should save over appropriate time period ----- . these things can be seperated into short- and long-term. . they are different from straight recurring expenses. . new hierarchy: . recurring income . recurring expenses . periodic expenses . short-term . long-term . savings goals . short-term . long-term But even this is weird, as the periodic expeneses act as savings goals at times, and both are seperated into short- and long-term items... there's obviously some similarity there to be exploited. I'm also pretty sure that Savings Goals and bcats [at least expense categories] are pretty much the same thing... maybe the distinction isn't between income/expense bcats and savings goals, but instead between income [pretty simple] and all these wacky different kinds of expenses. _______________________________________________ gnucash-devel mailing list [EMAIL PROTECTED] http://www.gnumatic.com/cgi-bin/mailman/listinfo/gnucash-devel