static void TransScrubOrphansFast (Transaction *trans, Account *root) { GList *node; gchar *accname; if (!trans) return; g_return_if_fail (root); for (node = trans->splits; node; node = node->next) { Split *split = node->data; Account *orph; if (split->acc) continue; DEBUG ("Found an orphan \n"); accname = g_strconcat (_("Orphan"), "-", gnc_commodity_get_mnemonic (trans->common_currency), NULL); orph = xaccScrubUtilityGetOrMakeAccount (root, trans->common_currency, accname, ACCT_TYPE_BANK, FALSE); g_free (accname); if (!orph) continue; xaccSplitSetAccount(split, orph); } }
/** Adds a split to a transaction. * @param trans The transaction to add a split to * @param account The split's account * @param amount The split's amount * @param rec_state The split's reconcile status * @param rec_date The split's reconcile date * @param price The split's conversion rate from account commodity to transaction commodity */ static void trans_add_split (Transaction* trans, Account* account, GncNumeric amount, const boost::optional<std::string>& action, const boost::optional<std::string>& memo, const boost::optional<char>& rec_state, const boost::optional<GncDate>& rec_date, const boost::optional<GncNumeric> price) { QofBook* book = xaccTransGetBook (trans); auto split = xaccMallocSplit (book); xaccSplitSetAccount (split, account); xaccSplitSetParent (split, trans); xaccSplitSetAmount (split, static_cast<gnc_numeric>(amount)); auto trans_curr = xaccTransGetCurrency(trans); auto acct_comm = xaccAccountGetCommodity(account); GncNumeric value; if (gnc_commodity_equiv(trans_curr, acct_comm)) value = amount; else if (price) value = amount * *price; else { auto time = xaccTransRetDatePosted (trans); /* Import data didn't specify price, let's lookup the nearest in time */ auto nprice = gnc_pricedb_lookup_nearest_in_time64(gnc_pricedb_get_db(book), acct_comm, trans_curr, time); if (nprice) { /* Found a usable price. Let's check if the conversion direction is right */ GncNumeric rate; if (gnc_commodity_equiv(gnc_price_get_currency(nprice), trans_curr)) rate = gnc_price_get_value(nprice); else rate = static_cast<GncNumeric>(gnc_price_get_value(nprice)).inv(); value = amount * rate; } else { PWARN("No price found, using a price of 1."); value = amount; } } xaccSplitSetValue (split, static_cast<gnc_numeric>(value)); if (memo) xaccSplitSetMemo (split, memo->c_str()); /* Note, this function assumes the num/action switch is done at a higher level * if needed by the book option */ if (action) xaccSplitSetAction (split, action->c_str()); if (rec_state && *rec_state != 'n') xaccSplitSetReconcile (split, *rec_state); if (rec_state && *rec_state == YREC && rec_date) xaccSplitSetDateReconciledSecs (split, static_cast<time64>(GncDateTime(*rec_date, DayPart::neutral))); }
/** Adds a split to a transaction. * @param trans The transaction to add a split to * @param account The account used for the split * @param book The book where the split should be stored * @param amount The amount of the split */ static void trans_add_split(Transaction* trans, Account* account, QofBook* book, gnc_numeric amount) { Split* split = xaccMallocSplit(book); xaccSplitSetAccount(split, account); xaccSplitSetParent(split, trans); xaccSplitSetAmount(split, amount); xaccSplitSetValue(split, amount); xaccSplitSetAction(split, "Deposit"); }
/** Adds a split to a transaction. * @param trans The transaction to add a split to * @param account The account used for the split * @param book The book where the split should be stored * @param amount The amount of the split */ static void trans_add_split (Transaction* trans, Account* account, QofBook* book, gnc_numeric amount, const char *num) { Split* split = xaccMallocSplit (book); xaccSplitSetAccount (split, account); xaccSplitSetParent (split, trans); xaccSplitSetAmount (split, amount); xaccSplitSetValue (split, amount); /* set tran-num and/or split-action per book option */ gnc_set_num_action (trans, split, num, NULL); }
static Split * get_balance_split (Transaction *trans, Account *root, Account *account, gnc_commodity *commodity) { Split *balance_split; gchar *accname; if (!account || !gnc_commodity_equiv (commodity, xaccAccountGetCommodity(account))) { if (!root) { root = gnc_book_get_root_account (xaccTransGetBook (trans)); if (NULL == root) { /* This can't occur, things should be in books */ PERR ("Bad data corruption, no root account in book"); return NULL; } } accname = g_strconcat (_("Imbalance"), "-", gnc_commodity_get_mnemonic (commodity), NULL); account = xaccScrubUtilityGetOrMakeAccount (root, commodity, accname, ACCT_TYPE_BANK, FALSE); g_free (accname); if (!account) { PERR ("Can't get balancing account"); return NULL; } } balance_split = xaccTransFindSplitByAccount(trans, account); /* Put split into account before setting split value */ if (!balance_split) { balance_split = xaccMallocSplit (qof_instance_get_book(trans)); xaccTransBeginEdit (trans); xaccSplitSetParent(balance_split, trans); xaccSplitSetAccount(balance_split, account); xaccTransCommitEdit (trans); } return balance_split; }
/* Get the trading split for a given commodity, creating it (and the necessary accounts) if it doesn't exist. */ static Split * get_trading_split (Transaction *trans, Account *root, gnc_commodity *commodity) { Split *balance_split; Account *trading_account; Account *ns_account; Account *account; gnc_commodity *default_currency = NULL; if (!root) { root = gnc_book_get_root_account (xaccTransGetBook (trans)); if (NULL == root) { /* This can't occur, things should be in books */ PERR ("Bad data corruption, no root account in book"); return NULL; } } /* Get the default currency. This is harder than it seems. It's not possible to call gnc_default_currency() since it's a UI function. One might think that the currency of the root account would do, but the root account has no currency. Instead look for the Income placeholder account and use its currency. */ default_currency = xaccAccountGetCommodity(gnc_account_lookup_by_name(root, _("Income"))); if (! default_currency) { default_currency = commodity; } trading_account = xaccScrubUtilityGetOrMakeAccount (root, default_currency, _("Trading"), ACCT_TYPE_TRADING, TRUE); if (!trading_account) { PERR ("Can't get trading account"); return NULL; } ns_account = xaccScrubUtilityGetOrMakeAccount (trading_account, default_currency, gnc_commodity_get_namespace(commodity), ACCT_TYPE_TRADING, TRUE); if (!ns_account) { PERR ("Can't get namespace account"); return NULL; } account = xaccScrubUtilityGetOrMakeAccount (ns_account, commodity, gnc_commodity_get_mnemonic(commodity), ACCT_TYPE_TRADING, FALSE); if (!account) { PERR ("Can't get commodity account"); return NULL; } balance_split = xaccTransFindSplitByAccount(trans, account); /* Put split into account before setting split value */ if (!balance_split) { balance_split = xaccMallocSplit (qof_instance_get_book(trans)); xaccTransBeginEdit (trans); xaccSplitSetParent(balance_split, trans); xaccSplitSetAccount(balance_split, account); xaccTransCommitEdit (trans); } return balance_split; }
Transaction * gnc_ab_trans_to_gnc(const AB_TRANSACTION *ab_trans, Account *gnc_acc) { QofBook *book; Transaction *gnc_trans; const gchar *fitid; const GWEN_TIME *valuta_date; time64 current_time; const char *custref; gchar *description; Split *split; gchar *memo; g_return_val_if_fail(ab_trans && gnc_acc, NULL); /* Create new GnuCash transaction for the given AqBanking one */ book = gnc_account_get_book(gnc_acc); gnc_trans = xaccMallocTransaction(book); xaccTransBeginEdit(gnc_trans); /* Date / Time */ valuta_date = AB_Transaction_GetValutaDate(ab_trans); if (!valuta_date) { const GWEN_TIME *normal_date = AB_Transaction_GetDate(ab_trans); if (normal_date) valuta_date = normal_date; } if (valuta_date) xaccTransSetDatePostedSecsNormalized(gnc_trans, GWEN_Time_toTime_t(valuta_date)); else g_warning("transaction_cb: Oops, date 'valuta_date' was NULL"); xaccTransSetDateEnteredSecs(gnc_trans, gnc_time (NULL)); /* Currency. We take simply the default currency of the gnucash account */ xaccTransSetCurrency(gnc_trans, xaccAccountGetCommodity(gnc_acc)); /* Trans-Num or Split-Action set with gnc_set_num_action below per book * option */ /* Description */ description = gnc_ab_description_to_gnc(ab_trans); xaccTransSetDescription(gnc_trans, description); g_free(description); /* Notes. */ /* xaccTransSetNotes(gnc_trans, g_notes); */ /* But Nobody ever uses the Notes field? */ /* Add one split */ split = xaccMallocSplit(book); xaccSplitSetParent(split, gnc_trans); xaccSplitSetAccount(split, gnc_acc); /* Set the transaction number or split action field based on book option. * We use the "customer reference", if there is one. */ custref = AB_Transaction_GetCustomerReference(ab_trans); if (custref && *custref && g_ascii_strncasecmp(custref, "NONREF", 6) != 0) gnc_set_num_action (gnc_trans, split, custref, NULL); /* Set OFX unique transaction ID */ fitid = AB_Transaction_GetFiId(ab_trans); if (fitid && *fitid) gnc_import_set_split_online_id(split, fitid); { /* Amount into the split */ const AB_VALUE *ab_value = AB_Transaction_GetValue(ab_trans); double d_value = ab_value ? AB_Value_GetValueAsDouble (ab_value) : 0.0; AB_TRANSACTION_TYPE ab_type = AB_Transaction_GetType (ab_trans); gnc_numeric gnc_amount; /*printf("Transaction with value %f has type %d\n", d_value, ab_type);*/ /* If the value is positive, but the transaction type says the money is transferred away from our account (Transfer instead of DebitNote), we switch the value to negative. */ if (d_value > 0.0 && ab_type == AB_Transaction_TypeTransfer) d_value = -d_value; gnc_amount = double_to_gnc_numeric( d_value, xaccAccountGetCommoditySCU(gnc_acc), GNC_HOW_RND_ROUND_HALF_UP); if (!ab_value) g_warning("transaction_cb: Oops, value was NULL. Using 0"); xaccSplitSetBaseValue(split, gnc_amount, xaccAccountGetCommodity(gnc_acc)); } /* Memo in the Split. */ memo = gnc_ab_memo_to_gnc(ab_trans); xaccSplitSetMemo(split, memo); g_free(memo); return gnc_trans; }
static gboolean create_each_transaction_helper(Transaction *template_txn, void *user_data) { Transaction *new_txn; GList *txn_splits, *template_splits; Split *copying_split; gnc_commodity *first_cmdty = NULL; gboolean err_flag = FALSE; SxTxnCreationData *creation_data; creation_data = (SxTxnCreationData*)user_data; /* FIXME: In general, this should [correctly] deal with errors such as not finding the approrpiate Accounts and not being able to parse the formula|credit/debit strings. */ new_txn = xaccTransClone(template_txn); xaccTransBeginEdit(new_txn); g_debug("creating template txn desc [%s] for sx [%s]", xaccTransGetDescription(new_txn), xaccSchedXactionGetName(creation_data->instance->parent->sx)); /* clear any copied KVP data */ qof_instance_set_slots(QOF_INSTANCE(new_txn), kvp_frame_new()); /* Bug#500427: copy the notes, if any */ if (xaccTransGetNotes(template_txn) != NULL) { xaccTransSetNotes(new_txn, g_strdup(xaccTransGetNotes(template_txn))); } xaccTransSetDate(new_txn, g_date_get_day(&creation_data->instance->date), g_date_get_month(&creation_data->instance->date), g_date_get_year(&creation_data->instance->date)); /* the accounts and amounts are in the kvp_frames of the splits. */ template_splits = xaccTransGetSplitList(template_txn); txn_splits = xaccTransGetSplitList(new_txn); if ((template_splits == NULL) || (txn_splits == NULL)) { g_critical("transaction w/o splits for sx [%s]", xaccSchedXactionGetName(creation_data->instance->parent->sx)); xaccTransDestroy(new_txn); xaccTransCommitEdit(new_txn); return FALSE; } for (; txn_splits && template_splits; txn_splits = txn_splits->next, template_splits = template_splits->next) { Split *template_split; Account *split_acct; gnc_commodity *split_cmdty = NULL; /* FIXME: Ick. This assumes that the split lists will be ordered identically. :( They are, but we'd rather not have to count on it. --jsled */ template_split = (Split*)template_splits->data; copying_split = (Split*)txn_splits->data; if (!_get_template_split_account(creation_data->instance, template_split, &split_acct, creation_data->creation_errors)) { err_flag = TRUE; break; } /* clear out any copied Split frame data. */ qof_instance_set_slots(QOF_INSTANCE(copying_split), kvp_frame_new()); split_cmdty = xaccAccountGetCommodity(split_acct); if (first_cmdty == NULL) { first_cmdty = split_cmdty; xaccTransSetCurrency(new_txn, first_cmdty); } xaccSplitSetAccount(copying_split, split_acct); { gnc_numeric credit_num, debit_num, final; gint gncn_error; credit_num = gnc_numeric_zero(); debit_num = gnc_numeric_zero(); _get_credit_formula_value(creation_data->instance, template_split, &credit_num, creation_data->creation_errors); _get_debit_formula_value(creation_data->instance, template_split, &debit_num, creation_data->creation_errors); final = gnc_numeric_sub_fixed( debit_num, credit_num ); gncn_error = gnc_numeric_check(final); if (gncn_error != GNC_ERROR_OK) { GString *err = g_string_new(""); g_string_printf(err, "error %d in SX [%s] final gnc_numeric value, using 0 instead", gncn_error, xaccSchedXactionGetName(creation_data->instance->parent->sx)); g_critical("%s", err->str); if (creation_data->creation_errors != NULL) *creation_data->creation_errors = g_list_append(*creation_data->creation_errors, err); else g_string_free(err, TRUE); final = gnc_numeric_zero(); }