35 #include <glib/gi18n.h> 36 #include <glib-object.h> 48 #include "gnc-exp-parser.h" 55 #define G_LOG_DOMAIN "gnc.app-utils.sx" 62 #define REPORT_ERROR(list, format, ...) do { \ 63 g_critical(format, __VA_ARGS__); \ 65 *list = g_list_append(*list, g_strdup_printf(_(format), __VA_ARGS__)); \ 68 typedef struct _SxTxnCreationData
71 GList **created_txn_guids;
72 GList **creation_errors;
80 gint qof_event_handler_id;
83 gboolean include_disabled;
84 GList *sx_instance_list;
87 static GncSxInstanceModel* gnc_sx_instance_model_new(
void);
89 static GncSxInstance* gnc_sx_instance_new(
GncSxInstances *parent, GncSxInstanceState state, GDate *date,
void *temporal_state, gint sequence_num);
91 static gint _get_vars_helper(Transaction *txn,
void *var_hash_data);
95 static void _gnc_sx_instance_event_handler(
QofInstance *ent,
QofEventId event_type, gpointer user_data, gpointer evt_data);
96 static gnc_commodity* get_transaction_currency(
SxTxnCreationData *creation_data, SchedXaction *sx, Transaction *template_txn);
107 REMOVING, UPDATED, ADDED,
111 static guint signals[LAST_SIGNAL] = { 0 };
114 scrub_sx_split_numeric (Split* split, gboolean is_credit, GList **changes)
116 const char *formula = is_credit ?
"sx-credit-formula" :
"sx-debit-formula";
117 const char *
numeric = is_credit ?
"sx-credit-numeric" :
"sx-debit-numeric";
119 gnc_numeric *numval = NULL;
120 GHashTable *parser_vars = g_hash_table_new_full
121 (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_free);
123 gnc_numeric amount = gnc_numeric_zero ();
124 gboolean parse_result = FALSE;
131 parse_result = gnc_exp_parser_parse_separate_vars (formval, &amount,
132 &error_loc, parser_vars);
134 if (!parse_result || g_hash_table_size (parser_vars) != 0)
135 amount = gnc_numeric_zero ();
141 change->amount = amount;
142 *changes = g_list_prepend (*changes, change);
145 g_hash_table_destroy (parser_vars);
156 Split *split = GNC_SPLIT (psplit);
158 GList *changes = NULL;
159 scrub_sx_split_numeric (split, TRUE, &changes);
160 scrub_sx_split_numeric (split, FALSE, &changes);
165 for (GList *n = changes; n; n = n->next)
169 change->name, &change->amount,
173 g_list_free_full (changes, g_free);
177 _sx_var_to_raw_numeric(gchar *name,
GncSxVariable *var, GHashTable *parser_var_hash)
179 g_hash_table_insert(parser_var_hash, g_strdup(name), &var->
value);
183 _var_numeric_to_sx_var(gchar *name, gnc_numeric *num, GHashTable *sx_var_hash)
186 if (!g_hash_table_lookup_extended(sx_var_hash, name, NULL, &p_var))
188 p_var = (gpointer)gnc_sx_variable_new(name);
189 g_hash_table_insert(sx_var_hash, g_strdup(name), p_var);
195 _wipe_parsed_sx_var(gchar *key,
GncSxVariable *var, gpointer unused_user_data)
201 split_is_marker(Split *split)
203 gchar *credit_formula = NULL;
204 gchar *debit_formula = NULL;
205 gboolean split_is_marker = TRUE;
208 "sx-credit-formula", &credit_formula,
209 "sx-debit-formula", &debit_formula,
212 if ((credit_formula && *credit_formula) ||
213 (debit_formula && *debit_formula))
214 split_is_marker = FALSE;
216 g_free(credit_formula);
217 g_free(debit_formula);
218 return split_is_marker;
227 GHashTable *parser_vars;
229 parser_vars = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
230 g_hash_table_foreach(instance_var_hash, (GHFunc)_sx_var_to_raw_numeric, parser_vars);
235 gnc_sx_parse_vars_from_formula(
const char *formula,
236 GHashTable *var_hash,
242 GHashTable *parser_vars;
247 num = gnc_numeric_zero();
248 if (!gnc_exp_parser_parse_separate_vars(formula, &num, &errLoc, parser_vars))
254 g_hash_table_foreach(parser_vars, (GHFunc)_var_numeric_to_sx_var, var_hash);
255 g_hash_table_destroy(parser_vars);
266 gnc_sx_variable_new(gchar *name)
269 var->name = g_strdup(name);
271 var->editable = TRUE;
276 gnc_sx_variable_new_full(gchar *name, gnc_numeric value, gboolean editable)
280 var->editable = editable;
289 var->editable = to_copy->editable;
301 var_name_from_commodities(gnc_commodity* split_c, gnc_commodity* txn_c)
305 gchar* var_name = g_strdup_printf (
"%s -> %s",
306 split_m ? split_m :
"(null)",
307 txn_m ? txn_m :
"(null)");
309 DEBUG(
"var_name is %s", var_name);
314 _get_vars_helper(Transaction *txn,
void *var_hash_data)
316 GHashTable *var_hash = (GHashTable*)var_hash_data;
319 gchar *credit_formula = NULL;
320 gchar *debit_formula = NULL;
321 gnc_commodity *txn_cmdty = get_transaction_currency(NULL, NULL, txn);
324 if (split_list == NULL)
329 for ( ; split_list; split_list = split_list->next)
331 gnc_commodity *split_cmdty = NULL;
334 gboolean split_is_marker = TRUE;
336 s = (Split*)split_list->data;
339 "sx-account", &acct_guid,
340 "sx-credit-formula", &credit_formula,
341 "sx-debit-formula", &debit_formula,
344 guid_free (acct_guid);
347 if (credit_formula && strlen(credit_formula) != 0)
349 gnc_sx_parse_vars_from_formula(credit_formula, var_hash, NULL);
350 split_is_marker = FALSE;
352 if (debit_formula && strlen(debit_formula) != 0)
354 gnc_sx_parse_vars_from_formula(debit_formula, var_hash, NULL);
355 split_is_marker = FALSE;
357 g_free (credit_formula);
358 g_free (debit_formula);
368 var_name = var_name_from_commodities(split_cmdty, txn_cmdty);
369 var = gnc_sx_variable_new(var_name);
370 g_hash_table_insert(var_hash, g_strdup(var->name), var);
379 gnc_sx_get_template_transaction_account(
const SchedXaction *sx)
381 Account *template_root, *sx_template_acct;
387 return sx_template_acct;
391 gnc_sx_get_variables(SchedXaction *sx, GHashTable *var_hash)
393 Account *sx_template_acct = gnc_sx_get_template_transaction_account(sx);
398 _set_var_to_random_value(gchar *key,
GncSxVariable *var, gpointer unused_user_data)
406 var->
value = gnc_numeric_create(g_random_int_range(1, 1000), 1);
410 gnc_sx_randomize_variables(GHashTable *vars)
412 g_hash_table_foreach(vars, (GHFunc)_set_var_to_random_value, NULL);
416 _clone_sx_var_hash_entry(gpointer key, gpointer value, gpointer user_data)
418 GHashTable *to = (GHashTable*)user_data;
421 g_hash_table_insert(to, g_strdup(key), var);
425 gnc_sx_instance_new(
GncSxInstances *parent, GncSxInstanceState state, GDate *date,
void *temporal_state, gint sequence_num)
431 g_date_clear(&rtn->
date, 1);
435 if (! parent->variable_names_parsed)
437 parent->variable_names = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)gnc_sx_variable_free);
438 gnc_sx_get_variables(parent->sx, parent->variable_names);
439 g_hash_table_foreach(parent->variable_names, (GHFunc)_wipe_parsed_sx_var, NULL);
440 parent->variable_names_parsed = TRUE;
443 rtn->
variable_bindings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)gnc_sx_variable_free);
444 g_hash_table_foreach(parent->variable_names, _clone_sx_var_hash_entry, rtn->
variable_bindings);
447 int instance_i_value;
452 i_num = gnc_numeric_create(instance_i_value, 1);
453 as_var = gnc_sx_variable_new_full(
"i", i_num, FALSE);
462 _compare_GncSxVariables(gconstpointer a, gconstpointer b)
468 _build_list_from_hash_elts(gpointer key, gpointer value, gpointer user_data)
470 GList **list = (GList**)user_data;
471 *list = g_list_prepend (*list, value);
478 g_hash_table_foreach(inst->
variable_bindings, _build_list_from_hash_elts, &vars);
479 return g_list_sort (vars, _compare_GncSxVariables);
483 _gnc_sx_gen_instances(gpointer *data, gpointer user_data)
486 GList *instlist = NULL;
487 SchedXaction *sx = (SchedXaction*)data;
488 const GDate *range_end = (
const GDate*)user_data;
489 GDate creation_end, remind_end;
495 creation_end = *range_end;
496 g_date_add_days(&creation_end, xaccSchedXactionGetAdvanceCreation(sx));
497 remind_end = creation_end;
498 g_date_add_days(&remind_end, xaccSchedXactionGetAdvanceReminder(sx));
503 for ( ; postponed != NULL; postponed = postponed->next)
509 g_date_clear(&inst_date, 1);
512 inst = gnc_sx_instance_new(instances, SX_INSTANCE_STATE_POSTPONED,
513 &inst_date, postponed->data, seq_num);
514 instlist = g_list_prepend (instlist, inst);
522 g_date_clear(&cur_date, 1);
524 instances->next_instance_date = cur_date;
525 while (g_date_valid(&cur_date) && g_date_compare(&cur_date, &creation_end) <= 0)
530 inst = gnc_sx_instance_new(instances, SX_INSTANCE_STATE_TO_CREATE,
531 &cur_date, temporal_state, seq_num);
532 instlist = g_list_prepend (instlist, inst);
538 while (g_date_valid(&cur_date) &&
539 g_date_compare(&cur_date, &remind_end) <= 0)
544 inst = gnc_sx_instance_new(instances, SX_INSTANCE_STATE_REMINDER,
545 &cur_date, temporal_state, seq_num);
546 instlist = g_list_prepend (instlist, inst);
559 sx_gen_select_instances(gpointer *data, gpointer user_data)
561 GncSxInstances *instances = _gnc_sx_gen_instances(data, user_data);
564 if (instlist == NULL)
566 SchedXaction *sx = instances->sx;
570 if (g_date_valid(&cur_date))
573 GncSxInstance *inst = gnc_sx_instance_new(instances, SX_INSTANCE_STATE_REMINDER,
574 &cur_date, temporal_state, seq_num);
586 sx_instances(GncSxInstanceModel *model, SchedXaction *sx)
588 return model->include_disabled ?
589 sx_gen_select_instances((gpointer)sx, (gpointer)&model->range_end) :
590 _gnc_sx_gen_instances((gpointer)sx, (gpointer)&model->range_end);
597 g_date_clear(&now, 1);
605 GList *all_sxes = gnc_book_get_schedxactions(gnc_get_current_book())->sx_list;
606 GncSxInstanceModel *instances;
608 g_assert(range_end != NULL);
609 g_assert(g_date_valid(range_end));
611 instances = gnc_sx_instance_model_new();
612 instances->include_disabled = include_disabled;
613 instances->range_end = *range_end;
615 if (include_disabled)
617 instances->sx_instance_list =
gnc_g_list_map(all_sxes, (GncGMapFunc)_gnc_sx_gen_instances, (gpointer)range_end);
621 GList *sx_iter = g_list_first(all_sxes);
622 GList *enabled_sxes = NULL;
624 for (; sx_iter != NULL; sx_iter = sx_iter->next)
626 SchedXaction *sx = (SchedXaction*)sx_iter->data;
627 if (xaccSchedXactionGetEnabled(sx))
629 enabled_sxes = g_list_prepend (enabled_sxes, sx);
632 enabled_sxes = g_list_reverse (enabled_sxes);
633 instances->sx_instance_list =
gnc_g_list_map(enabled_sxes, (GncGMapFunc)_gnc_sx_gen_instances, (gpointer)range_end);
634 g_list_free(enabled_sxes);
643 GncSxInstanceModel *instances;
646 g_date_clear(&now, 1);
649 instances = gnc_sx_instance_model_new();
650 instances->include_disabled = TRUE;
651 instances->range_end = now;
653 instances->sx_instance_list =
gnc_g_list_map(sel_sxes, (GncGMapFunc)sx_gen_select_instances, (gpointer)&now);
658 G_DEFINE_TYPE (GncSxInstanceModel, gnc_sx_instance_model, G_TYPE_OBJECT)
660 static GncSxInstanceModel*
661 gnc_sx_instance_model_new(
void)
663 return GNC_SX_INSTANCE_MODEL(g_object_new(GNC_TYPE_SX_INSTANCE_MODEL, NULL));
667 gnc_sx_instance_model_dispose(GObject *
object)
669 GncSxInstanceModel *model;
670 g_return_if_fail(
object != NULL);
671 model = GNC_SX_INSTANCE_MODEL(
object);
673 g_return_if_fail(!model->disposed);
674 model->disposed = TRUE;
678 G_OBJECT_CLASS(gnc_sx_instance_model_parent_class)->dispose(
object);
698 GList *instance_iter;
706 instances->sx = NULL;
708 for (instance_iter = instances->
instance_list; instance_iter != NULL; instance_iter = instance_iter->next)
711 gnc_sx_instance_free(inst);
720 gnc_sx_instance_model_finalize (GObject *
object)
722 GncSxInstanceModel *model;
725 g_return_if_fail(
object != NULL);
727 model = GNC_SX_INSTANCE_MODEL(
object);
728 for (sx_list_iter = model->sx_instance_list; sx_list_iter != NULL; sx_list_iter = sx_list_iter->next)
731 gnc_sx_instances_free(instances);
733 g_list_free(model->sx_instance_list);
734 model->sx_instance_list = NULL;
736 G_OBJECT_CLASS(gnc_sx_instance_model_parent_class)->finalize(
object);
740 gnc_sx_instance_model_class_init (GncSxInstanceModelClass *klass)
742 GObjectClass *object_class = G_OBJECT_CLASS(klass);
744 object_class->dispose = gnc_sx_instance_model_dispose;
745 object_class->finalize = gnc_sx_instance_model_finalize;
748 g_signal_new(
"removing",
749 GNC_TYPE_SX_INSTANCE_MODEL,
754 g_cclosure_marshal_VOID__POINTER,
760 g_signal_new(
"updated",
761 GNC_TYPE_SX_INSTANCE_MODEL,
766 g_cclosure_marshal_VOID__POINTER,
772 g_signal_new(
"added",
773 GNC_TYPE_SX_INSTANCE_MODEL,
778 g_cclosure_marshal_VOID__POINTER,
785 gnc_sx_instance_model_init(GncSxInstanceModel *inst)
787 g_date_clear(&inst->range_end, 1);
788 inst->sx_instance_list = NULL;
793 _gnc_sx_instance_find_by_sx(
GncSxInstances *in_list_instances, SchedXaction *sx_to_find)
795 if (in_list_instances->sx == sx_to_find)
801 _gnc_sx_instance_event_handler(
QofInstance *ent,
QofEventId event_type, gpointer user_data, gpointer evt_data)
803 GncSxInstanceModel *instances = GNC_SX_INSTANCE_MODEL(user_data);
810 if (!(GNC_IS_SX(ent) || GNC_IS_SXES(ent)))
816 gboolean sx_is_in_model = FALSE;
820 sx_is_in_model = (g_list_find_custom(instances->sx_instance_list, sx, (GCompareFunc)_gnc_sx_instance_find_by_sx) != NULL);
821 if (event_type & QOF_EVENT_MODIFY)
825 if (instances->include_disabled || xaccSchedXactionGetEnabled(sx))
827 g_signal_emit_by_name(instances,
"updated", (gpointer)sx);
832 g_signal_emit_by_name(instances,
"removing", (gpointer)sx);
838 GList *all_sxes = gnc_book_get_schedxactions(gnc_get_current_book())->sx_list;
839 if (g_list_find(all_sxes, sx) && (!instances->include_disabled && xaccSchedXactionGetEnabled(sx)))
842 instances->sx_instance_list = g_list_append(instances->sx_instance_list, sx_instances(instances, sx));
843 g_signal_emit_by_name(instances,
"added", (gpointer)sx);
849 else if (GNC_IS_SXES(ent))
851 SchedXaction *sx = GNC_SX(evt_data);
853 if (event_type & GNC_EVENT_ITEM_REMOVED)
855 GList *instances_link;
856 instances_link = g_list_find_custom(instances->sx_instance_list, sx, (GCompareFunc)_gnc_sx_instance_find_by_sx);
857 if (instances_link != NULL)
859 g_signal_emit_by_name(instances,
"removing", (gpointer)sx);
861 else if (instances->include_disabled)
863 g_warning(
"could not remove instances that do not exist in the model");
868 if (instances->include_disabled || xaccSchedXactionGetEnabled(sx))
871 instances->sx_instance_list = g_list_append(instances->sx_instance_list, sx_instances(instances, sx));
872 g_signal_emit_by_name(instances,
"added", (gpointer)sx);
879 typedef struct _HashListPair
886 _find_unreferenced_vars(gchar *key,
890 if (cb_pair->hash == NULL ||
891 !g_hash_table_lookup_extended(cb_pair->hash, key, NULL, NULL))
893 DEBUG(
"variable [%s] not found", key);
894 cb_pair->list = g_list_prepend (cb_pair->list, key);
904 link = g_list_find_custom(model->sx_instance_list, sx, (GCompareFunc)_gnc_sx_instance_find_by_sx);
907 g_critical(
"couldn't find sx [%p]\n", sx);
913 new_instances = sx_instances(model, sx);
914 existing->sx = new_instances->sx;
915 existing->next_instance_date = new_instances->next_instance_date;
917 GList *existing_iter, *new_iter;
918 gboolean existing_remain, new_remain;
925 for (; existing_iter != NULL && new_iter != NULL; existing_iter = existing_iter->next, new_iter = new_iter->next)
928 gboolean same_instance_date;
932 same_instance_date = g_date_compare(&existing_inst->
date, &new_inst->
date) == 0;
933 if (!same_instance_date)
937 existing_remain = (existing_iter != NULL);
938 new_remain = (new_iter != NULL);
944 g_list_foreach(existing_iter, (GFunc)gnc_sx_instance_free, NULL);
950 GList *new_iter_iter;
953 for (new_iter_iter = new_iter; new_iter_iter != NULL; new_iter_iter = new_iter_iter->next)
959 g_list_free(new_iter);
965 GList *removed_var_names = NULL, *added_var_names = NULL;
966 GList *inst_iter = NULL;
972 removed_cb_data.list = NULL;
973 g_hash_table_foreach(existing->
variable_names, (GHFunc)_find_unreferenced_vars, &removed_cb_data);
974 removed_var_names = g_list_reverse (removed_cb_data.list);
976 DEBUG(
"%d removed variables", g_list_length(removed_var_names));
982 added_cb_data.list = NULL;
983 g_hash_table_foreach(new_instances->
variable_names, (GHFunc)_find_unreferenced_vars, &added_cb_data);
984 added_var_names = g_list_reverse (added_cb_data.list);
986 DEBUG(
"%d added variables", g_list_length(added_var_names));
995 for (inst_iter = existing->
instance_list; inst_iter != NULL; inst_iter = inst_iter->next)
1000 for (var_iter = removed_var_names; var_iter != NULL; var_iter = var_iter->next)
1002 gchar *to_remove_key = (gchar*)var_iter->data;
1006 for (var_iter = added_var_names; var_iter != NULL; var_iter = var_iter->next)
1008 gchar *to_add_key = (gchar*)var_iter->data;
1009 if (!g_hash_table_lookup_extended(
1016 g_assert(parent_var != NULL);
1017 var_copy = gnc_sx_variable_new_copy(parent_var);
1023 gnc_sx_instances_free(new_instances);
1027 gnc_sx_instance_model_remove_sx_instances(GncSxInstanceModel *model, SchedXaction *sx)
1029 GList *instance_link = NULL;
1031 instance_link = g_list_find_custom(model->sx_instance_list, sx, (GCompareFunc)_gnc_sx_instance_find_by_sx);
1032 if (instance_link == NULL)
1034 g_warning(
"instance not found!\n");
1038 model->sx_instance_list = g_list_remove_link(model->sx_instance_list, instance_link);
1043 increment_sx_state(
GncSxInstance *inst, GDate **last_occur_date,
int *instance_count,
int *remain_occur_count)
1045 if (!g_date_valid(*last_occur_date)
1046 || (g_date_valid(*last_occur_date)
1047 && g_date_compare(*last_occur_date, &inst->
date) <= 0))
1049 *last_occur_date = &inst->
date;
1054 if (*remain_occur_count > 0)
1056 *remain_occur_count -= 1;
1061 _get_template_split_account(
const SchedXaction* sx,
1062 const Split *template_split,
1064 GList **creation_errors)
1066 gboolean success = TRUE;
1069 "sx-account", &acct_guid,
1072 if (!*split_acct && sx && creation_errors)
1077 gchar* err = N_(
"Unknown account for guid [%s], cancelling SX [%s] creation.");
1079 REPORT_ERROR(creation_errors, err, guid_str, xaccSchedXactionGetName(sx));
1083 guid_free (acct_guid);
1088 _get_sx_formula_value(
const SchedXaction* sx,
1089 const Split *template_split,
1091 GList **creation_errors,
1092 const char *formula_key,
1093 const char* numeric_key,
1094 GHashTable *variable_bindings)
1097 char *formula_str = NULL, *parseErrorLoc = NULL;
1098 gnc_numeric *numeric_val = NULL;
1100 formula_key, &formula_str,
1101 numeric_key, &numeric_val,
1104 if ((variable_bindings == NULL ||
1105 g_hash_table_size (variable_bindings) == 0) &&
1106 numeric_val != NULL &&
1113 numeric->num = numeric_val->num;
1114 numeric->denom = numeric_val->denom;
1115 g_free (formula_str);
1116 g_free (numeric_val);
1120 if (formula_str != NULL && strlen(formula_str) != 0)
1122 GHashTable *parser_vars = NULL;
1123 if (variable_bindings)
1127 if (!gnc_exp_parser_parse_separate_vars(formula_str,
1132 gchar *err = N_(
"Error parsing SX [%s] key [%s]=formula [%s] at [%s]: %s.");
1133 REPORT_ERROR(creation_errors, err,
1134 xaccSchedXactionGetName(sx),
1138 gnc_exp_parser_error_string());
1141 if (parser_vars != NULL)
1143 g_hash_table_destroy(parser_vars);
1146 g_free (formula_str);
1147 g_free (numeric_val);
1152 const Split *template_split, gnc_numeric *credit_num,
1153 GList **creation_errors)
1155 _get_sx_formula_value(instance->
parent->sx, template_split, credit_num,
1156 creation_errors,
"sx-credit-formula",
1161 _get_debit_formula_value(
GncSxInstance *instance,
const Split *template_split,
1162 gnc_numeric *debit_num, GList **creation_errors)
1164 _get_sx_formula_value(instance->
parent->sx, template_split, debit_num,
1165 creation_errors,
"sx-debit-formula",
1172 gnc_numeric credit_num = gnc_numeric_zero();
1173 gnc_numeric debit_num = gnc_numeric_zero();
1176 SchedXaction *sx = creation_data->instance->
parent->sx;
1178 _get_credit_formula_value(creation_data->instance, split, &credit_num,
1179 creation_data->creation_errors);
1180 _get_debit_formula_value(creation_data->instance, split, &debit_num,
1181 creation_data->creation_errors);
1183 final = gnc_numeric_sub_fixed(debit_num, credit_num);
1188 gchar *err = N_(
"Error %d in SX [%s] final gnc_numeric value, using 0 instead.");
1189 REPORT_ERROR(creation_data->creation_errors, err,
1190 gncn_error, xaccSchedXactionGetName(sx));
1191 final = gnc_numeric_zero();
1197 split_apply_exchange_rate (Split *split, GHashTable *bindings,
1198 gnc_commodity *txn_cmdty,
1199 gnc_commodity *split_cmdty, gnc_numeric *
final)
1201 gchar *exchange_rate_var_name;
1204 gnc_numeric exchange_rate = gnc_numeric_create (1, 1);
1206 exchange_rate_var_name = var_name_from_commodities(split_cmdty, txn_cmdty);
1209 exchange_rate_var_name);
1211 if (exchange_rate_var != NULL)
1213 exchange_rate = exchange_rate_var->
value;
1216 g_free (exchange_rate_var_name);
1245 static gnc_commodity*
1247 SchedXaction *sx, Transaction *template_txn)
1249 gnc_commodity *first_currency = NULL, *first_cmdty = NULL,
1250 *fallback_cmdty = NULL;
1251 gboolean err_flag = FALSE, txn_cmdty_in_splits = FALSE;
1254 GList** creation_errors =
1255 creation_data ? creation_data->creation_errors : NULL;
1258 DEBUG(
"Template txn currency is %s.",
1261 DEBUG(
"No template txn currency.");
1263 for (;txn_splits; txn_splits = txn_splits->next)
1265 Split* t_split = (Split*)txn_splits->data;
1266 Account* split_account = NULL;
1267 gnc_commodity *split_cmdty = NULL;
1269 if (!_get_template_split_account(sx, t_split, &split_account,
1278 if (!fallback_cmdty)
1281 if (split_is_marker(t_split))
1286 txn_cmdty = split_cmdty;
1288 first_cmdty = split_cmdty;
1290 txn_cmdty_in_splits = TRUE;
1292 first_currency = split_cmdty;
1296 g_critical(
"Error in SX transaction [%s], split missing account: " 1297 "Creation aborted.", xaccSchedXactionGetName(sx));
1300 if (first_currency &&
1302 return first_currency;
1303 if (!txn_cmdty_in_splits && first_cmdty)
1307 return fallback_cmdty;
1311 create_each_transaction_helper(Transaction *template_txn,
void *user_data)
1313 Transaction *new_txn;
1314 GList *txn_splits, *template_splits;
1315 Split *copying_split;
1317 SchedXaction *sx = creation_data->instance->
parent->sx;
1318 gnc_commodity *txn_cmdty = get_transaction_currency (creation_data,
1322 if (txn_cmdty == NULL)
1332 DEBUG(
"creating template txn desc [%s] for sx [%s]",
1334 xaccSchedXactionGetName(sx));
1342 g_date_get_day(&creation_data->instance->
date),
1343 g_date_get_month(&creation_data->instance->
date),
1344 g_date_get_year(&creation_data->instance->
date));
1349 if ((template_splits == NULL) || (txn_splits == NULL))
1351 g_critical(
"transaction w/o splits for sx [%s]",
1352 xaccSchedXactionGetName(sx));
1358 if (txn_cmdty == NULL)
1367 txn_splits && template_splits;
1368 txn_splits = txn_splits->next, template_splits = template_splits->next)
1370 const Split *template_split;
1372 gnc_commodity *split_cmdty = NULL;
1377 template_split = (Split*)template_splits->data;
1378 copying_split = (Split*)txn_splits->data;
1380 _get_template_split_account(sx, template_split, &split_acct,
1381 creation_data->creation_errors);
1384 xaccSplitSetAccount(copying_split, split_acct);
1387 gnc_numeric
final = split_apply_formulas(template_split,
1390 DEBUG(
"value is %s for memo split '%s'",
1395 split_apply_exchange_rate(copying_split,
1397 txn_cmdty, split_cmdty, &
final);
1407 "from-sched-xaction",
1414 if (creation_data->created_txn_guids != NULL)
1416 *creation_data->created_txn_guids
1417 = g_list_append(*(creation_data->created_txn_guids),
1425 create_transactions_for_instance(
GncSxInstance *instance, GList **created_txn_guids, GList **creation_errors)
1430 sx_template_account = gnc_sx_get_template_transaction_account(instance->
parent->sx);
1432 creation_data.instance = instance;
1433 creation_data.created_txn_guids = created_txn_guids;
1434 creation_data.creation_errors = creation_errors;
1440 create_each_transaction_helper,
1447 gboolean auto_create_only,
1448 GList **created_transaction_guids,
1449 GList **creation_errors)
1459 for (iter = model->sx_instance_list; iter != NULL; iter = iter->next)
1461 GList *instance_iter;
1463 GDate *last_occur_date;
1464 gint instance_count = 0;
1465 gint remain_occur_count = 0;
1473 last_occur_date = (GDate*) xaccSchedXactionGetLastOccurDate(instances->sx);
1475 remain_occur_count = xaccSchedXactionGetRemOccur(instances->sx);
1477 for (instance_iter = instances->
instance_list; instance_iter != NULL; instance_iter = instance_iter->next)
1480 gboolean sx_is_auto_create;
1481 GList *instance_errors = NULL;
1483 xaccSchedXactionGetAutoCreate(inst->
parent->sx, &sx_is_auto_create, NULL);
1484 if (auto_create_only && !sx_is_auto_create)
1486 if (inst->
state != SX_INSTANCE_STATE_TO_CREATE)
1493 if (inst->
orig_state == SX_INSTANCE_STATE_POSTPONED
1494 && inst->
state != SX_INSTANCE_STATE_POSTPONED)
1502 switch (inst->
state)
1504 case SX_INSTANCE_STATE_CREATED:
1507 case SX_INSTANCE_STATE_IGNORED:
1508 increment_sx_state(inst, &last_occur_date, &instance_count, &remain_occur_count);
1510 case SX_INSTANCE_STATE_POSTPONED:
1511 if (inst->
orig_state != SX_INSTANCE_STATE_POSTPONED)
1516 increment_sx_state(inst, &last_occur_date, &instance_count, &remain_occur_count);
1518 case SX_INSTANCE_STATE_TO_CREATE:
1519 create_transactions_for_instance (inst,
1520 created_transaction_guids,
1522 if (instance_errors == NULL)
1524 increment_sx_state (inst, &last_occur_date,
1526 &remain_occur_count);
1528 (model, inst, SX_INSTANCE_STATE_CREATED);
1530 else if (creation_errors)
1532 *creation_errors = g_list_concat (*creation_errors,
1534 instance_errors = NULL;
1537 case SX_INSTANCE_STATE_REMINDER:
1542 g_assert_not_reached();
1546 if (instance_errors)
1547 g_list_free_full (instance_errors, g_free);
1550 xaccSchedXactionSetLastOccurDate(instances->sx, last_occur_date);
1552 xaccSchedXactionSetRemOccur(instances->sx, remain_occur_count);
1559 GncSxInstanceState new_state)
1561 if (instance->
state == new_state)
1564 instance->
state = new_state;
1570 g_assert(inst_iter != NULL);
1571 if (instance->
state != SX_INSTANCE_STATE_REMINDER)
1574 for (inst_iter = inst_iter->prev; inst_iter != NULL; inst_iter = inst_iter->prev)
1577 if (prev_inst->
state != SX_INSTANCE_STATE_REMINDER)
1579 prev_inst->
state = SX_INSTANCE_STATE_POSTPONED;
1585 for (inst_iter = inst_iter->next; inst_iter != NULL; inst_iter = inst_iter->next)
1588 if (next_inst->
state == SX_INSTANCE_STATE_REMINDER)
1590 next_inst->
state = SX_INSTANCE_STATE_REMINDER;
1595 g_signal_emit_by_name(model,
"updated", (gpointer)instance->
parent->sx);
1599 gnc_sx_instance_model_set_variable(GncSxInstanceModel *model,
1602 gnc_numeric *new_value)
1607 variable->
value = *new_value;
1608 g_signal_emit_by_name(model,
"updated", (gpointer)instance->
parent->sx);
1612 _list_from_hash_elts(gpointer key, gpointer value, GList **result_list)
1614 *result_list = g_list_prepend (*result_list, value);
1621 GList *sx_iter, *inst_iter, *var_list = NULL, *var_iter;
1623 for (sx_iter = model->sx_instance_list; sx_iter != NULL; sx_iter = sx_iter->next)
1626 for (inst_iter = instances->
instance_list; inst_iter != NULL; inst_iter = inst_iter->next)
1630 if (inst->
state != SX_INSTANCE_STATE_TO_CREATE)
1633 g_hash_table_foreach(inst->
variable_bindings, (GHFunc)_list_from_hash_elts, &var_list);
1634 for (var_iter = var_list; var_iter != NULL; var_iter = var_iter->next)
1640 need->instance = inst;
1641 need->variable = var;
1642 rtn = g_list_prepend (rtn, need);
1645 g_list_free(var_list);
1655 GList *sx_iter, *inst_iter;
1657 g_return_if_fail(model != NULL);
1658 g_return_if_fail(summary != NULL);
1666 for (sx_iter = model->sx_instance_list; sx_iter != NULL; sx_iter = sx_iter->next)
1669 gboolean sx_is_auto_create = FALSE, sx_notify = FALSE;
1670 xaccSchedXactionGetAutoCreate(instances->sx, &sx_is_auto_create, &sx_notify);
1671 for (inst_iter = instances->
instance_list; inst_iter != NULL; inst_iter = inst_iter->next)
1676 if (inst->
state == SX_INSTANCE_STATE_TO_CREATE)
1678 if (sx_is_auto_create)
1714 static void gnc_numeric_free(gpointer data)
1716 gnc_numeric *p = (gnc_numeric*) data;
1723 NULL, gnc_numeric_free);
1729 GList **creation_errors;
1730 const SchedXaction *sx;
1734 static void add_to_hash_amount(GHashTable* hash,
const GncGUID* guid,
const gnc_numeric* amount)
1739 gnc_numeric* elem = g_hash_table_lookup(hash, guid);
1744 elem = g_new0(gnc_numeric, 1);
1745 *elem = gnc_numeric_zero();
1746 g_hash_table_insert(hash, (gpointer) guid, elem);
1752 g_critical(
"Oops, the given amount [%s] has the error code %d, at guid [%s].",
1760 g_critical(
"Oops, the account's amount [%s] has the error code %d, at guid [%s].",
1778 g_critical(
"Oops, after addition at guid [%s] the resulting amount [%s] has the error code %d; added amount = [%s].",
1787 DEBUG(
"Adding to guid [%s] the value [%s]. Value now [%s].",
1794 create_cashflow_helper(Transaction *template_txn,
void *user_data)
1797 GList *template_splits;
1798 const gnc_commodity *first_cmdty = NULL;
1800 DEBUG(
"Evaluating txn desc [%s] for sx [%s]",
1802 xaccSchedXactionGetName(creation_data->sx));
1806 if (template_splits == NULL)
1808 g_critical(
"transaction w/o splits for sx [%s]",
1809 xaccSchedXactionGetName(creation_data->sx));
1815 template_splits = template_splits->next)
1818 const gnc_commodity *split_cmdty = NULL;
1819 const Split *template_split = (
const Split*) template_splits->data;
1822 if (!_get_template_split_account(creation_data->sx, template_split, &split_acct, creation_data->creation_errors))
1824 DEBUG(
"Could not find account for split");
1830 if (first_cmdty == NULL)
1832 first_cmdty = split_cmdty;
1837 gnc_numeric credit_num = gnc_numeric_zero();
1838 gnc_numeric debit_num = gnc_numeric_zero();
1839 gnc_numeric final_once,
final;
1843 _get_sx_formula_value(creation_data->sx, template_split,
1844 &credit_num, creation_data->creation_errors,
1845 "sx-credit-formula",
"sx-credit-numeric",
1848 _get_sx_formula_value(creation_data->sx, template_split,
1849 &debit_num, creation_data->creation_errors,
1850 "sx-debit-formula",
"sx-debit-numeric", NULL);
1854 final_once = gnc_numeric_sub_fixed( debit_num, credit_num );
1857 gnc_numeric_denom(final_once),
1863 gchar* err = N_(
"Error %d in SX [%s] final gnc_numeric value, using 0 instead.");
1864 REPORT_ERROR(creation_data->creation_errors, err,
1865 gncn_error, xaccSchedXactionGetName(creation_data->sx));
1866 final = gnc_numeric_zero();
1872 gchar *err = N_(
"No exchange rate available in SX [%s] for %s -> %s, value is zero.");
1873 REPORT_ERROR(creation_data->creation_errors, err,
1874 xaccSchedXactionGetName(creation_data->sx),
1877 final = gnc_numeric_zero();
1889 instantiate_cashflow_internal(
const SchedXaction* sx,
1891 GList **creation_errors, gint count)
1894 Account* sx_template_account = gnc_sx_get_template_transaction_account(sx);
1896 if (!sx_template_account)
1898 g_critical(
"Huh? No template account for the SX %s", xaccSchedXactionGetName(sx));
1902 if (!xaccSchedXactionGetEnabled(sx))
1904 DEBUG(
"Skipping non-enabled SX [%s]",
1905 xaccSchedXactionGetName(sx));
1909 create_cashflow_data.hash = map;
1910 create_cashflow_data.creation_errors = creation_errors;
1911 create_cashflow_data.sx = sx;
1912 create_cashflow_data.count = gnc_numeric_create(count, 1);
1917 create_cashflow_helper,
1918 &create_cashflow_data);
1924 GList **creation_errors;
1925 const GDate *range_start;
1926 const GDate *range_end;
1929 static void instantiate_cashflow_cb(gpointer data, gpointer _user_data)
1931 const SchedXaction* sx = (
const SchedXaction*) data;
1940 userdata->range_end);
1946 instantiate_cashflow_internal(sx,
1948 userdata->creation_errors,
1954 const GDate *range_start,
const GDate *range_end,
1955 GHashTable* map, GList **creation_errors)
1958 userdata.hash = map;
1959 userdata.creation_errors = creation_errors;
1960 userdata.range_start = range_start;
1961 userdata.range_end = range_end;
1964 g_list_foreach(all_sxes, instantiate_cashflow_cb, &userdata);
1971 GList *all_sxes = gnc_book_get_schedxactions(gnc_get_current_book())->sx_list;
1973 &range_start, &range_end,
1980 return model->sx_instance_list;
void xaccSplitSetValue(Split *split, gnc_numeric val)
The xaccSplitSetValue() method sets the value of this split in the transaction's commodity.
Never round at all, and signal an error if there is a fractional result in a computation.
GHashTable * variable_bindings
variable bindings.
gint xaccAccountForEachTransaction(const Account *acc, TransactionCallback proc, void *data)
The xaccAccountForEachTransaction() routine will traverse all of the transactions in account and call...
GList * gnc_g_list_map(GList *list, GncGMapFunc fn, gpointer user_data)
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b represent the same number.
GHashTable * gnc_g_hash_new_guid_numeric(void)
Returns a GHashTable<GUID*, gnc_numeric*> with no destructor for the key, but a destructor for the va...
void gnc_sx_set_instance_count(SchedXaction *sx, gint instance_num)
Sets the instance count to something other than the default.
SXTmpStateData * temporal_state
the sx creation temporal state.
gboolean gnc_commodity_is_currency(const gnc_commodity *cm)
Checks to see if the specified commodity is an ISO 4217 recognized currency or a legacy currency...
gchar * gnc_num_dbg_to_string(gnc_numeric n)
Convert to string.
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
GHashTable * variable_names
<name:char*,GncSxVariable*>
void qof_instance_get(const QofInstance *inst, const gchar *first_prop,...)
Wrapper for g_object_get.
Date and Time handling routines.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
void gnc_sx_scrub_split_numerics(gpointer psplit, gpointer user)
Fix up numerics where they've gotten out-of-sync with the formulas.
void gnc_sx_instance_model_change_instance_state(GncSxInstanceModel *model, GncSxInstance *instance, GncSxInstanceState new_state)
There is a constraint around a sequence of upcoming instance states.
GHashTable * gnc_sx_all_instantiate_cashflow_all(GDate range_start, GDate range_end)
Simplified wrapper around gnc_sx_all_instantiate_cashflow(): Run that function on all SX of the curre...
void gnc_sx_destroy_temporal_state(SXTmpStateData *tsd)
Frees the given stateDate object.
utility functions for the GnuCash UI
#define G_LOG_DOMAIN
Functions providing the SX List as a plugin page.
#define PINFO(format, args...)
Print an informational note.
gint num_auto_create_no_notify_instances
The number of automatically-created instances that do no request notification.
void xaccTransSetNotes(Transaction *trans, const char *notes)
Sets the transaction Notes.
SXTmpStateData * gnc_sx_create_temporal_state(const SchedXaction *sx)
Allocates a new SXTmpStateData object and fills it with the current state of the given sx...
#define DEBUG(format, args...)
Print a debugging message.
void qof_instance_set(QofInstance *inst, const gchar *first_prop,...)
Wrapper for g_object_set Group setting multiple parameters in a single begin/commit/rollback.
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
This routine returns TRUE if the two commodities are equal.
GncSxInstanceState orig_state
the original state at generation time.
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Return a+b.
GHashTable * gnc_sx_instance_get_variables_for_parser(GHashTable *instance_var_hash)
void gnc_sx_instance_model_summarize(GncSxInstanceModel *model, GncSxSummary *summary)
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
void gnc_sx_instance_model_update_sx_instances(GncSxInstanceModel *model, SchedXaction *sx)
Regenerates and updates the GncSxInstances* for the given SX.
Account * gnc_book_get_template_root(const QofBook *book)
Returns the template group from the book.
void gnc_sx_instance_model_effect_change(GncSxInstanceModel *model, gboolean auto_create_only, GList **created_transaction_guids, GList **creation_errors)
Really ("effectively") create the transactions from the SX instances in the given model...
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
API for Transactions and Splits (journal entries)
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
Just the variable temporal bits from the SX structure.
guint guid_hash_to_guint(gconstpointer ptr)
Hash function for a GUID.
gint num_to_create_instances
The number of (not-auto-create) to-create instances.
gint num_instances
The number of total instances (in any state).
GDate xaccSchedXactionGetNextInstance(const SchedXaction *sx, SXTmpStateData *tsd)
Returns the next occurrence of a scheduled transaction.
void gnc_sx_summary_print(const GncSxSummary *summary)
Debug output to trace file.
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Set a new currency on a transaction.
void xaccTransDestroy(Transaction *trans)
Destroys a transaction.
gint qof_event_register_handler(QofEventHandler handler, gpointer user_data)
Register a handler for events.
Account * gnc_account_lookup_by_name(const Account *parent, const char *name)
The gnc_account_lookup_by_name() subroutine fetches the account by name from the descendants of the s...
const char * xaccTransGetNotes(const Transaction *trans)
Gets the transaction Notes.
#define xaccAccountGetGUID(X)
convert single-entry accounts to clean double-entry
void xaccSplitSetAmount(Split *split, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account's commodity that the split should have...
void gnc_sx_incr_temporal_state(const SchedXaction *sx, SXTmpStateData *tsd)
Calculates the next occurrence of the given SX and stores that occurrence in the remporalStateDate.
Account handling public routines.
GncSxInstances * parent
the parent instances collection.
gint QofEventId
Define the type of events allowed.
Reduce the result value by common factor elimination, using the smallest possible value for the denom...
gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Multiply a times b, returning the product.
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
gnc_numeric gnc_numeric_error(GNCNumericErrorCode error_code)
Create a gnc_numeric object that signals the error condition noted by error_code, rather than a numbe...
void xaccSplitScrub(Split *split)
The xaccSplitScrub method ensures that if this split has the same commodity and currency, then it will have the same amount and value.
void gnc_sx_add_defer_instance(SchedXaction *sx, void *deferStateData)
Adds an instance to the deferred list of the SX.
Anchor Scheduled Transaction info in a book.
Transaction * xaccTransCloneNoKvp(const Transaction *from)
The xaccTransCloneNoKvp() method will create a complete copy of an existing transaction except that ...
void qof_event_unregister_handler(gint handler_id)
Unregister an event handler.
gint gnc_sx_get_num_occur_daterange(const SchedXaction *sx, const GDate *start_date, const GDate *end_date)
Calculates and returns the number of occurrences of the given SX in the given date range (inclusive)...
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
Argument is not a valid number.
void gnc_g_list_cut(GList **list, GList *cut_point)
Cut a GList into two parts; the cut_point is the beginning of the new list; list may need to be modif...
SXTmpStateData * gnc_sx_clone_temporal_state(SXTmpStateData *tsd)
Allocates and returns a one-by-one copy of the given temporal state.
void xaccTransSetDate(Transaction *trans, int day, int mon, int year)
The xaccTransSetDate() method does the same thing as xaccTransSetDate[Posted]Secs(), but takes a convenient day-month-year format.
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
Additional event handling code.
gnc_numeric gnc_numeric_div(gnc_numeric x, gnc_numeric y, gint64 denom, gint how)
Division.
gint num_auto_create_instances
The total number of auto-create instances.
GDate date
the instance date.
#define xaccSchedXactionGetGUID(X)
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
gboolean gnc_numeric_eq(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b are exactly the same (have the same numerator and ...
void gnc_sx_all_instantiate_cashflow(GList *all_sxes, const GDate *range_start, const GDate *range_end, GHashTable *map, GList **creation_errors)
Instantiates the cash flow of all given SXs (in the given GList<SchedXAction*>) into the GHashTable<G...
GList * gnc_sx_instance_get_variables(GncSxInstance *inst)
#define xaccTransGetGUID(X)
GncSxInstanceModel * gnc_sx_get_select_instances(GList *sel_sxes)
Allocates a new SxInstanceModel and fills it with generated instances for the given scheduled transac...
GList * gnc_sx_instance_model_get_sx_instances_list(GncSxInstanceModel *model)
Returns the list of GncSxInstances in the model (Each element in the list has type GncSxInstances) ...
gboolean qof_book_is_readonly(const QofBook *book)
Return whether the book is read only.
GncSxInstanceModel * gnc_sx_get_instances(const GDate *range_end, gboolean include_disabled)
Allocates a new SxInstanceModel and fills it with generated instances for all scheduled transactions ...
void qof_event_suspend(void)
Suspend all engine events.
void gnc_gdate_set_time64(GDate *gd, time64 time)
Set a GDate to a time64.
gnc_numeric value
only numeric values are supported.
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity.
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Returns the valuation commodity of this transaction.
void qof_event_resume(void)
Resume engine event generation.
GncSxInstanceState state
the current state of the instance (during editing)
GncSxInstanceModel * gnc_sx_get_current_instances(void)
Shorthand for get_instances(now, FALSE);.
void gnc_sx_remove_defer_instance(SchedXaction *sx, void *deferStateData)
Removes an instance from the deferred list.
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
time64 gnc_time(time64 *tbuf)
get the current time
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
Check for error signal in value.
const char * xaccSplitGetMemo(const Split *split)
Returns the memo string.
void xaccTransSetDateEnteredSecs(Transaction *trans, time64 secs)
Modify the date of when the transaction was entered.
GList * instance_list
GList<GncSxInstance*>
Scheduled Transactions public handling routines.
#define GNC_EVENT_ITEM_ADDED
These events are used when a split is added to an account.
#define GNC_DENOM_AUTO
Values that can be passed as the 'denom' argument.
API for Transactions and Splits (journal entries)
gboolean need_dialog
If the dialog needs to be displayed.
The type used to store guids in C.
SplitList * xaccTransGetSplitList(const Transaction *trans)
The xaccTransGetSplitList() method returns a GList of the splits in a transaction.
Commodity handling public routines.
gint guid_g_hash_table_equal(gconstpointer guid_a, gconstpointer guid_b)
Equality function for two GUIDs in a GHashTable.
GList * gnc_sx_instance_model_check_variables(GncSxInstanceModel *model)
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
The xaccAccountLookup() subroutine will return the account associated with the given id...
GList * gnc_sx_get_defer_instances(SchedXaction *sx)
Returns the defer list from the SX; this is a (date-)sorted temporal-state-data instance list...
gint gnc_sx_get_instance_count(const SchedXaction *sx, SXTmpStateData *stateData)
Get the instance count.