/** Balance the transaction by adding more trading splits. This shouldn't * ordinarily be necessary. * @param trans the transaction to balance * @param root the root account */ static void gnc_transaction_balance_trading_more_splits (Transaction *trans, Account *root) { /* Copy the split list so we don't see the splits we're adding */ GList *splits_dup = g_list_copy(trans->splits), *splits = NULL; const gnc_commodity *txn_curr = xaccTransGetCurrency (trans); for (splits = splits_dup; splits; splits = splits->next) { Split *split = splits->data; if (! xaccTransStillHasSplit(trans, split)) continue; if (!gnc_numeric_zero_p(xaccSplitGetValue(split)) && gnc_numeric_zero_p(xaccSplitGetAmount(split))) { gnc_commodity *commodity; gnc_numeric old_value, new_value; Split *balance_split; Account *account = NULL; commodity = xaccAccountGetCommodity(xaccSplitGetAccount(split)); if (!commodity) { PERR("Split has no commodity"); continue; } balance_split = get_trading_split(trans, root, commodity); if (!balance_split) { /* Error already logged */ LEAVE(""); return; } account = xaccSplitGetAccount(balance_split); xaccTransBeginEdit (trans); old_value = xaccSplitGetValue (balance_split); new_value = gnc_numeric_sub (old_value, xaccSplitGetValue(split), gnc_commodity_get_fraction(txn_curr), GNC_HOW_RND_ROUND_HALF_UP); xaccSplitSetValue (balance_split, new_value); /* Don't change the balance split's amount since the amount is zero in the split we're working on */ xaccSplitScrub (balance_split); xaccTransCommitEdit (trans); } } g_list_free(splits_dup); }
PaymentWindow * gnc_ui_payment_new_with_txn (GncOwner *owner, Transaction *txn) { SplitList *slist; Split *assetaccount_split; Split *postaccount_split; gnc_numeric amount; PaymentWindow *pw; if (!txn) return NULL; // We require the txn to have one split in an Asset account. slist = xaccTransGetSplitList(txn); if (!slist) return NULL; if (countAssetAccounts(slist) == 0) { g_message("No asset splits in txn \"%s\"; cannot use this for assigning a payment.", xaccTransGetDescription(txn)); return NULL; } assetaccount_split = getFirstAssetAccountSplit(slist); postaccount_split = getFirstAPARAccountSplit(slist); // watch out: Might be NULL amount = xaccSplitGetValue(assetaccount_split); pw = gnc_ui_payment_new(owner, qof_instance_get_book(QOF_INSTANCE(txn))); g_assert(assetaccount_split); // we can rely on this because of the countAssetAccounts() check above g_debug("Amount=%s", gnc_numeric_to_string(amount)); // Fill in the values from the given txn pw->pre_existing_txn = txn; gnc_ui_payment_window_set_num(pw, gnc_get_num_action(txn, assetaccount_split)); gnc_ui_payment_window_set_memo(pw, xaccTransGetDescription(txn)); { GDate txn_date = xaccTransGetDatePostedGDate (txn); gnc_ui_payment_window_set_date(pw, &txn_date); } gnc_ui_payment_window_set_amount(pw, amount); gnc_ui_payment_window_set_xferaccount(pw, xaccSplitGetAccount(assetaccount_split)); if (postaccount_split) gnc_ui_payment_window_set_postaccount(pw, xaccSplitGetAccount(postaccount_split)); return pw; }
static void run_test (void) { Account *act1; Account *act2; //Split *spl; QofSession *session; QofBook *book; session = qof_session_new (); book = qof_session_get_book (session); act1 = get_random_account(book); do_test(act1 != NULL, "random account created"); act2 = get_random_account(book); do_test(act2 != NULL, "random account created"); #if 0 spl = get_random_split(book, act1, NULL); do_test(spl != NULL, "random split created"); do_test(act1 == xaccSplitGetAccount(spl), "xaccAccountInsertSplit()"); #endif //FIXME //xaccSplitSetAccount (spl, NULL); //do_test(xaccSplitGetAccount(spl) == NULL, "xaccAccountRemoveSplit()"); }
// Account Name short or Long static gchar* add_account_name (gchar *so_far, Account *acc, Split *split, gboolean full, CsvExportInfo *info) { gchar *name = NULL; gchar *conv; gchar *result; Account *account = NULL; if (split == NULL) { if (acc == NULL) name = g_strdup (" "); else account = acc; } else account = xaccSplitGetAccount (split); if (account != NULL) { if (full) name = gnc_account_get_full_name (account); else name = g_strdup (xaccAccountGetName (account)); } conv = csv_txn_test_field_string (info, name); result = g_strconcat (so_far, conv, info->mid_sep, NULL); g_free (name); g_free (conv); g_free (so_far); return result; }
/* Is current split a security account */ static gboolean gtu_sr_use_security (GncTreeViewSplitReg *view) { RowDepth depth; Account *account = NULL; Split *split; split = gnc_tree_view_split_reg_get_current_split (view); depth = gnc_tree_view_reg_get_selected_row_depth (view); if (!split) return TRUE; if (depth != SPLIT3) return TRUE; if (!account) account = xaccSplitGetAccount (split); if (!account) return TRUE; if (xaccTransUseTradingAccounts (xaccSplitGetParent (split))) { if (!gnc_commodity_is_iso (xaccAccountGetCommodity (account))) return TRUE; } return xaccAccountIsPriced (account); }
gboolean gnc_tree_util_split_reg_needs_amount (GncTreeViewSplitReg *view, Split *split) { Transaction *txn = xaccSplitGetParent (split); Account *acc = xaccSplitGetAccount (split); return gnc_tree_util_split_reg_needs_conv_rate (view, txn, acc); }
gboolean gnc_split_register_split_needs_amount (SplitRegister *reg, Split *split) { Transaction *txn = xaccSplitGetParent (split); Account *acc = xaccSplitGetAccount (split); return gnc_split_register_needs_conv_rate (reg, txn, acc); }
// //////////////////////////////////////////////////////////// static void increment_if_asset_account (gpointer data, gpointer user_data) { int *r = user_data; const Split *split = data; const Account *account = xaccSplitGetAccount(split); if (xaccAccountIsAssetLiabType(xaccAccountGetType(account))) ++(*r); }
static gint predicate_is_apar_account(gconstpointer a, gconstpointer user_data) { const Split *split = a; const Account *account = xaccSplitGetAccount(split); if (xaccAccountIsAPARType(xaccAccountGetType(account))) return 0; else return -1; }
static gnc_numeric gnc_transaction_adjust_trading_splits (Transaction* trans, Account *root) { GList* splits; gnc_numeric imbalance = gnc_numeric_zero(); for (splits = trans->splits; splits; splits = splits->next) { Split *split = splits->data; Split *balance_split = NULL; gnc_numeric value, amount; gnc_commodity *commodity, *txn_curr = xaccTransGetCurrency (trans); if (! xaccTransStillHasSplit (trans, split)) continue; commodity = xaccAccountGetCommodity (xaccSplitGetAccount(split)); if (!commodity) { PERR("Split has no commodity"); continue; } balance_split = find_trading_split (trans, root, commodity); if (balance_split != split) /* this is not a trading split */ imbalance = gnc_numeric_add(imbalance, xaccSplitGetValue (split), GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT); /* Ignore splits where value or amount is zero */ value = xaccSplitGetValue (split); amount = xaccSplitGetAmount (split); if (gnc_numeric_zero_p(amount) || gnc_numeric_zero_p(value)) continue; if (balance_split && balance_split != split) { gnc_numeric convrate = gnc_numeric_div (amount, value, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE); gnc_numeric old_value, new_value; old_value = xaccSplitGetValue(balance_split); new_value = gnc_numeric_div (xaccSplitGetAmount(balance_split), convrate, gnc_commodity_get_fraction(txn_curr), GNC_HOW_RND_ROUND_HALF_UP); if (! gnc_numeric_equal (old_value, new_value)) { xaccTransBeginEdit (trans); xaccSplitSetValue (balance_split, new_value); xaccSplitScrub (balance_split); xaccTransCommitEdit (trans); } } } return imbalance; }
/* Returns the amount denom */ static int gtu_sr_get_amount_denom (Split *split) { int denom; denom = xaccAccountGetCommoditySCU (xaccSplitGetAccount (split)); if (denom == 0) { gnc_commodity *commodity = gnc_default_currency (); denom = gnc_commodity_get_fraction (commodity); if (denom == 0) denom = 100; } return denom; }
static void gnc_split_register_save_mxfrm_cell (BasicCell * cell, gpointer save_data, gpointer user_data) { SRSaveData *sd = save_data; SplitRegister *reg = user_data; Split * other_split; g_return_if_fail (gnc_basic_cell_has_name (cell, MXFRM_CELL)); other_split = xaccSplitGetOtherSplit (sd->split); /* other_split may be null for two very different reasons: * (1) the parent transaction has three or more splits in it, * and so the "other" split is ambiguous, and thus null. * (2) the parent transaction has only this one split as a child. * and "other" is null because there is no other. * * In the case (2), we want to create the other split, so that * the user's request to transfer actually works out. */ if (!other_split) { other_split = xaccTransGetSplit (sd->trans, 1); if (!other_split) { other_split = xaccMallocSplit (gnc_get_current_book ()); xaccTransAppendSplit (sd->trans, other_split); } } if (other_split) { Account *old_acc; Account *new_acc; /* Do some reparenting. Insertion into new account * will automatically delete from the old account. */ old_acc = xaccSplitGetAccount (other_split); new_acc = gnc_split_register_get_account (reg, MXFRM_CELL); if ((new_acc != NULL) && (old_acc != new_acc)) xaccAccountInsertSplit (new_acc, other_split); } }
void gnc_tree_util_split_reg_set_value_for (GncTreeViewSplitReg *view, Transaction *trans, Split *split, gnc_numeric input, gboolean force) { GncTreeModelSplitReg *model; GtkWidget *window; Account *anchor; Account *acct = xaccSplitGetAccount (split); gnc_commodity *currency; gnc_numeric value, amount, rate; ENTER("set_value_for trans %p and split %p input %s force %d", trans, split, gnc_numeric_to_string (input), force); currency = xaccTransGetCurrency (trans); model = gnc_tree_view_split_reg_get_model_from_view (view); anchor = gnc_tree_model_split_reg_get_anchor (model); if (gnc_numeric_zero_p (input)) { xaccSplitSetValue (split, input); xaccSplitSetAmount (split, input); LEAVE("input is zero"); return; } window = gnc_tree_view_split_reg_get_parent (view); if (gtu_sr_needs_exchange_rate (view, trans, split)) { if (gtu_sr_handle_exchange_rate (view, input, trans, split, force)) { ; //FIXME ?????? } else { gnc_error_dialog (window, "%s", _("Exchange Rate Canceled, using existing rate or default 1 to 1 rate if this is a new transaction.")); } LEAVE("used exchange rate"); return; } gnc_tree_util_split_reg_save_amount_values (view, trans, split, input); LEAVE(" "); }
static void merge_splits (Split *sa, Split *sb) { Account *act; Transaction *txn; gnc_numeric amt, val; act = xaccSplitGetAccount (sb); xaccAccountBeginEdit (act); txn = sa->parent; xaccTransBeginEdit (txn); /* Remove the guid of sb from the 'gemini' of sa */ remove_guids (sa, sb); /* Add amount of sb into sa, ditto for value. */ amt = xaccSplitGetAmount (sa); amt = gnc_numeric_add_fixed (amt, xaccSplitGetAmount (sb)); xaccSplitSetAmount (sa, amt); val = xaccSplitGetValue (sa); val = gnc_numeric_add_fixed (val, xaccSplitGetValue (sb)); xaccSplitSetValue (sa, val); /* Set reconcile to no; after this much violence, * no way its reconciled. */ xaccSplitSetReconcile (sa, NREC); /* If sb has associated gains splits, trash them. */ if ((sb->gains_split) && (sb->gains_split->gains & GAINS_STATUS_GAINS)) { Transaction *t = sb->gains_split->parent; xaccTransBeginEdit (t); xaccTransDestroy (t); xaccTransCommitEdit (t); } /* Finally, delete sb */ xaccSplitDestroy(sb); xaccTransCommitEdit (txn); xaccAccountCommitEdit (act); }
static xmlNodePtr find_appropriate_node (xmlNodePtr node, Split* spl) { xmlNodePtr mark; for (mark = node->xmlChildrenNode; mark; mark = mark->next) { gboolean account_guid_good = FALSE; gboolean amount_good = FALSE; xmlNodePtr mark2; for (mark2 = mark->xmlChildrenNode; mark2; mark2 = mark2->next) { if (g_strcmp0 ((char*)mark2->name, "split:value") == 0) { gnc_numeric* num = dom_tree_to_gnc_numeric (mark2); if (gnc_numeric_equal (*num, xaccSplitGetValue (spl))) { amount_good = TRUE; } g_free (num); } else if (g_strcmp0 ((char*)mark2->name, "split:account") == 0) { GncGUID* accid = dom_tree_to_guid (mark2); Account* account = xaccSplitGetAccount (spl); if (guid_equal (accid, xaccAccountGetGUID (account))) { account_guid_good = TRUE; } g_free (accid); } if (account_guid_good && amount_good) { return mark; } } } return NULL; }
// Commodity Namespace static gchar* add_comm_namespace (gchar *so_far, Transaction *trans, Split *split, CsvExportInfo *info) { const gchar *comm_n; gchar *conv; gchar *result; if (split == NULL) comm_n = gnc_commodity_get_namespace (xaccTransGetCurrency (trans)); else comm_n = gnc_commodity_get_namespace (xaccAccountGetCommodity (xaccSplitGetAccount(split))); conv = csv_txn_test_field_string (info, comm_n); result = g_strconcat (so_far, conv, info->mid_sep, NULL); g_free (conv); g_free (so_far); return result; }
/* Return the string entry for transfer column and if multi */ const char * gnc_tree_util_split_reg_get_transfer_entry (Split *split, gboolean *is_multi) { static char *name = NULL; gboolean multi = FALSE; Split *osplit; if (is_multi) *is_multi = multi; if (!split) return NULL; osplit = xaccSplitGetOtherSplit (split); g_free (name); if (osplit) name = gnc_get_account_name_for_register (xaccSplitGetAccount (osplit)); else { /* For multi-split transactions and stock splits, * use a special value. */ osplit = xaccTransGetSplit (xaccSplitGetParent (split), 1); if (osplit) { name = g_strdup (SPLIT_TRANS_STR); multi = TRUE; } else if (g_strcmp0 ("stock-split", xaccSplitGetType (split)) == 0) { name = g_strdup (STOCK_SPLIT_STR); multi = TRUE; } else name = g_strdup (""); } if (is_multi) *is_multi = multi; return name; }
/* OK, the handling of transfers gets complicated because it depends * on what was displayed to the user. For a multi-line display, we * just reparent the indicated split. For a two-line display, we want * to reparent the "other" split, but only if there is one. XFRM is * the straight split, MXFRM is the mirrored split. */ static void gnc_split_register_save_xfrm_cell (BasicCell * cell, gpointer save_data, gpointer user_data) { SRSaveData *sd = save_data; SplitRegister *reg = user_data; Account *old_acc; Account *new_acc; g_return_if_fail (gnc_basic_cell_has_name (cell, XFRM_CELL)); old_acc = xaccSplitGetAccount (sd->split); new_acc = gnc_split_register_get_account (reg, XFRM_CELL); if ((new_acc != NULL) && (old_acc != new_acc)) xaccAccountInsertSplit (new_acc, sd->split); }
static gnc_numeric gnc_transaction_get_commodity_imbalance (Transaction *trans, gnc_commodity *commodity) { /* Find the value imbalance in this commodity */ gnc_numeric val_imbalance = gnc_numeric_zero(); GList *splits = NULL; for (splits = trans->splits; splits; splits = splits->next) { Split *split = splits->data; gnc_commodity *split_commodity = xaccAccountGetCommodity(xaccSplitGetAccount(split)); if (xaccTransStillHasSplit (trans, split) && gnc_commodity_equal (commodity, split_commodity)) val_imbalance = gnc_numeric_add (val_imbalance, xaccSplitGetValue (split), GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT); } return val_imbalance; }
static void add_balance_split (Transaction *trans, gnc_numeric imbalance, Account *root, Account *account) { const gnc_commodity *commodity; gnc_numeric old_value, new_value; Split *balance_split; gnc_commodity *currency = xaccTransGetCurrency (trans); balance_split = get_balance_split(trans, root, account, currency); if (!balance_split) { /* Error already logged */ LEAVE(""); return; } account = xaccSplitGetAccount(balance_split); xaccTransBeginEdit (trans); old_value = xaccSplitGetValue (balance_split); /* Note: We have to round for the commodity's fraction, NOT any * already existing denominator (bug #104343), because either one * of the denominators might already be reduced. */ new_value = gnc_numeric_sub (old_value, imbalance, gnc_commodity_get_fraction(currency), GNC_HOW_RND_ROUND_HALF_UP); xaccSplitSetValue (balance_split, new_value); commodity = xaccAccountGetCommodity (account); if (gnc_commodity_equiv (currency, commodity)) { xaccSplitSetAmount (balance_split, new_value); } xaccSplitScrub (balance_split); xaccTransCommitEdit (trans); }
/* Do we need an exchange rate */ static gboolean gtu_sr_needs_exchange_rate (GncTreeViewSplitReg *view, Transaction *trans, Split *split) { gnc_commodity *split_com, *txn_curr, *reg_com; ENTER("gtu_sr_needs_exchange_rate - trans %p and split %p", trans, split); txn_curr = xaccTransGetCurrency (trans); split_com = xaccAccountGetCommodity (xaccSplitGetAccount (split)); if (split_com && txn_curr && !gnc_commodity_equiv (split_com, txn_curr)) { LEAVE("gtu_sr_needs_exchange_rate split_com to txn_curr return TRUE"); return TRUE; } reg_com = gnc_tree_view_split_reg_get_reg_commodity (view); if (split_com && reg_com && !gnc_commodity_equiv (split_com, reg_com)) { LEAVE("gtu_sr_needs_exchange_rate split_com and reg_com return TRUE"); return TRUE; } LEAVE("No Exchange rate needed"); return FALSE; }
static void gnc_reconcile_view_toggle_children (Account *account, GNCReconcileView *view, Split *split) { GList *child_accounts, *node; Transaction *transaction; /* * Need to get all splits in this transaction and identify any that are * in the same hierarchy as the account being reconciled (not necessarily * the account this split is from.) * * For each of these splits toggle them all to the same state. */ child_accounts = gnc_account_get_descendants (account); child_accounts = g_list_prepend (child_accounts, account); transaction = xaccSplitGetParent (split); for (node = xaccTransGetSplitList (transaction); node; node = node->next) { Split *other_split; Account *other_account; GNCReconcileView *current_view; GtkTreeModel *model; GtkTreeIter iter; gboolean valid; gpointer pointer; other_split = node->data; other_account = xaccSplitGetAccount (other_split); if (other_split == split) continue; /* Check this 'other' account in in the same hierarchy */ if (!g_list_find (child_accounts, other_account)) continue; /* Search our sibling view for this split first. We search the * sibling list first because that it where it is most likely to be. */ current_view = view->sibling; if (!gnc_query_view_item_in_view (GNC_QUERY_VIEW (current_view), other_split)) { /* Not in the sibling view, try this view */ current_view = view; if (!gnc_query_view_item_in_view (GNC_QUERY_VIEW (current_view), other_split)) /* We can't find it, nothing more I can do about it */ continue; } /* Found the other split. Toggle the reconciled check mark in the view... */ model = gtk_tree_view_get_model (GTK_TREE_VIEW (current_view)); valid = gtk_tree_model_get_iter_first (model, &iter); while (valid) { // Walk through the list, reading each row gtk_tree_model_get (model, &iter, REC_POINTER, &pointer, -1); if(pointer == other_split) { gboolean toggled; gtk_tree_model_get (model, &iter, REC_RECN, &toggled, -1); gtk_list_store_set (GTK_LIST_STORE (model), &iter, REC_RECN, !toggled, -1); break; } valid = gtk_tree_model_iter_next (model, &iter); } /* ...and toggle its reconciled state in the internal hash */ gnc_reconcile_view_toggle_split (current_view, other_split); } g_list_free (child_accounts); }
static void gnc_transaction_balance_trading (Transaction *trans, Account *root) { MonetaryList *imbal_list; MonetaryList *imbalance_commod; Split *balance_split = NULL; /* If the transaction is balanced, nothing more to do */ imbal_list = xaccTransGetImbalance (trans); if (!imbal_list) { LEAVE("transaction is balanced"); return; } PINFO ("Currency unbalanced transaction"); for (imbalance_commod = imbal_list; imbalance_commod; imbalance_commod = imbalance_commod->next) { gnc_monetary *imbal_mon = imbalance_commod->data; gnc_commodity *commodity; gnc_numeric old_amount, new_amount; gnc_numeric old_value, new_value, val_imbalance; Account *account = NULL; const gnc_commodity *txn_curr = xaccTransGetCurrency (trans); commodity = gnc_monetary_commodity (*imbal_mon); balance_split = get_trading_split(trans, root, commodity); if (!balance_split) { /* Error already logged */ gnc_monetary_list_free(imbal_list); LEAVE(""); return; } account = xaccSplitGetAccount(balance_split); if (! gnc_commodity_equal (txn_curr, commodity)) { val_imbalance = gnc_transaction_get_commodity_imbalance (trans, commodity); } xaccTransBeginEdit (trans); old_amount = xaccSplitGetAmount (balance_split); new_amount = gnc_numeric_sub (old_amount, gnc_monetary_value(*imbal_mon), gnc_commodity_get_fraction(commodity), GNC_HOW_RND_ROUND_HALF_UP); xaccSplitSetAmount (balance_split, new_amount); if (gnc_commodity_equal (txn_curr, commodity)) { /* Imbalance commodity is the transaction currency, value in the split must be the same as the amount */ xaccSplitSetValue (balance_split, new_amount); } else { old_value = xaccSplitGetValue (balance_split); new_value = gnc_numeric_sub (old_value, val_imbalance, gnc_commodity_get_fraction(txn_curr), GNC_HOW_RND_ROUND_HALF_UP); xaccSplitSetValue (balance_split, new_value); } xaccSplitScrub (balance_split); xaccTransCommitEdit (trans); } gnc_monetary_list_free(imbal_list); }
static void gnc_split_register_save_cells (gpointer save_data, gpointer user_data) { SRSaveData *sd = save_data; SplitRegister *reg = user_data; Split *other_split; gnc_commodity *txn_cur; gnc_numeric rate = gnc_numeric_zero(); g_return_if_fail (sd != NULL); if (!sd->do_scrub) return; other_split = xaccSplitGetOtherSplit (sd->split); txn_cur = xaccTransGetCurrency (sd->trans); xaccSplitScrub (sd->split); rate = gnc_split_register_get_rate_cell (reg, RATE_CELL); if (other_split && !sd->reg_expanded) { gnc_numeric amount, value = xaccSplitGetValue (sd->split); Account *acc; gboolean split_needs_amount; split_needs_amount = gnc_split_register_split_needs_amount(reg, sd->split); /* We are changing the rate on the current split, but it was not * handled in the debcred handler, so we need to do it here. */ if (!sd->handled_dc && split_needs_amount && !gnc_numeric_zero_p (rate)) { gnc_numeric amount = xaccSplitGetAmount (sd->split); value = gnc_numeric_div( amount, rate, gnc_commodity_get_fraction(txn_cur), GNC_HOW_RND_ROUND_HALF_UP); xaccSplitSetValue (sd->split, value); /* XXX: do we need to set the amount on the other split? */ } /* Now reverse the value for the other split */ value = gnc_numeric_neg (value); if (gnc_split_register_split_needs_amount (reg, other_split)) { acc = xaccSplitGetAccount (other_split); /* If we don't have an exchange rate then figure it out. Or, if * BOTH splits require an amount, then most likely we're in the * strange case of having a transaction currency different than * _both_ accounts -- so grab the other exchange rate. */ if (gnc_numeric_zero_p (rate) || split_needs_amount) rate = xaccTransGetAccountConvRate(xaccSplitGetParent (other_split), acc); amount = gnc_numeric_mul (value, rate, xaccAccountGetCommoditySCU (acc), GNC_HOW_RND_ROUND_HALF_UP); xaccSplitSetAmount (other_split, amount); } xaccSplitSetValue (other_split, value); xaccSplitScrub (other_split); } else if (gnc_split_register_split_needs_amount (reg, sd->split) && ! gnc_numeric_zero_p (rate)) { /* this is either a multi-split or expanded transaction, so only * deal with this split... In particular we need to reset the * Value if the conv-rate changed. * * If we handled the debcred then no need to do anything there -- * the debcred handler did all the computation. If NOT, then the * convrate changed -- reset the value from the amount. */ if (!sd->handled_dc) { gnc_split_register_save_amount_values (sd, reg); #if 0 gnc_numeric value, amount; amount = xaccSplitGetAmount (sd->split); value = gnc_numeric_div (amount, rate, gnc_commodity_get_fraction (txn_cur), GNC_HOW_RND_ROUND_HALF_UP); xaccSplitSetValue (sd->split, value); #endif } } }
void xaccSplitScrub (Split *split) { Account *account; Transaction *trans; gnc_numeric value, amount; gnc_commodity *currency, *acc_commodity; int scu; if (!split) return; ENTER ("(split=%p)", split); trans = xaccSplitGetParent (split); if (!trans) { LEAVE("no trans"); return; } account = xaccSplitGetAccount (split); /* If there's no account, this split is an orphan. * We need to fix that first, before proceeding. */ if (!account) { xaccTransScrubOrphans (trans); account = xaccSplitGetAccount (split); } /* Grrr... the register gnc_split_register_load() line 203 of * src/register/ledger-core/split-register-load.c will create * free-floating bogus transactions. Ignore these for now ... */ if (!account) { PINFO ("Free Floating Transaction!"); LEAVE ("no account"); return; } /* Split amounts and values should be valid numbers */ value = xaccSplitGetValue (split); if (gnc_numeric_check (value)) { value = gnc_numeric_zero(); xaccSplitSetValue (split, value); } amount = xaccSplitGetAmount (split); if (gnc_numeric_check (amount)) { amount = gnc_numeric_zero(); xaccSplitSetAmount (split, amount); } currency = xaccTransGetCurrency (trans); /* If the account doesn't have a commodity, * we should attempt to fix that first. */ acc_commodity = xaccAccountGetCommodity(account); if (!acc_commodity) { xaccAccountScrubCommodity (account); } if (!acc_commodity || !gnc_commodity_equiv(acc_commodity, currency)) { LEAVE ("(split=%p) inequiv currency", split); return; } scu = MIN (xaccAccountGetCommoditySCU (account), gnc_commodity_get_fraction (currency)); if (gnc_numeric_same (amount, value, scu, GNC_HOW_RND_ROUND_HALF_UP)) { LEAVE("(split=%p) different values", split); return; } /* * This will be hit every time you answer yes to the dialog "The * current transaction has changed. Would you like to record it. */ PINFO ("Adjusted split with mismatched values, desc=\"%s\" memo=\"%s\"" " old amount %s %s, new amount %s", trans->description, split->memo, gnc_num_dbg_to_string (xaccSplitGetAmount(split)), gnc_commodity_get_mnemonic (currency), gnc_num_dbg_to_string (xaccSplitGetValue(split))); xaccTransBeginEdit (trans); xaccSplitSetAmount (split, value); xaccTransCommitEdit (trans); LEAVE ("(split=%p)", split); }
static void gnc_split_register_save_amount_values (SRSaveData *sd, SplitRegister *reg) { Account *acc; gnc_numeric new_amount, convrate, amtconv, value; gnc_commodity *curr, *reg_com, *xfer_com; Account *xfer_acc; new_amount = gnc_split_register_debcred_cell_value (reg); acc = gnc_split_register_get_default_account (reg); xfer_acc = xaccSplitGetAccount (sd->split); xfer_com = xaccAccountGetCommodity (xfer_acc); reg_com = xaccAccountGetCommodity (acc); curr = xaccTransGetCurrency (sd->trans); /* First, compute the conversion rate to convert the value to the * amount. */ amtconv = convrate = gnc_split_register_get_rate_cell (reg, RATE_CELL); if (acc && gnc_split_register_needs_conv_rate (reg, sd->trans, acc)) { /* If we are in an expanded register and the xfer_acc->comm != * reg_acc->comm then we need to compute the convrate here. * Otherwise, we _can_ use the rate_cell! */ if (sd->reg_expanded && ! gnc_commodity_equal (reg_com, xfer_com)) amtconv = xaccTransGetAccountConvRate(sd->trans, acc); } if (xaccTransUseTradingAccounts (sd->trans)) { /* Using currency accounts, the amount is probably really the amount and not the value. */ gboolean is_amount; if (reg->type == STOCK_REGISTER || reg->type == CURRENCY_REGISTER || reg->type == PORTFOLIO_LEDGER) { if (xaccAccountIsPriced(xfer_acc) || !gnc_commodity_is_iso(xaccAccountGetCommodity(xfer_acc))) is_amount = FALSE; else is_amount = TRUE; } else { is_amount = TRUE; } if (is_amount) { xaccSplitSetAmount(sd->split, new_amount); if (gnc_split_register_split_needs_amount (reg, sd->split)) { value = gnc_numeric_div(new_amount, amtconv, gnc_commodity_get_fraction(curr), GNC_HOW_RND_ROUND_HALF_UP); xaccSplitSetValue(sd->split, value); } else xaccSplitSetValue(sd->split, new_amount); } else { xaccSplitSetValue(sd->split, new_amount); } return; } /* How to interpret new_amount depends on our view of this * transaction. If we're sitting in an account with the same * commodity as the transaction, then we can set the Value and then * compute the amount. Otherwise we are setting the "converted * value". This means we need to convert new_amount to the actual * 'value' by dividing by the convrate in order to set the value. */ /* Now compute/set the split value. Amount is in the register * currency but we need to convert to the txn currency. */ if (gnc_split_register_needs_conv_rate (reg, sd->trans, acc)) { /* convert the amount to the Value ... */ value = gnc_numeric_div (new_amount, amtconv, gnc_commodity_get_fraction (curr), GNC_HOW_RND_ROUND_HALF_UP); xaccSplitSetValue (sd->split, value); } else xaccSplitSetValue (sd->split, new_amount); /* Now re-compute the Amount from the Value. We may need to convert * from the Value back to the amount here using the convrate from * earlier. */ value = xaccSplitGetValue (sd->split); if (gnc_split_register_split_needs_amount (reg, sd->split)) { acc = xaccSplitGetAccount (sd->split); new_amount = gnc_numeric_mul (value, convrate, xaccAccountGetCommoditySCU (acc), GNC_HOW_RND_ROUND_HALF_UP); xaccSplitSetAmount (sd->split, new_amount); } }
void gnc_tree_util_split_reg_save_amount_values (GncTreeViewSplitReg *view, Transaction *trans, Split *split, gnc_numeric input) { GncTreeModelSplitReg *model; Account *acc; gnc_numeric new_amount, convrate, amtconv, value; gnc_commodity *curr, *reg_com, *xfer_com; Account *xfer_acc; ENTER("View is %p, trans is %p, split is %p, input is %s", view, trans, split, gnc_numeric_to_string (input)); model = gnc_tree_view_split_reg_get_model_from_view (view); new_amount = input; acc = gnc_tree_model_split_reg_get_anchor (model); xfer_acc = xaccSplitGetAccount (split); xfer_com = xaccAccountGetCommodity (xfer_acc); reg_com = xaccAccountGetCommodity (acc); curr = xaccTransGetCurrency (trans); if (!xaccTransGetRateForCommodity (trans, reg_com, NULL, &convrate)) convrate = gnc_numeric_create (100, 100); amtconv = convrate; if (gnc_tree_util_split_reg_needs_conv_rate (view, trans, acc)) { /* If we are in an expanded register and the xfer_acc->comm != * reg_acc->comm then we need to compute the convrate here. * Otherwise, we _can_ use the rate_cell! */ if (gnc_commodity_equal (reg_com, xfer_com)) amtconv = xaccTransGetAccountConvRate (trans, acc); } if (xaccTransUseTradingAccounts (trans)) { /* Using currency accounts, the amount is probably really the amount and not the value. */ gboolean is_amount; if (model->type == STOCK_REGISTER2 || model->type == CURRENCY_REGISTER2 || model->type == PORTFOLIO_LEDGER2) { if (xaccAccountIsPriced (xfer_acc) || !gnc_commodity_is_iso (xaccAccountGetCommodity (xfer_acc))) is_amount = FALSE; else is_amount = TRUE; } else { is_amount = TRUE; } if (is_amount) { xaccSplitSetAmount (split, new_amount); if (gnc_tree_util_split_reg_needs_amount (view, split)) { value = gnc_numeric_div (new_amount, amtconv, gnc_commodity_get_fraction (curr), GNC_HOW_RND_ROUND_HALF_UP); xaccSplitSetValue (split, value); } else xaccSplitSetValue (split, new_amount); } else { xaccSplitSetValue (split, new_amount); } LEAVE(" "); return; } /* How to interpret new_amount depends on our view of this * transaction. If we're sitting in an account with the same * commodity as the transaction, then we can set the Value and then * compute the amount. Otherwise we are setting the "converted * value". This means we need to convert new_amount to the actual * 'value' by dividing by the convrate in order to set the value. */ /* Now compute/set the split value. Amount is in the register * currency but we need to convert to the txn currency. */ if (gnc_tree_util_split_reg_needs_conv_rate (view, trans, acc)) { /* convert the amount to the Value ... */ value = gnc_numeric_div (new_amount, amtconv, gnc_commodity_get_fraction (curr), GNC_HOW_RND_ROUND_HALF_UP); xaccSplitSetValue (split, value); } else { xaccSplitSetValue (split, new_amount); } /* Now re-compute the Amount from the Value. We may need to convert * from the Value back to the amount here using the convrate from * earlier. */ value = xaccSplitGetValue (split); if (gnc_tree_util_split_reg_needs_amount (view, split)) { acc = xaccSplitGetAccount (split); new_amount = gnc_numeric_mul (value, convrate, xaccAccountGetCommoditySCU (acc), GNC_HOW_RND_ROUND_HALF_UP); xaccSplitSetAmount (split, new_amount); } else { xaccSplitSetAmount (split, value); } LEAVE(" "); }
static gboolean save_transaction( GncSqlBackend* be, Transaction* pTx, gboolean do_save_splits ) { const GncGUID* guid; gint op; gboolean is_infant; QofInstance* inst; gboolean is_ok = TRUE; gchar* err = NULL; g_return_val_if_fail( be != NULL, FALSE ); g_return_val_if_fail( pTx != NULL, FALSE ); inst = QOF_INSTANCE(pTx); is_infant = qof_instance_get_infant( inst ); if ( qof_instance_get_destroying( inst ) ) { op = OP_DB_DELETE; } else if ( be->is_pristine_db || is_infant ) { op = OP_DB_INSERT; } else { op = OP_DB_UPDATE; } if ( op != OP_DB_DELETE ) { gnc_commodity *commodity = xaccTransGetCurrency( pTx ); // Ensure the commodity is in the db is_ok = gnc_sql_save_commodity( be, commodity ); if ( ! is_ok ) { err = "Commodity save failed: Probably an invalid or missing currency"; qof_backend_set_error( &be->be, ERR_BACKEND_DATA_CORRUPT); } } if ( is_ok ) { is_ok = gnc_sql_do_db_operation( be, op, TRANSACTION_TABLE, GNC_ID_TRANS, pTx, tx_col_table ); if ( ! is_ok ) { err = "Transaction header save failed. Check trace log for SQL errors"; } } if ( is_ok ) { // Commit slots and splits guid = qof_instance_get_guid( inst ); if ( !qof_instance_get_destroying(inst) ) { is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) ); if ( ! is_ok ) { err = "Slots save failed. Check trace log for SQL errors"; } if ( is_ok && do_save_splits ) { is_ok = save_splits( be, guid, xaccTransGetSplitList( pTx ) ); if ( ! is_ok ) { err = "Split save failed. Check trace log for SQL errors"; } } } else { is_ok = gnc_sql_slots_delete( be, guid ); if ( ! is_ok ) { err = "Slots delete failed. Check trace log for SQL errors"; } if ( is_ok ) { is_ok = delete_splits( be, pTx ); if ( ! is_ok ) { err = "Split delete failed. Check trace log for SQL errors"; } } } } if (! is_ok ) { G_GNUC_UNUSED gchar *message1 = "Transaction %s dated %s in account %s not saved due to %s.%s"; G_GNUC_UNUSED gchar *message2 = "\nDatabase may be corrupted, check your data carefully."; Split* split = xaccTransGetSplit( pTx, 0); Account *acc = xaccSplitGetAccount( split ); /* FIXME: This needs to be implemented qof_error_format_secondary_text( GTK_MESSAGE_DIALOG( msg ), message1, xaccTransGetDescription( pTx ), qof_print_date( xaccTransGetDate( pTx ) ), xaccAccountGetName( acc ), err, message2 ); */ PERR( "Transaction %s dated %s in account %s not saved due to %s.\n", xaccTransGetDescription( pTx ), qof_print_date( xaccTransGetDate( pTx ) ), xaccAccountGetName( acc ), err ); } return is_ok; }
void gnc_split_register_load (SplitRegister *reg, GList * slist, Account *default_account) { SRInfo *info; Transaction *pending_trans; CursorBuffer *cursor_buffer; GHashTable *trans_table = NULL; CellBlock *cursor_header; CellBlock *lead_cursor; CellBlock *split_cursor; Transaction *blank_trans; Transaction *find_trans; Transaction *trans; CursorClass find_class; Split *find_trans_split; Split *blank_split; Split *find_split; Split *split; Table *table; GList *node; gboolean start_primary_color = TRUE; gboolean found_pending = FALSE; gboolean need_divider_upper = FALSE; gboolean found_divider_upper = FALSE; gboolean found_divider = FALSE; gboolean has_last_num = FALSE; gboolean multi_line; gboolean dynamic; gboolean we_own_slist = FALSE; gboolean use_autoreadonly = qof_book_uses_autoreadonly(gnc_get_current_book()); VirtualCellLocation vcell_loc; VirtualLocation save_loc; int new_trans_split_row = -1; int new_trans_row = -1; int new_split_row = -1; time64 present, autoreadonly_time = 0; g_return_if_fail(reg); table = reg->table; g_return_if_fail(table); info = gnc_split_register_get_info (reg); g_return_if_fail(info); ENTER("reg=%p, slist=%p, default_account=%p", reg, slist, default_account); blank_split = xaccSplitLookup (&info->blank_split_guid, gnc_get_current_book ()); pending_trans = xaccTransLookup (&info->pending_trans_guid, gnc_get_current_book ()); /* make sure we have a blank split */ if (blank_split == NULL) { /* Wouldn't it be a bug to open the new transaction if there was * already a pending transaction? */ g_assert(pending_trans == NULL); blank_split = create_blank_split (default_account, info); } blank_trans = xaccSplitGetParent (blank_split); DEBUG("blank_split=%p, blank_trans=%p, pending_trans=%p", blank_split, blank_trans, pending_trans); info->default_account = *xaccAccountGetGUID (default_account); // gnc_table_leave_update (table, table->current_cursor_loc); multi_line = (reg->style == REG_STYLE_JOURNAL); dynamic = (reg->style == REG_STYLE_AUTO_LEDGER); lead_cursor = gnc_split_register_get_passive_cursor (reg); split_cursor = gnc_table_layout_get_cursor (table->layout, CURSOR_SPLIT); /* figure out where we are going to. */ if (info->traverse_to_new) { find_trans = blank_trans; find_split = NULL; find_trans_split = blank_split; find_class = CURSOR_CLASS_SPLIT; } else { find_trans = info->cursor_hint_trans; find_split = info->cursor_hint_split; find_trans_split = info->cursor_hint_trans_split; find_class = info->cursor_hint_cursor_class; } save_loc = table->current_cursor_loc; /* If the current cursor has changed we save the values for later * possible restoration. */ if (gnc_table_current_cursor_changed (table, TRUE) && (find_split == gnc_split_register_get_current_split (reg))) { cursor_buffer = gnc_cursor_buffer_new (); gnc_table_save_current_cursor (table, cursor_buffer); } else cursor_buffer = NULL; /* disable move callback -- we don't want the cascade of * callbacks while we are fiddling with loading the register */ gnc_table_control_allow_move (table->control, FALSE); /* invalidate the cursor */ { VirtualLocation virt_loc; gnc_virtual_location_init(&virt_loc); gnc_table_move_cursor_gui (table, virt_loc); } /* make sure that the header is loaded */ vcell_loc.virt_row = 0; vcell_loc.virt_col = 0; cursor_header = gnc_table_layout_get_cursor (table->layout, CURSOR_HEADER); gnc_table_set_vcell (table, cursor_header, NULL, TRUE, TRUE, vcell_loc); vcell_loc.virt_row++; /* get the current time and reset the dividing row */ present = gnc_time64_get_today_end (); if (use_autoreadonly) { GDate *d = qof_book_get_autoreadonly_gdate(gnc_get_current_book()); // "d" is NULL if use_autoreadonly is FALSE autoreadonly_time = d ? timespecToTime64(gdate_to_timespec(*d)) : 0; g_date_free(d); } if (info->first_pass) { if (default_account) { const char *last_num = xaccAccountGetLastNum (default_account); if (last_num) { NumCell *cell; cell = (NumCell *) gnc_table_layout_get_cell(table->layout, NUM_CELL); gnc_num_cell_set_last_num (cell, last_num); has_last_num = TRUE; } } /* load up account names into the transfer combobox menus */ gnc_split_register_load_xfer_cells (reg, default_account); gnc_split_register_load_recn_cells (reg); gnc_split_register_load_type_cells (reg); } if (info->separator_changed) change_account_separator (info, table, reg); table->model->dividing_row_upper = -1; table->model->dividing_row = -1; // Ensure that the transaction and splits being edited are in the split // list we're about to load. if (pending_trans != NULL) { for (node = xaccTransGetSplitList(pending_trans); node; node = node->next) { Split *pending_split = (Split*)node->data; if (!xaccTransStillHasSplit(pending_trans, pending_split)) continue; if (g_list_find(slist, pending_split) != NULL) continue; if (g_list_find_custom(slist, pending_trans, _find_split_with_parent_txn) != NULL) continue; if (!we_own_slist) { // lazy-copy slist = g_list_copy(slist); we_own_slist = TRUE; } slist = g_list_append(slist, pending_split); } } if (multi_line) trans_table = g_hash_table_new (g_direct_hash, g_direct_equal); /* populate the table */ for (node = slist; node; node = node->next) { split = node->data; trans = xaccSplitGetParent (split); if (!xaccTransStillHasSplit(trans, split)) continue; if (pending_trans == trans) found_pending = TRUE; /* If the transaction has only one split, and it's not our * pending_trans, then it's another register's blank split and * we don't want to see it. */ else if (xaccTransCountSplits (trans) == 1 && xaccSplitGetAccount (split) == NULL) continue; /* Do not load splits from the blank transaction. */ if (trans == blank_trans) continue; if (multi_line) { /* Skip this split if its transaction has already been loaded. */ if (g_hash_table_lookup (trans_table, trans)) continue; g_hash_table_insert (trans_table, trans, trans); } if (info->show_present_divider && use_autoreadonly && !found_divider_upper) { if (xaccTransGetDate (trans) >= autoreadonly_time) { table->model->dividing_row_upper = vcell_loc.virt_row; found_divider_upper = TRUE; } else { need_divider_upper = TRUE; } } if (info->show_present_divider && !found_divider && (xaccTransGetDate (trans) > present)) { table->model->dividing_row = vcell_loc.virt_row; found_divider = TRUE; } /* If this is the first load of the register, * fill up the quickfill cells. */ if (info->first_pass) add_quickfill_completions(reg->table->layout, trans, split, has_last_num); if (trans == find_trans) new_trans_row = vcell_loc.virt_row; if (split == find_trans_split) new_trans_split_row = vcell_loc.virt_row; gnc_split_register_add_transaction (reg, trans, split, lead_cursor, split_cursor, multi_line, start_primary_color, TRUE, find_trans, find_split, find_class, &new_split_row, &vcell_loc); if (!multi_line) start_primary_color = !start_primary_color; } if (multi_line) g_hash_table_destroy (trans_table); /* add the blank split at the end. */ if (pending_trans == blank_trans) found_pending = TRUE; /* No upper divider yet? Store it now */ if (info->show_present_divider && use_autoreadonly && !found_divider_upper && need_divider_upper) { table->model->dividing_row_upper = vcell_loc.virt_row; found_divider_upper = TRUE; } if (blank_trans == find_trans) new_trans_row = vcell_loc.virt_row; if (blank_split == find_trans_split) new_trans_split_row = vcell_loc.virt_row; /* If we didn't find the pending transaction, it was removed * from the account. */ if (!found_pending) { info->pending_trans_guid = *guid_null (); if (xaccTransIsOpen (pending_trans)) xaccTransCommitEdit (pending_trans); else if (pending_trans) g_assert_not_reached(); pending_trans = NULL; } /* go to blank on first pass */ if (info->first_pass) { new_split_row = -1; new_trans_split_row = -1; new_trans_row = -1; save_loc.vcell_loc = vcell_loc; save_loc.phys_row_offset = 0; save_loc.phys_col_offset = 0; } gnc_split_register_add_transaction (reg, blank_trans, blank_split, lead_cursor, split_cursor, multi_line, start_primary_color, info->blank_split_edited, find_trans, find_split, find_class, &new_split_row, &vcell_loc); /* resize the table to the sizes we just counted above */ /* num_virt_cols is always one. */ gnc_table_set_size (table, vcell_loc.virt_row, 1); /* restore the cursor to its rightful position */ { VirtualLocation trans_split_loc; if (new_split_row > 0) save_loc.vcell_loc.virt_row = new_split_row; else if (new_trans_split_row > 0) save_loc.vcell_loc.virt_row = new_trans_split_row; else if (new_trans_row > 0) save_loc.vcell_loc.virt_row = new_trans_row; trans_split_loc = save_loc; gnc_split_register_get_trans_split (reg, save_loc.vcell_loc, &trans_split_loc.vcell_loc); if (dynamic || multi_line || info->trans_expanded) { gnc_table_set_virt_cell_cursor( table, trans_split_loc.vcell_loc, gnc_split_register_get_active_cursor (reg)); gnc_split_register_set_trans_visible (reg, trans_split_loc.vcell_loc, TRUE, multi_line); info->trans_expanded = (reg->style == REG_STYLE_LEDGER); } else { save_loc = trans_split_loc; info->trans_expanded = FALSE; } if (gnc_table_find_close_valid_cell (table, &save_loc, FALSE)) { gnc_table_move_cursor_gui (table, save_loc); new_split_row = save_loc.vcell_loc.virt_row; if (find_split == gnc_split_register_get_current_split (reg)) gnc_table_restore_current_cursor (table, cursor_buffer); } } gnc_cursor_buffer_destroy (cursor_buffer); cursor_buffer = NULL; update_info (info, reg); gnc_split_register_set_cell_fractions( reg, gnc_split_register_get_current_split (reg)); gnc_table_refresh_gui (table, TRUE); gnc_split_register_show_trans (reg, table->current_cursor_loc.vcell_loc); /* enable callback for cursor user-driven moves */ gnc_table_control_allow_move (table->control, TRUE); if (we_own_slist) g_list_free(slist); LEAVE(" "); }
static guint sxftd_add_template_trans(SXFromTransInfo *sxfti) { Transaction *tr = sxfti->trans; GList *tt_list = NULL; GList *splits, *template_splits = NULL; TTInfo *tti = gnc_ttinfo_malloc(); TTSplitInfo *ttsi; Split *sp; gnc_numeric runningBalance; gnc_numeric split_value; const char *tmpStr; runningBalance = gnc_numeric_zero(); gnc_ttinfo_set_description(tti, xaccTransGetDescription(tr)); gnc_ttinfo_set_num(tti, gnc_get_num_action(tr, NULL)); gnc_ttinfo_set_currency(tti, xaccTransGetCurrency(tr)); for (splits = xaccTransGetSplitList(tr); splits; splits = splits->next) { sp = splits->data; ttsi = gnc_ttsplitinfo_malloc(); gnc_ttsplitinfo_set_action(ttsi, gnc_get_num_action(NULL, sp)); split_value = xaccSplitGetValue(sp); gnc_ttsplitinfo_set_memo(ttsi, xaccSplitGetMemo(sp)); runningBalance = gnc_numeric_add( runningBalance, split_value, 100, (GNC_DENOM_AUTO | GNC_HOW_DENOM_LCD) ); if (gnc_numeric_positive_p(split_value)) { tmpStr = xaccPrintAmount( split_value, gnc_default_print_info(FALSE) ); gnc_ttsplitinfo_set_debit_formula( ttsi, tmpStr ); } else { /* Negate the numeric so it prints w/o the sign at the front. */ tmpStr = xaccPrintAmount( gnc_numeric_neg( split_value ), gnc_default_print_info(FALSE) ); gnc_ttsplitinfo_set_credit_formula( ttsi, tmpStr ); } /* Copy over per-split account info */ gnc_ttsplitinfo_set_account( ttsi, xaccSplitGetAccount( sp ) ); template_splits = g_list_append(template_splits, ttsi); } if ( ! gnc_numeric_zero_p( runningBalance ) && !gnc_verify_dialog( (GtkWidget *)sxfti->dialog, FALSE, "%s", _("The Scheduled Transaction Editor " "cannot automatically balance " "this transaction. " "Should it still be " "entered?") ) ) { return SXFTD_ERRNO_UNBALANCED_XACTION; } gnc_ttinfo_set_template_splits(tti, template_splits); tt_list = g_list_append(tt_list, tti); gnc_suspend_gui_refresh (); xaccSchedXactionSetTemplateTrans(sxfti->sx, tt_list, gnc_get_current_book ()); gnc_resume_gui_refresh (); return 0; }