Transaction* GncPreTrans::create_trans (QofBook* book, gnc_commodity* currency) { if (created) return nullptr; /* Gently refuse to create the transaction if the basics are not set correctly * This should have been tested before calling this function though! */ auto check = verify_essentials(); if (!check.empty()) { PWARN ("Refusing to create transaction because essentials not set properly: %s", check.c_str()); return nullptr; } auto trans = xaccMallocTransaction (book); xaccTransBeginEdit (trans); xaccTransSetCurrency (trans, m_commodity ? *m_commodity : currency); xaccTransSetDatePostedSecsNormalized (trans, static_cast<time64>(GncDateTime(*m_date, DayPart::neutral))); if (m_num) xaccTransSetNum (trans, m_num->c_str()); if (m_desc) xaccTransSetDescription (trans, m_desc->c_str()); if (m_notes) xaccTransSetNotes (trans, m_notes->c_str()); created = true; return trans; }
void xaccSchedXactionSetTemplateTrans(SchedXaction *sx, GList *t_t_list, QofBook *book) { Transaction *new_trans; TTInfo *tti; TTSplitInfo *s_info; Split *new_split; GList *split_list; g_return_if_fail (book); /* delete any old transactions, if there are any */ delete_template_trans( sx ); for (; t_t_list != NULL; t_t_list = t_t_list->next) { tti = t_t_list->data; new_trans = xaccMallocTransaction(book); xaccTransBeginEdit(new_trans); xaccTransSetDescription(new_trans, gnc_ttinfo_get_description(tti)); xaccTransSetDatePostedSecsNormalized(new_trans, gnc_time (NULL)); /* Set tran-num with gnc_set_num_action which is the same as * xaccTransSetNum with these arguments */ gnc_set_num_action(new_trans, NULL, gnc_ttinfo_get_num(tti), NULL); xaccTransSetNotes (new_trans, gnc_ttinfo_get_notes (tti)); xaccTransSetCurrency( new_trans, gnc_ttinfo_get_currency(tti) ); for (split_list = gnc_ttinfo_get_template_splits(tti); split_list; split_list = split_list->next) { s_info = split_list->data; new_split = pack_split_info(s_info, sx->template_acct, new_trans, book); xaccTransAppendSplit(new_trans, new_split); } xaccTransCommitEdit(new_trans); } }
static void gnc_split_register_save_notes_cell (BasicCell * cell, gpointer save_data, gpointer user_data) { SRSaveData *sd = save_data; const char *value; g_return_if_fail (gnc_basic_cell_has_name (cell, NOTES_CELL)); value = gnc_basic_cell_get_value (cell); DEBUG ("NOTES: %s", value ? value : "(null)"); xaccTransSetNotes (sd->trans, value); }
/** Create a Transaction from a TransPropertyList. * @param list The list of properties * @param error Contains an error on failure * @return On success, a GncCsvTransLine; on failure, the trans pointer is NULL */ static GncCsvTransLine* trans_property_list_to_trans (TransPropertyList* list, gchar** error) { GncCsvTransLine* trans_line = g_new (GncCsvTransLine, 1); GList* properties_begin = list->properties; QofBook* book = gnc_account_get_book (list->account); gnc_commodity* currency = xaccAccountGetCommodity (list->account); gnc_numeric amount = double_to_gnc_numeric (0.0, xaccAccountGetCommoditySCU (list->account), GNC_HOW_RND_ROUND_HALF_UP); gchar *num = NULL; /* This flag is set to TRUE if we can use the "Deposit" or "Withdrawal" column. */ gboolean amount_set = FALSE; /* The balance is 0 by default. */ trans_line->balance_set = FALSE; trans_line->balance = amount; trans_line->num = NULL; /* We make the line_no -1 just to mark that it hasn't been set. We * may get rid of line_no soon anyway, so it's not particularly * important. */ trans_line->line_no = -1; /* Make sure this is a transaction with all the columns we need. */ if (!trans_property_list_verify_essentials (list, error)) { g_free(trans_line); return NULL; } trans_line->trans = xaccMallocTransaction (book); xaccTransBeginEdit (trans_line->trans); xaccTransSetCurrency (trans_line->trans, currency); /* Go through each of the properties and edit the transaction accordingly. */ list->properties = properties_begin; while (list->properties != NULL) { TransProperty* prop = (TransProperty*)(list->properties->data); switch (prop->type) { case GNC_CSV_DATE: xaccTransSetDatePostedSecsNormalized (trans_line->trans, *((time64*)(prop->value))); break; case GNC_CSV_DESCRIPTION: xaccTransSetDescription (trans_line->trans, (char*)(prop->value)); break; case GNC_CSV_NOTES: xaccTransSetNotes (trans_line->trans, (char*)(prop->value)); break; case GNC_CSV_NUM: /* the 'num' is saved and passed to 'trans_add_split' below where * 'gnc_set_num_action' is used to set tran-num and/or split-action * per book option */ num = g_strdup ((char*)(prop->value)); /* the 'num' is also saved and used in 'gnc_csv_parse_to_trans' when * it calls 'trans_add_split' after deleting the splits added below * when a balance is used by the user */ trans_line->num = g_strdup ((char*)(prop->value)); break; case GNC_CSV_DEPOSIT: /* Add deposits to the existing amount. */ if (prop->value != NULL) { amount = gnc_numeric_add (*((gnc_numeric*)(prop->value)), amount, xaccAccountGetCommoditySCU (list->account), GNC_HOW_RND_ROUND_HALF_UP); amount_set = TRUE; /* We will use the "Deposit" and "Withdrawal" columns in preference to "Balance". */ trans_line->balance_set = FALSE; } break; case GNC_CSV_WITHDRAWAL: /* Withdrawals are just negative deposits. */ if (prop->value != NULL) { amount = gnc_numeric_add (gnc_numeric_neg(*((gnc_numeric*)(prop->value))), amount, xaccAccountGetCommoditySCU (list->account), GNC_HOW_RND_ROUND_HALF_UP); amount_set = TRUE; /* We will use the "Deposit" and "Withdrawal" columns in preference to "Balance". */ trans_line->balance_set = FALSE; } break; case GNC_CSV_BALANCE: /* The balance gets stored in a separate field in trans_line. */ /* We will use the "Deposit" and "Withdrawal" columns in preference to "Balance". */ if (!amount_set && prop->value != NULL) { /* This gets put into the actual transaction at the end of gnc_csv_parse_to_trans. */ trans_line->balance = *((gnc_numeric*)(prop->value)); trans_line->balance_set = TRUE; } break; } list->properties = g_list_next (list->properties); } /* Add a split with the cumulative amount value. */ trans_add_split (trans_line->trans, list->account, book, amount, num); if (num) g_free (num); return trans_line; }
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(); }
/* File pointer must already be at the begining of a record */ static void process_trans_record( FILE *log_file) { char read_buf[2048]; char *read_retval; char * trans_ro = NULL; const char * record_end_str = "===== END"; int first_record = TRUE; int record_ended = FALSE; int split_num = 0; split_record record; Transaction * trans = NULL; Split * split = NULL; Account * acct = NULL; QofBook * book = gnc_get_current_book(); DEBUG("process_trans_record(): Begin...\n"); while ( record_ended == FALSE) { read_retval = fgets(read_buf, sizeof(read_buf), log_file); if (read_retval != NULL && strncmp(record_end_str, read_buf, strlen(record_end_str)) != 0) /* If we are not at the end of the record */ { split_num++; /*DEBUG("process_trans_record(): Line read: %s%s",read_buf ,"\n");*/ record = interpret_split_record( read_buf); dump_split_record( record); if (record.log_action_present) { switch (record.log_action) { case split_record::LOG_BEGIN_EDIT: DEBUG("process_trans_record():Ignoring log action: LOG_BEGIN_EDIT"); /*Do nothing, there is no point*/ break; case split_record::LOG_ROLLBACK: DEBUG("process_trans_record():Ignoring log action: LOG_ROLLBACK");/*Do nothing, since we didn't do the begin_edit either*/ break; case split_record::LOG_DELETE: DEBUG("process_trans_record(): Playing back LOG_DELETE"); if ((trans = xaccTransLookup (&(record.trans_guid), book)) != NULL && first_record == TRUE) { first_record = FALSE; if (xaccTransGetReadOnly(trans)) { PWARN("Destroying a read only transaction."); xaccTransClearReadOnly(trans); } xaccTransBeginEdit(trans); xaccTransDestroy(trans); } else if (first_record == TRUE) { PERR("The transaction to delete was not found!"); } else xaccTransDestroy(trans); break; case split_record::LOG_COMMIT: DEBUG("process_trans_record(): Playing back LOG_COMMIT"); if (record.trans_guid_present == TRUE && first_record == TRUE) { trans = xaccTransLookupDirect (record.trans_guid, book); if (trans != NULL) { DEBUG("process_trans_record(): Transaction to be edited was found"); xaccTransBeginEdit(trans); trans_ro = g_strdup(xaccTransGetReadOnly(trans)); if (trans_ro) { PWARN("Replaying a read only transaction."); xaccTransClearReadOnly(trans); } } else { DEBUG("process_trans_record(): Creating a new transaction"); trans = xaccMallocTransaction (book); xaccTransBeginEdit(trans); } xaccTransSetGUID (trans, &(record.trans_guid)); /*Fill the transaction info*/ if (record.date_entered_present) { xaccTransSetDateEnteredTS(trans, &(record.date_entered)); } if (record.date_posted_present) { xaccTransSetDatePostedTS(trans, &(record.date_posted)); } if (record.trans_num_present) { xaccTransSetNum(trans, record.trans_num); } if (record.trans_descr_present) { xaccTransSetDescription(trans, record.trans_descr); } if (record.trans_notes_present) { xaccTransSetNotes(trans, record.trans_notes); } } if (record.split_guid_present == TRUE) /*Fill the split info*/ { gboolean is_new_split; split = xaccSplitLookupDirect (record.split_guid, book); if (split != NULL) { DEBUG("process_trans_record(): Split to be edited was found"); is_new_split = FALSE; } else { DEBUG("process_trans_record(): Creating a new split"); split = xaccMallocSplit(book); is_new_split = TRUE; } xaccSplitSetGUID (split, &(record.split_guid)); if (record.acc_guid_present) { acct = xaccAccountLookupDirect(record.acc_guid, book); xaccAccountInsertSplit(acct, split); } if (is_new_split) xaccTransAppendSplit(trans, split); if (record.split_memo_present) { xaccSplitSetMemo(split, record.split_memo); } if (record.split_action_present) { xaccSplitSetAction(split, record.split_action); } if (record.date_reconciled_present) { xaccSplitSetDateReconciledTS (split, &(record.date_reconciled)); } if (record.split_reconcile_present) { xaccSplitSetReconcile(split, record.split_reconcile); } if (record.amount_present) { xaccSplitSetAmount(split, record.amount); } if (record.value_present) { xaccSplitSetValue(split, record.value); } } first_record = FALSE; break; } } else { PERR("Corrupted record"); } } else /* The record ended */ { record_ended = TRUE; DEBUG("process_trans_record(): Record ended\n"); if (trans != NULL) /*If we played with a transaction, commit it here*/ { xaccTransScrubCurrencyFromSplits(trans); xaccTransSetReadOnly(trans, trans_ro); xaccTransCommitEdit(trans); g_free(trans_ro); } } } }
int ofx_proc_transaction_cb(struct OfxTransactionData data, void * transaction_user_data) { char dest_string[255]; time64 current_time = gnc_time (NULL); Account *account; Account *investment_account = NULL; Account *income_account = NULL; gchar *investment_account_text, *investment_account_onlineid; gnc_commodity *currency = NULL; gnc_commodity *investment_commodity = NULL; gnc_numeric gnc_amount, gnc_units; QofBook *book; Transaction *transaction; Split *split; gchar *notes, *tmp; g_assert(gnc_ofx_importer_gui); if (!data.account_id_valid) { PERR("account ID for this transaction is unavailable!"); return 0; } account = gnc_import_select_account(gnc_gen_trans_list_widget(gnc_ofx_importer_gui), data.account_id, 0, NULL, NULL, ACCT_TYPE_NONE, NULL, NULL); if (account == NULL) { PERR("Unable to find account for id %s", data.account_id); return 0; } /***** Validate the input strings to ensure utf8 *****/ if (data.name_valid) gnc_utf8_strip_invalid(data.name); if (data.memo_valid) gnc_utf8_strip_invalid(data.memo); if (data.check_number_valid) gnc_utf8_strip_invalid(data.check_number); if (data.reference_number_valid) gnc_utf8_strip_invalid(data.reference_number); /***** Create the transaction and setup transaction data *******/ book = gnc_account_get_book(account); transaction = xaccMallocTransaction(book); xaccTransBeginEdit(transaction); /* Note: Unfortunately libofx <= 0.9.5 will not report a missing * date field as an invalid one. Instead, it will report it as * valid and return a completely bogus date. Starting with * libofx-0.9.6 (not yet released as of 2012-09-09), it will still * be reported as valid but at least the date integer itself is * just plain zero. */ if (data.date_posted_valid && (data.date_posted != 0)) { /* The hopeful case: We have a posted_date */ xaccTransSetDatePostedSecsNormalized(transaction, data.date_posted); } else if (data.date_initiated_valid && (data.date_initiated != 0)) { /* No posted date? Maybe we have an initiated_date */ xaccTransSetDatePostedSecsNormalized(transaction, data.date_initiated); } else { /* Uh no, no valid date. As a workaround use today's date */ xaccTransSetDatePostedSecsNormalized(transaction, current_time); } xaccTransSetDateEnteredSecs(transaction, current_time); /* Put transaction name in Description, or memo if name unavailable */ if (data.name_valid) { xaccTransSetDescription(transaction, data.name); } else if (data.memo_valid) { xaccTransSetDescription(transaction, data.memo); } /* Put everything else in the Notes field */ notes = g_strdup_printf("OFX ext. info: "); if (data.transactiontype_valid) { tmp = notes; notes = g_strdup_printf("%s%s%s", tmp, "|Trans type:", gnc_ofx_ttype_to_string(data.transactiontype)); g_free(tmp); } if (data.invtransactiontype_valid) { tmp = notes; notes = g_strdup_printf("%s%s%s", tmp, "|Investment Trans type:", gnc_ofx_invttype_to_str(data.invtransactiontype)); g_free(tmp); } if (data.memo_valid && data.name_valid) /* Copy only if memo wasn't put in Description */ { tmp = notes; notes = g_strdup_printf("%s%s%s", tmp, "|Memo:", data.memo); g_free(tmp); } if (data.date_funds_available_valid) { Timespec ts; timespecFromTime64(&ts, data.date_funds_available); gnc_timespec_to_iso8601_buff (ts, dest_string); tmp = notes; notes = g_strdup_printf("%s%s%s", tmp, "|Date funds available:", dest_string); g_free(tmp); } if (data.server_transaction_id_valid) { tmp = notes; notes = g_strdup_printf("%s%s%s", tmp, "|Server trans ID (conf. number):", data.server_transaction_id); g_free(tmp); } if (data.standard_industrial_code_valid) { tmp = notes; notes = g_strdup_printf("%s%s%ld", tmp, "|Standard Industrial Code:", data.standard_industrial_code); g_free(tmp); } if (data.payee_id_valid) { tmp = notes; notes = g_strdup_printf("%s%s%s", tmp, "|Payee ID:", data.payee_id); g_free(tmp); } //PERR("WRITEME: GnuCash ofx_proc_transaction():Add PAYEE and ADRESS here once supported by libofx! Notes=%s\n", notes); /* Ideally, gnucash should process the corrected transactions */ if (data.fi_id_corrected_valid) { PERR("WRITEME: GnuCash ofx_proc_transaction(): WARNING: This transaction corrected a previous transaction, but we created a new one instead!\n"); tmp = notes; notes = g_strdup_printf("%s%s%s%s", tmp, "|This corrects transaction #", data.fi_id_corrected, "but GnuCash didn't process the correction!"); g_free(tmp); } xaccTransSetNotes(transaction, notes); g_free(notes); if (data.account_ptr && data.account_ptr->currency_valid) { DEBUG("Currency from libofx: %s", data.account_ptr->currency); currency = gnc_commodity_table_lookup( gnc_get_current_commodities (), GNC_COMMODITY_NS_CURRENCY, data.account_ptr->currency); } else { DEBUG("Currency from libofx unavailable, defaulting to account's default"); currency = xaccAccountGetCommodity(account); } xaccTransSetCurrency(transaction, currency); if (data.amount_valid) { if (!data.invtransactiontype_valid) { /***** Process a normal transaction ******/ DEBUG("Adding split; Ordinary banking transaction, money flows from or into the source account"); split = xaccMallocSplit(book); xaccTransAppendSplit(transaction, split); xaccAccountInsertSplit(account, split); gnc_amount = gnc_ofx_numeric_from_double_txn(data.amount, transaction); xaccSplitSetBaseValue(split, gnc_amount, xaccTransGetCurrency(transaction)); /* set tran-num and/or split-action per book option */ if (data.check_number_valid) { gnc_set_num_action(transaction, split, data.check_number, NULL); } else if (data.reference_number_valid) { gnc_set_num_action(transaction, split, data.reference_number, NULL); } /* Also put the ofx transaction's memo in the * split's memo field */ if (data.memo_valid) { xaccSplitSetMemo(split, data.memo); } if (data.fi_id_valid) { gnc_import_set_split_online_id(split, data.fi_id); } } else if (data.unique_id_valid && data.security_data_valid && data.security_data_ptr != NULL && data.security_data_ptr->secname_valid) { gboolean choosing_account = TRUE; /********* Process an investment transaction **********/ /* Note that the ACCT_TYPE_STOCK account type should be replaced with something derived from data.invtranstype*/ // We have an investment transaction. First select the correct commodity. investment_commodity = gnc_import_select_commodity(data.unique_id, FALSE, NULL, NULL); if (investment_commodity != NULL) { // As we now have the commodity, select the account with that commodity. investment_account_text = g_strdup_printf( /* This string is a default account name. It MUST NOT contain the character ':' anywhere in it or in any translations. */ _("Stock account for security \"%s\""), data.security_data_ptr->secname); investment_account_onlineid = g_strdup_printf( "%s%s", data.account_id, data.unique_id); investment_account = gnc_import_select_account(NULL, investment_account_onlineid, 1, investment_account_text, investment_commodity, ACCT_TYPE_STOCK, NULL, NULL); // but use it only if that's really the right commodity if (investment_account && xaccAccountGetCommodity(investment_account) != investment_commodity) investment_account = NULL; // Loop until we either have an account, or the user pressed Cancel while (!investment_account && choosing_account) { // No account with correct commodity automatically found. // But are we in auto-create mode and already know a parent? if (auto_create_commodity && ofx_parent_account) { // Yes, so use that as parent when auto-creating the new account below. investment_account = ofx_parent_account; } else { // Let the user choose an account investment_account = gnc_import_select_account( gnc_gen_trans_list_widget(gnc_ofx_importer_gui), data.unique_id, TRUE, investment_account_text, investment_commodity, ACCT_TYPE_STOCK, NULL, &choosing_account); } // Does the chosen account have the right commodity? if (investment_account && xaccAccountGetCommodity(investment_account) != investment_commodity) { if (auto_create_commodity && xaccAccountTypesCompatible(xaccAccountGetType(investment_account), ACCT_TYPE_STOCK)) { // The user chose an account, but it does // not have the right commodity. Also, // auto-creation is on. Hence, we create a // new child account of the selected one, // and this one will have the right // commodity. Account *parent_account = investment_account; investment_account = gnc_ofx_new_account(investment_account_text, investment_commodity, parent_account, ACCT_TYPE_STOCK); if (investment_account) { gnc_import_set_acc_online_id(investment_account, data.unique_id); choosing_account = FALSE; ofx_parent_account = parent_account; } else { ofx_parent_account = NULL; } } else { // No account with matching commodity. Ask the user // whether to continue or abort. choosing_account = gnc_verify_dialog( gnc_gen_trans_list_widget(gnc_ofx_importer_gui), TRUE, "The chosen account \"%s\" does not have the correct " "currency/security \"%s\" (it has \"%s\" instead). " "This account cannot be used. " "Do you want to choose again?", xaccAccountGetName(investment_account), gnc_commodity_get_fullname(investment_commodity), gnc_commodity_get_fullname(xaccAccountGetCommodity(investment_account))); // We must also delete the online_id that was set in gnc_import_select_account() gnc_import_set_acc_online_id(investment_account, ""); investment_account = NULL; } } } if (!investment_account) { PERR("No investment account found for text: %s\n", investment_account_text); } g_free (investment_account_text); g_free (investment_account_onlineid); investment_account_text = NULL; if (investment_account != NULL && data.unitprice_valid && data.units_valid && ( data.invtransactiontype != OFX_INCOME ) ) { DEBUG("Adding investment split; Money flows from or into the stock account"); split = xaccMallocSplit(book); xaccTransAppendSplit(transaction, split); xaccAccountInsertSplit(investment_account, split); gnc_amount = gnc_ofx_numeric_from_double (ofx_get_investment_amount(&data), investment_commodity); gnc_units = gnc_ofx_numeric_from_double (data.units, investment_commodity); xaccSplitSetAmount(split, gnc_units); xaccSplitSetValue(split, gnc_amount); /* set tran-num and/or split-action per book option */ if (data.check_number_valid) { gnc_set_num_action(transaction, split, data.check_number, NULL); } else if (data.reference_number_valid) { gnc_set_num_action(transaction, split, data.reference_number, NULL); } if (data.security_data_ptr->memo_valid) { xaccSplitSetMemo(split, data.security_data_ptr->memo); } if (data.fi_id_valid) { gnc_import_set_split_online_id(split, data.fi_id); } } else { if (investment_account) PERR("The investment account, units or unitprice was not found for the investment transaction"); } } else { PERR("Commodity not found for the investment transaction"); } if (data.invtransactiontype_valid && investment_account) { if (data.invtransactiontype == OFX_REINVEST || data.invtransactiontype == OFX_INCOME) { DEBUG("Now let's find an account for the destination split"); income_account = gnc_ofx_kvp_get_assoc_account(investment_account); if (income_account == NULL) { DEBUG("Couldn't find an associated income account"); investment_account_text = g_strdup_printf( /* This string is a default account name. It MUST NOT contain the character ':' anywhere in it or in any translations. */ _("Income account for security \"%s\""), data.security_data_ptr->secname); income_account = gnc_import_select_account( gnc_gen_trans_list_widget(gnc_ofx_importer_gui), NULL, 1, investment_account_text, currency, ACCT_TYPE_INCOME, NULL, NULL); gnc_ofx_kvp_set_assoc_account(investment_account, income_account); DEBUG("KVP written"); } else { DEBUG("Found at least one associated income account"); } } if (income_account != NULL && data.invtransactiontype == OFX_REINVEST) { DEBUG("Adding investment split; Money flows from the income account"); split = xaccMallocSplit(book); xaccTransAppendSplit(transaction, split); xaccAccountInsertSplit(income_account, split); gnc_amount = gnc_ofx_numeric_from_double_txn (data.amount, transaction); xaccSplitSetBaseValue(split, gnc_amount, xaccTransGetCurrency(transaction)); // Set split memo from ofx transaction name or memo gnc_ofx_set_split_memo(&data, split); } if (income_account != NULL && data.invtransactiontype == OFX_INCOME) { DEBUG("Adding investment split; Money flows from the income account"); split = xaccMallocSplit(book); xaccTransAppendSplit(transaction, split); xaccAccountInsertSplit(income_account, split); gnc_amount = gnc_ofx_numeric_from_double_txn (-data.amount,/*OFX_INCOME amounts come in as positive numbers*/ transaction); xaccSplitSetBaseValue(split, gnc_amount, xaccTransGetCurrency(transaction)); // Set split memo from ofx transaction name or memo gnc_ofx_set_split_memo(&data, split); } } if (data.invtransactiontype_valid && data.invtransactiontype != OFX_REINVEST) { DEBUG("Adding investment split; Money flows from or to the cash account"); split = xaccMallocSplit(book); xaccTransAppendSplit(transaction, split); xaccAccountInsertSplit(account, split); gnc_amount = gnc_ofx_numeric_from_double_txn( -ofx_get_investment_amount(&data), transaction); xaccSplitSetBaseValue(split, gnc_amount, xaccTransGetCurrency(transaction)); // Set split memo from ofx transaction name or memo gnc_ofx_set_split_memo(&data, split); } } /* Send transaction to importer GUI. */ if (xaccTransCountSplits(transaction) > 0) { DEBUG("%d splits sent to the importer gui", xaccTransCountSplits(transaction)); gnc_gen_trans_list_add_trans (gnc_ofx_importer_gui, transaction); } else { PERR("No splits in transaction (missing account?), ignoring."); xaccTransDestroy(transaction); xaccTransCommitEdit(transaction); } } else { PERR("The transaction doesn't have a valid amount"); xaccTransDestroy(transaction); xaccTransCommitEdit(transaction); } return 0; }//end ofx_proc_transaction()