GnuCash c935c2f+
Loading...
Searching...
No Matches
policy.cpp
1/********************************************************************\
2 * policy.c -- Implement FIFO Accounting Policy *
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 "Account.h"
37#include "Account.hpp"
38#include "Transaction.h"
39#include "TransactionP.hpp"
40#include "cap-gains.h"
41#include "gnc-engine.h"
42#include "gnc-lot.h"
43#include "policy.h"
44#include "policy-p.h"
45
46#ifndef SWIG /* swig doesn't see N_() as a string constant */
47#include <glib/gi18n.h>
48#else
49#define N_(string) string
50#endif
51
52#define FIFO_POLICY "fifo"
53#define FIFO_POLICY_DESC N_("First In, First Out")
54#define FIFO_POLICY_HINT N_("Use oldest lots first.")
55#define LIFO_POLICY "lifo"
56#define LIFO_POLICY_DESC N_("Last In, First Out")
57#define LIFO_POLICY_HINT N_("Use newest lots first.")
58#define AVERAGE_POLICY "average"
59#define AVERAGE_POLICY_DESC N_("Average")
60#define AVERAGE_POLICY_HINT N_("Average cost of open lots.")
61#define MANUAL_POLICY "manual"
62#define MANUAL_POLICY_DESC N_("Manual")
63#define MANUAL_POLICY_HINT N_("Manually select lots.")
64
65//static QofLogModule log_module = GNC_MOD_LOT;
66
67static Split *
68DirectionPolicyGetSplit (GNCPolicy *pcy, GNCLot *lot, short reverse)
69{
70 Split *split;
71 gnc_commodity *common_currency;
72 gboolean want_positive;
73 gnc_numeric baln;
74 Split *osplit;
75 Transaction *otrans;
76 time64 open_time;
77 Account* lot_account;
78
79 if (!pcy || !lot || !gnc_lot_get_split_list(lot)) return nullptr;
80 lot_account = gnc_lot_get_account(lot);
81 if (!lot_account) return nullptr;
82
83 /* Recomputing the balance re-evaluates the lot closure */
84 baln = gnc_lot_get_balance (lot);
85 if (gnc_lot_is_closed(lot)) return nullptr;
86
87 want_positive = gnc_numeric_negative_p (baln);
88
89 /* All splits in lot must share a common transaction currency. */
90 split = GNC_SPLIT(gnc_lot_get_split_list(lot)->data);
91 common_currency = split->parent->common_currency;
92
93 /* Don't add a split to the lot unless it will be the new last
94 split in the lot. Otherwise our balance tests will be wrong
95 and the lot may end up too thin or too fat. */
96 osplit = gnc_lot_get_latest_split (lot);
97 otrans = osplit ? xaccSplitGetParent (osplit) : 0;
98 open_time = xaccTransRetDatePosted (otrans);
99
100 /* Walk over *all* splits in the account, till we find one that
101 * hasn't been assigned to a lot. Return that split.
102 * Make use of the fact that the splits in an account are
103 * already in date order; so we don't have to sort. */
104 auto find_split = [open_time, common_currency, want_positive](const Split* split)
105 {
106 return (!split->lot &&
107 xaccTransRetDatePosted (xaccSplitGetParent (split)) >= open_time &&
108 gnc_commodity_equiv (common_currency, split->parent->common_currency) &&
109 !gnc_numeric_zero_p (split->amount) &&
110 want_positive == gnc_numeric_positive_p (split->amount));
111 };
112
113 return gnc_account_find_split (lot_account, find_split, reverse);
114}
115
116/* ============================================================== */
117
118static GNCLot *
119FIFOPolicyGetLot (GNCPolicy *pcy, Split *split)
120{
121 if (!split) return nullptr;
123 split->parent->common_currency);
124}
125
126static Split *
127FIFOPolicyGetSplit (GNCPolicy *pcy, GNCLot *lot)
128{
129 return DirectionPolicyGetSplit (pcy, lot, 0);
130}
131
132static void
133FIFOPolicyGetLotOpening (GNCPolicy *pcy,
134 GNCLot *lot,
135 gnc_numeric *ret_amount, gnc_numeric *ret_value,
136 gnc_commodity **ret_currency)
137{
138 Split *opening_split;
139 opening_split = gnc_lot_get_earliest_split(lot);
140
141 if (ret_amount) *ret_amount = xaccSplitGetAdjustedAmount (opening_split);
142 if (ret_value) *ret_value = opening_split->value;
143 if (ret_currency) *ret_currency = opening_split->parent->common_currency;
144}
145
146static gboolean
147FIFOPolicyIsOpeningSplit (GNCPolicy *pcy, GNCLot *lot, Split *split)
148{
149 Split *opening_split;
150 opening_split = gnc_lot_get_earliest_split(lot);
151 return (split == opening_split);
152}
153
154GNCPolicy *
156{
157 static GNCPolicy *pcy = nullptr;
158
159 if (!pcy)
160 {
161 pcy = g_new (GNCPolicy, 1);
162 pcy->PolicyGetLot = FIFOPolicyGetLot;
163 pcy->PolicyGetSplit = FIFOPolicyGetSplit;
164 pcy->PolicyGetLotOpening = FIFOPolicyGetLotOpening;
165 pcy->PolicyIsOpeningSplit = FIFOPolicyIsOpeningSplit;
166 }
167 return pcy;
168}
169
170
171/* =========================== END OF FILE ======================= */
Account handling public routines.
Account public routines (C++ api)
API for Transactions and Splits (journal entries)
Utilities to Automatically Compute Capital Gains/Losses.
All type declarations for the whole Gnucash engine.
find_split(split_list, search_string)
Split * gnc_account_find_split(const Account *acc, std::function< bool(const Split *)> predicate, bool reverse)
scans account split list (in forward or reverse order) until predicate split->bool returns true.
Definition Account.cpp:1167
GNCLot * xaccAccountFindEarliestOpenLot(Account *acc, gnc_numeric sign, gnc_commodity *currency)
The xaccAccountFindEarliestOpenLot() method is a handy utility routine for finding the earliest open ...
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equivalent.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition gnc-date.h:87
time64 xaccTransRetDatePosted(const Transaction *trans)
Retrieve the posted date of the transaction.
Split * gnc_lot_get_latest_split(GNCLot *lot)
Convenience routineto identify the date this lot was closed.
Definition gnc-lot.cpp:670
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
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_lot_is_closed(GNCLot *lot)
Returns closed status of the given lot.
Definition gnc-lot.cpp:367
Split * gnc_lot_get_earliest_split(GNCLot *lot)
Convenience routine to identify the earliest date in the lot.
Definition gnc-lot.cpp:658
gboolean gnc_numeric_negative_p(gnc_numeric a)
Returns 1 if a < 0, otherwise returns 0.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
gboolean gnc_numeric_positive_p(gnc_numeric a)
Returns 1 if a > 0, otherwise returns 0.
GNCPolicy * xaccGetFIFOPolicy(void)
First-in, First-out Policy This policy will create FIFO Lots.
Definition policy.cpp:155
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
gnc_numeric xaccSplitGetAdjustedAmount(const Split *s)
Returns the stock-split adjusted amount of the split in the account's commodity.
Definition Split.cpp:1340
Implement Accounting Policy Private header File.
Implement Accounting Policy.
STRUCTS.