diff --git a/src/engine/Period.c b/src/engine/Period.c index 49b6f23e7d..9ace76d8a0 100644 --- a/src/engine/Period.c +++ b/src/engine/Period.c @@ -178,35 +178,136 @@ find_nearest_equity_acct (Account *acc) /* traverse all accounts, get account balances */ static void -add_closing_balances (AccountGroup *closed_grp, GNCBook *open_book) +add_closing_balances (AccountGroup *closed_grp, + GNCBook *open_book, + GNCBook *closed_book, + Timespec *post_date, Timespec *date_entered, + const char *desc) { AccountList *acc_list, *node; + if (!closed_grp) return; + /* walk accounts in closed book */ acc_list = xaccGroupGetAccountList (closed_grp); for (node=acc_list; node; node=node->next) { + kvp_frame *cwd; + kvp_value *vvv; + Account *twin; + AccountGroup *childs; Account * candidate = (Account *) node->data; GNCAccountType tip = xaccAccountGetType (candidate); - if (EQUITY == tip) + /* find the peer account of this account in the open book */ + twin = xaccAccountLookupTwin (candidate, open_book); + + /* -------------------------------- */ + /* add KVP to open account, indicating the progenitor + * of this account. */ + xaccAccountBeginEdit (twin); + cwd = xaccAccountGetSlots (twin); + cwd = kvp_frame_get_frame_slash (cwd, "/book/"); + + vvv = kvp_value_new_guid (xaccAccountGetGUID (candidate)); + kvp_frame_set_slot_nc (cwd, "prev-acct", vvv); + + vvv = kvp_value_new_guid (&closed_book->guid); + kvp_frame_set_slot_nc (cwd, "prev-book", vvv); + + xaccAccountCommitEdit (twin); + + /* -------------------------------- */ + /* add KVP to closed account, indicating where + * the next book is. */ + xaccAccountBeginEdit (candidate); + cwd = xaccAccountGetSlots (candidate); + cwd = kvp_frame_get_frame_slash (cwd, "/book/"); + + vvv = kvp_value_new_guid (&open_book->guid); + kvp_frame_set_slot_nc (cwd, "next-book", vvv); + + vvv = kvp_value_new_guid (xaccAccountGetGUID (twin)); + kvp_frame_set_slot_nc (cwd, "next-acct", vvv); + + /* -------------------------------- */ + /* We need to carry a balance on any account that is not + * and income or expense or equity account */ + if ((INCOME != tip) && (EXPENSE != tip) && (EQUITY != tip)) { + Split *se, *st; + Transaction *trans; + Account *equity; + gnc_numeric baln; + + baln = xaccAccountGetBalance (candidate); + + /* find the equity account into which we'll poke the + * balancing transaction */ + equity = find_nearest_equity_acct (twin); + + /* -------------------------------- */ + /* create the balancing transaction */ + trans = xaccMallocTransaction (open_book); + xaccTransBeginEdit (trans); + st = xaccMallocSplit(open_book); + xaccAccountInsertSplit (twin, st); + + se = xaccMallocSplit(open_book); + xaccAccountInsertSplit (equity, se); + + xaccSplitSetValue (st, baln); + xaccSplitSetValue (se, gnc_numeric_neg(baln)); + + xaccTransSetDatePostedTS (trans, post_date); + xaccTransSetDateEnteredTS (trans, date_entered); + xaccTransSetDescription (trans, desc); + + /* add KVP data showing where the balancing + * transaction came from */ + cwd = xaccTransGetSlots (trans); + cwd = kvp_frame_get_frame_slash (cwd, "/book/"); + + vvv = kvp_value_new_guid (&closed_book->guid); + kvp_frame_set_slot_nc (cwd, "closed-book", vvv); + + vvv = kvp_value_new_guid (xaccAccountGetGUID(candidate)); + kvp_frame_set_slot_nc (cwd, "closed-acct", vvv); + + xaccTransCommitEdit (trans); + + /* -------------------------------- */ + /* add KVP to closed account, indicating where the + * balance was carried forward to. */ + xaccAccountBeginEdit (candidate); + cwd = xaccAccountGetSlots (candidate); + cwd = kvp_frame_get_frame_slash (cwd, "/book/"); + + vvv = kvp_value_new_guid (xaccTransGetGUID(trans)); + kvp_frame_set_slot_nc (cwd, "balancing-trans", vvv); + xaccAccountCommitEdit (candidate); } - } -#if 0 - for each + /* we left an open dangling above ... */ + xaccAccountCommitEdit (candidate); - -#endif + /* recurse down to the children */ + childs = xaccAccountGetChildren(candidate); + if (childs) + { + add_closing_balances (childs, open_book, closed_book, + post_date, date_entered, desc); + } + } } /* ================================================================ */ /* split a book into two by date */ GNCBook * -gnc_book_calve_period (GNCBook *existing_book, Timespec calve_date) +gnc_book_calve_period (GNCBook *existing_book, Timespec calve_date, + const char * memo) { Query *query; GNCBook *partition_book; @@ -247,6 +348,11 @@ gnc_book_calve_period (GNCBook *existing_book, Timespec calve_date) vvv = kvp_value_new_guid (&partition_book->guid); kvp_frame_set_slot_nc (exist_cwd, "prev-book", vvv); + /* add in transactions to equity accounts that will + * hold the colsing balances */ + add_closing_balances (gnc_book_get_group(partition_book), + existing_book, partition_book, + &calve_date, &ts, memo); return partition_book; } diff --git a/src/engine/Period.h b/src/engine/Period.h index f253fde554..7c1bdd2674 100644 --- a/src/engine/Period.h +++ b/src/engine/Period.h @@ -26,30 +26,49 @@ * book into two books, returning a newly created book with * the older transactions placed in it. * + * The 'memo' is used as the description in the transaction that + * creates the opening balances for the accounts. Typically, + * it should be _("Opening Balance") + * -- Make an equity transfer so that we can carry forward the balances. + the equity account is created if not found. only the peers and + immediate parents of an account is searchd for the qeuity account. + -- hack alert -- should not allow closed books to have unreconciled transactions ??? -- It will use the following kvp entries in /book/: -Implemented in book: -/book/start-date earliest date in this book. +Implemented in the closed book: /book/end-date latest date in this book. must not change ... /book/close-date date on which book was closed. -/book/next-book guid of next book -/book/prev-book guid of previous book +/book/next-book guid of next book (the still-open book) + +Implemented in still-open book: +/book/start-date earliest date in this book. +/book/prev-book guid of previous book (the closed book) -Mot imlemented (yet): -/book/closing-balance-of-account-guid +Implemented in the balancing transaction: +/book/closed-acct guid of account whose balance was brought forward +/book/closed-book guid of book whose balance was brought forward + +Implemented in the closed account: +/book/balancing-trans GUID of equity-balancing transaction. +/book/next-book GUID of equity-balancing book. +/book/next-acct GUID of twin of this account in the open book. + +Implemented in the still-open account: +/book/prev-acct GUID of twin of this account in the closed book. +/book/prev-book guid of previous book (the closed book) + +Not imlemented (yet), these should go into book: /book/name=some-user-supplied-name /book/notes=user-supplied-descriptive-comments /book/accounting-period=enum {none, week, month, quarter, trimester, year} -To go into account: -/book/balancing-trans GUID of equity-balancing transaction. */ -GNCBook * gnc_book_calve_period (GNCBook *, Timespec); +GNCBook * gnc_book_calve_period (GNCBook *, Timespec, const char *memo); /* The gnc_book_partition() uses the result of the indicated query * to partition an existing book into two parts. It returns