1 /*
2  * gnc-sx-instance-model.h
3  *
4  * Copyright (C) 2006 Josh Sled <jsled@asynchronous.org>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of version 2 and/or version 3 of the GNU General Public
8  * License as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, contact:
17  *
18  * Free Software Foundation           Voice:  +1-617-542-5942
19  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
20  * Boston, MA  02110-1301,  USA       gnu@gnu.org
21  */
22 
23 /** \file
24  */
25 
26 #ifndef _GNC_SX_INSTANCE_MODEL_H
27 #define _GNC_SX_INSTANCE_MODEL_H
28 
29 #include <config.h>
30 #include <glib.h>
31 #include <glib-object.h>
32 #include "gnc-numeric.h"
33 #include "SchedXaction.h"
34 
35 G_BEGIN_DECLS
36 
37 #define GNC_TYPE_SX_INSTANCE_MODEL	      (gnc_sx_instance_model_get_type ())
38 #define GNC_SX_INSTANCE_MODEL(obj)	      (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_SX_INSTANCE_MODEL, GncSxInstanceModel))
39 #define GNC_SX_INSTANCE_MODEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_SX_INSTANCE_MODEL, GncSxInstanceModelClass))
40 #define GNC_IS_SX_INSTANCE_MODEL(obj)	      (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_SX_INSTANCE_MODEL))
41 #define GNC_IS_SX_INSTANCE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_SX_INSTANCE_MODEL))
42 #define GNC_SX_INSTANCE_MODEL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_SX_INSTANCE_MODEL, GncSxInstanceModelClass))
43 
44 typedef struct _GncSxInstanceModel
45 {
46     GObject parent;
47     gboolean disposed;
48 
49     /* private */
50     gint qof_event_handler_id;
51 
52     /* signals */
53     /* void (*added)(SchedXaction *sx); // gpointer user_data */
54     /* void (*updated)(SchedXaction *sx); // gpointer user_data */
55     /* void (*removing)(SchedXaction *sx); // gpointer user_data */
56 
57     /* public */
58     GDate range_end;
59     gboolean include_disabled;
60     GList *sx_instance_list; /* <GncSxInstances*> */
61 } GncSxInstanceModel;
62 
63 typedef struct _GncSxInstanceModelClass
64 {
65     GObjectClass parent;
66 
67     guint removing_signal_id;
68     guint updated_signal_id;
69     guint added_signal_id;
70 } GncSxInstanceModelClass;
71 
72 typedef struct _GncSxInstances
73 {
74     SchedXaction *sx;
75     GHashTable /** <name:char*,GncSxVariable*> **/ *variable_names;
76     gboolean variable_names_parsed;
77 
78     GDate next_instance_date;
79 
80     /** GList<GncSxInstance*> **/
81     GList *instance_list;
82 } GncSxInstances;
83 
84 typedef enum
85 {
86     SX_INSTANCE_STATE_IGNORED,
87     SX_INSTANCE_STATE_POSTPONED,
88     SX_INSTANCE_STATE_TO_CREATE,
89     SX_INSTANCE_STATE_REMINDER,
90     SX_INSTANCE_STATE_CREATED,
91     SX_INSTANCE_STATE_MAX_STATE
92 } GncSxInstanceState;
93 
94 typedef struct _GncSxVariable
95 {
96     gchar *name;
97     gnc_numeric value; /**< only numeric values are supported. **/
98     gboolean editable;
99 } GncSxVariable;
100 
101 typedef struct _GncSxInstance
102 {
103     GncSxInstances *parent; /**< the parent instances collection. **/
104     SXTmpStateData *temporal_state; /**< the sx creation temporal state. **/
105     GncSxInstanceState orig_state; /**< the original state at generation time. **/
106     GncSxInstanceState state; /**< the current state of the instance (during editing) **/
107     GDate date; /**< the instance date. **/
108     GHashTable *variable_bindings; /**< variable bindings. **/
109 } GncSxInstance;
110 
111 typedef struct _GncSxVariableNeeded
112 {
113     GncSxInstance *instance;
114     GncSxVariable *variable;
115 } GncSxVariableNeeded;
116 
117 GType gnc_sx_instance_model_get_type(void);
118 
119 /** Shorthand for get_instances(now, FALSE); */
120 GncSxInstanceModel* gnc_sx_get_current_instances(void);
121 
122 /** Allocates a new SxInstanceModel and fills it with generated
123  * instances for all scheduled transactions up to the given range_end
124  * date.
125  *
126  * The caller must unref the returned object by
127  * g_object_unref(G_OBJECT(inst_model)); when no longer in use. */
128 GncSxInstanceModel* gnc_sx_get_instances(const GDate *range_end, gboolean include_disabled);
129 
130 /**
131  * Regenerates and updates the GncSxInstances* for the given SX.  Model
132  * consumers are probably going to call this in response to seeing the
133  * "update" signal, unless they need to be doing something else like
134  * finishing an iteration over an existing GncSxInstances*.
135  **/
136 void gnc_sx_instance_model_update_sx_instances(GncSxInstanceModel *model, SchedXaction *sx);
137 void gnc_sx_instance_model_remove_sx_instances(GncSxInstanceModel *model, SchedXaction *sx);
138 
139 /** Fix up numerics where they've gotten out-of-sync with the formulas.
140  *
141  * Ideally this would be done at load time, but it requires gnc_exp_parser to
142  * work and neither engine nor the backends can depend on it.
143  */
144 void gnc_sx_scrub_split_numerics (gpointer psplit, gpointer user);
145 
146 /** @return GList<GncSxVariable*>. Caller owns the list, but not the items. **/
147 GList *gnc_sx_instance_get_variables(GncSxInstance *inst);
148 
149 Account* gnc_sx_get_template_transaction_account(const SchedXaction *sx);
150 
151 /**
152  * @return caller-owned data struct.
153  **/
154 GHashTable* gnc_sx_instance_get_variables_for_parser(GHashTable *instance_var_hash);
155 
156 GncSxVariable* gnc_sx_variable_new_full(gchar *name, gnc_numeric value, gboolean editable);
157 void gnc_sx_variable_free(GncSxVariable *var);
158 
159 /**
160  * There is a constraint around a sequence of upcoming instance states.  In
161  * short: the last-created state and a list of postponed instances are modeled,
162  * but upcoming reminders are not.  As such, a reminder can never be before any
163  * other (modeled) instance type.  For instance, the following sequences are
164  * disallowed:
165  *
166  * [...]
167  * remind    <- will be lost/skipped over; must be converted to `postponed`.
168  * to-create <- this will be the last-recorded state.
169  * [...]
170  *
171  * [...]
172  * remind    <- same as previous; will be lost/skipped; must be `postponed`.
173  * postponed
174  * [...]
175  *
176  * remind    <- same...
177  * ignore
178  * [...]
179  *
180  *
181  * As such, the SinceLastRun model will enforce that there are no previous
182  * `remind` instances at every state change.  They will be silently converted to
183  * `postponed`-state transactions.
184  **/
185 void gnc_sx_instance_model_change_instance_state(GncSxInstanceModel *model,
186         GncSxInstance *instance,
187         GncSxInstanceState new_state);
188 
189 void gnc_sx_instance_model_set_variable(GncSxInstanceModel *model,
190                                         GncSxInstance *instance,
191                                         GncSxVariable *variable,
192                                         gnc_numeric *new_value);
193 
194 /**
195  * @return List<GncSxVariableNeeded> of unbound {instance,variable} pairs;
196  * the caller owns the list and the items.
197  **/
198 GList* gnc_sx_instance_model_check_variables(GncSxInstanceModel *model);
199 
200 /** Really ("effectively") create the transactions from the SX
201  * instances in the given model. */
202 void gnc_sx_instance_model_effect_change(GncSxInstanceModel *model,
203         gboolean auto_create_only,
204         GList **created_transaction_guids,
205         GList **creation_errors);
206 
207 typedef struct _GncSxSummary
208 {
209     gboolean need_dialog; /**< If the dialog needs to be displayed. **/
210 
211     gint num_instances; /**< The number of total instances (in any state). **/
212     gint num_to_create_instances; /**< The number of (not-auto-create) to-create instances. **/
213     gint num_auto_create_instances;  /**< The total number of auto-create instances. **/
214     gint num_auto_create_no_notify_instances; /**< The number of automatically-created instances that do no request notification. **/
215 } GncSxSummary;
216 
217 /**
218  * @param summary Caller-provided, populated with a summarization of the
219  * state of the model.  Specifically, used to determine if there are SLR SXes
220  * that need either auto-creation or user-interaction.
221  **/
222 void gnc_sx_instance_model_summarize(GncSxInstanceModel *model, GncSxSummary *summary);
223 
224 /** Debug output to trace file */
225 void gnc_sx_summary_print(const GncSxSummary *summary);
226 
227 void gnc_sx_get_variables(SchedXaction *sx, GHashTable *var_hash);
228 int gnc_sx_parse_vars_from_formula(const char *formula, GHashTable *var_hash, gnc_numeric *result);
229 void gnc_sx_randomize_variables(GHashTable *vars);
230 
231 /** Returns a GHashTable<GUID*, gnc_numeric*> with no destructor for
232  * the key, but a destructor for the value set.
233  *
234  * The returned value must be free'd with g_hash_table_destroy or
235  * g_hash_table_unref. */
236 GHashTable* gnc_g_hash_new_guid_numeric(void);
237 
238 /** Instantiates the cash flow of all given SXs (in the given
239  * GList<SchedXAction*>) into the GHashTable<GUID*, gnc_numeric*> for the
240  * given date range. Each SX is counted with multiplicity as it has
241  * occurrences in the given date range.
242  *
243  * The creation_errors list, if non-NULL, receive any errors that
244  * occurred during creation, similar as in
245  * gnc_sx_instance_model_effect_change(). */
246 void gnc_sx_all_instantiate_cashflow(GList *all_sxes,
247                                      const GDate *range_start, const GDate *range_end,
248                                      GHashTable* map, GList **creation_errors);
249 
250 /** Simplified wrapper around gnc_sx_all_instantiate_cashflow(): Run
251  * that function on all SX of the current book for the given date
252  * range. Ignore any potential error messages. Returns a newly
253  * allocated GHashTable with the result, which is a GHashTable<GUID*,
254  * gnc_numeric*>, identical to what gnc_g_hash_new_guid_numeric()
255  * would return. The returned value must be free'd with
256  * g_hash_table_destroy. */
257 GHashTable* gnc_sx_all_instantiate_cashflow_all(GDate range_start, GDate range_end);
258 
259 G_END_DECLS
260 
261 
262 #endif // _GNC_SX_INSTANCE_MODEL_H
263