GnuCash c935c2f+
Loading...
Searching...
No Matches
Scrub3.cpp
1/********************************************************************\
2 * Scrub3.c -- Constrain Cap Gains to Track Sources of Gains *
3 * *
4 * This program is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU General Public License as *
6 * published by the Free Software Foundation; either version 2 of *
7 * the License, or (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License*
15 * along with this program; if not, contact: *
16 * *
17 * Free Software Foundation Voice: +1-617-542-5942 *
18 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
19 * Boston, MA 02110-1301, USA gnu@gnu.org *
20\********************************************************************/
21
32#include <config.h>
33
34#include <glib.h>
35
36#include "cap-gains.h"
37#include "gnc-commodity.h"
38#include "gnc-engine.h"
39#include "gnc-lot.h"
40#include "policy-p.h"
41#include "Account.h"
42#include "AccountP.hpp"
43#include "Scrub2.h"
44#include "Scrub3.h"
45#include "Transaction.h"
46#include "TransactionP.hpp"
47
48static QofLogModule log_module = GNC_MOD_LOT;
49
50/* ================================================================= */
58static inline gboolean
59gains_possible (GNCLot *lot)
60{
61 SplitList *node;
62 Account *acc;
63 Split *split;
64 gboolean comeq;
65 gnc_commodity *acc_commodity;
66
67 acc = gnc_lot_get_account (lot);
68
69 node = gnc_lot_get_split_list (lot);
70 if (!node) return FALSE;
71 split = GNC_SPLIT(node->data);
72
73 acc_commodity = xaccAccountGetCommodity(acc);
74 comeq = gnc_commodity_equiv (acc_commodity, split->parent->common_currency);
75 return (FALSE == comeq);
76}
77
78/* ================================================================= */
79/* XXX What happens if, as a result of scrubbing, the lot is empty?
80 * I don't think this is handled properly. I think that what will
81 * happen is we'll end up with an empty, closed lot ... ?
82 */
83
84gboolean
85xaccScrubLot (GNCLot *lot)
86{
87 gboolean splits_deleted = FALSE;
88 gnc_numeric lot_baln;
89 gboolean opening_baln_is_pos, lot_baln_is_pos;
90 Account *acc;
91 GNCPolicy *pcy;
92
93 if (!lot) return FALSE;
94 ENTER ("(lot=%p) %s", lot, gnc_lot_get_title(lot));
95
96 acc = gnc_lot_get_account (lot);
97 pcy = gnc_account_get_policy(acc);
100
101 /* If the lot balance is zero, we don't need to rebalance */
102 lot_baln = gnc_lot_get_balance (lot);
103 PINFO ("lot baln=%s for %s", gnc_num_dbg_to_string (lot_baln),
104 gnc_lot_get_title(lot));
105 if (! gnc_numeric_zero_p (lot_baln))
106 {
107 SplitList *node;
108 gnc_numeric opening_baln;
109
110 /* Get the opening balance for this lot */
111 pcy->PolicyGetLotOpening (pcy, lot, &opening_baln, nullptr, nullptr);
112 PINFO ("lot opener baln=%s", gnc_num_dbg_to_string (opening_baln));
113
114 /* If the lot is fat, give the boot to all the non-opening
115 * splits, and refill it */
116 opening_baln_is_pos = gnc_numeric_positive_p(opening_baln);
117 lot_baln_is_pos = gnc_numeric_positive_p(lot_baln);
118 if ((opening_baln_is_pos || lot_baln_is_pos) &&
119 ((!opening_baln_is_pos) || (!lot_baln_is_pos)))
120 {
121rethin:
122 for (node = gnc_lot_get_split_list(lot); node; node = node->next)
123 {
124 Split *s = GNC_SPLIT(node->data);
125 if (pcy->PolicyIsOpeningSplit (pcy, lot, s)) continue;
126 gnc_lot_remove_split (lot, s);
127 goto rethin;
128 }
129 }
130
131 /* At this point the lot is thin, so try to fill it */
132 xaccLotFill (lot);
133
134 /* Make sure there are no subsplits. */
135 splits_deleted = xaccScrubMergeLotSubSplits (lot, TRUE);
136 }
137
138 /* Now re-compute cap gains, and then double-check that.
139 * But we only compute cap-gains if gains are possible;
140 * that is if the lot commodity is not the same as the
141 * currency. That is, one can't possibly have gains
142 * selling dollars for dollars. The business modules
143 * use lots with lot commodity == lot currency.
144 */
145 if (gains_possible (lot))
146 {
147 xaccLotComputeCapGains (lot, nullptr);
149 }
151
152 LEAVE ("(lot=%s, deleted=%d)", gnc_lot_get_title(lot), splits_deleted);
153 return splits_deleted;
154}
155
156/* ============================================================== */
157
158void
160{
161 LotList *lots, *node;
162 if (!acc) return;
163 if (FALSE == xaccAccountHasTrades (acc)) return;
164
165 ENTER ("(acc=%s)", xaccAccountGetName(acc));
168
169 lots = xaccAccountGetLotList(acc);
170 for (node = lots; node; node = node->next)
171 {
172 GNCLot *lot = GNC_LOT(node->data);
173 xaccScrubLot (lot);
174 }
175 g_list_free(lots);
177 LEAVE ("(acc=%s)", xaccAccountGetName(acc));
178}
179
180/* ============================================================== */
181
182static void
183lot_scrub_cb (Account *acc, gpointer data)
184{
185 if (FALSE == xaccAccountHasTrades (acc)) return;
187}
188
189void
190xaccAccountTreeScrubLots (Account *acc)
191{
192 if (!acc) return;
193
194 gnc_account_foreach_descendant(acc, lot_scrub_cb, nullptr);
196}
197
198/* ========================== END OF FILE ========================= */
This is the private header for the account structure.
Account handling public routines.
Utilities to Convert Stock Accounts to use Lots.
High-Level API for imposing Lot constraints.
API for Transactions and Splits (journal entries)
Utilities to Automatically Compute Capital Gains/Losses.
Commodity handling public routines.
All type declarations for the whole Gnucash engine.
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
Definition Account.cpp:3289
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition Account.cpp:1516
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition Account.cpp:1475
GNCPolicy * gnc_account_get_policy(Account *acc)
Get the account's lot order policy.
Definition Account.cpp:2100
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity
Definition Account.cpp:3408
gboolean xaccAccountHasTrades(const Account *acc)
The xaccAccountHasTrades() method checks to see if the indicated account is used in the trading of co...
Definition cap-gains.cpp:80
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equivalent.
LotList * xaccAccountGetLotList(const Account *acc)
The xaccAccountGetLotList() routine returns a list of all lots in this account.
Definition Account.cpp:3975
GList LotList
GList of GNCLots.
Definition gnc-engine.h:205
GList SplitList
GList of Split.
Definition gnc-engine.h:207
#define PINFO(format, args...)
Print an informational note.
Definition qoflog.h:256
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition qoflog.h:282
#define ENTER(format, args...)
Print a function entry debugging message.
Definition qoflog.h:272
Account * gnc_lot_get_account(const GNCLot *lot)
Returns the account with which this lot is associated.
Definition gnc-lot.cpp:377
gnc_numeric gnc_lot_get_balance(GNCLot *lot)
Returns the lot balance.
Definition gnc-lot.cpp:487
void gnc_lot_remove_split(GNCLot *lot, Split *split)
Adds a split from this lot.
Definition gnc-lot.cpp:631
SplitList * gnc_lot_get_split_list(const GNCLot *lot)
Returns a list of all the splits in this lot.
Definition gnc-lot.cpp:425
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
gchar * gnc_num_dbg_to_string(gnc_numeric n)
Convert to string.
gboolean gnc_numeric_positive_p(gnc_numeric a)
Returns 1 if a > 0, otherwise returns 0.
void xaccAccountAssignLots(Account *acc)
Loop over all splits, and make sure that every split belongs to some lot.
Definition Scrub2.cpp:59
void xaccLotFill(GNCLot *lot)
The xaccLotFill() routine attempts to assign splits to the indicated lot until the lot balance goes t...
Definition Scrub2.cpp:95
void xaccAccountScrubLots(Account *acc)
The xaccAccountScrubLots() routine makes sure that every split in the account is assigned to a lot,...
Definition Scrub3.cpp:159
gboolean xaccScrubMergeLotSubSplits(GNCLot *lot, gboolean strict)
The xaccScrubMergeLotSubSplits() routine does the same as the xaccScrubMergSubSplits,...
Definition Scrub2.cpp:390
void xaccLotScrubDoubleBalance(GNCLot *lot)
The xaccLotScrubDoubleBalance() routine examines the indicated lot.
Definition Scrub2.cpp:171
gboolean xaccScrubLot(GNCLot *lot)
The xaccScrubLot() routine makes sure that the indicated lot is self-consistent and properly balanced...
Definition Scrub3.cpp:85
Implement Accounting Policy Private header File.
STRUCTS.