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; }
static void gnc_split_register_save_num_cell (BasicCell * cell, gpointer save_data, gpointer user_data) { SRSaveData *sd = save_data; SplitRegister *reg = user_data; const char *value; g_return_if_fail (gnc_basic_cell_has_name (cell, NUM_CELL)); value = gnc_basic_cell_get_value (cell); DEBUG ("NUM: %s\n", value ? value : "(null)"); xaccTransSetNum (sd->trans, value); if (gnc_num_cell_set_last_num ((NumCell *) cell, value)) { SRInfo *info = gnc_split_register_get_info (reg); Split *blank_split = xaccSplitLookup (&info->blank_split_guid, gnc_get_current_book ()); Transaction *blank_trans = xaccSplitGetParent (blank_split); if (sd->trans == blank_trans) gnc_split_register_set_last_num (reg, gnc_basic_cell_get_value (cell)); } }
/** 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_RND_ROUND); /* 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; /* 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: xaccTransSetDatePostedSecs(trans_line->trans, *((time_t*)(prop->value))); break; case GNC_CSV_DESCRIPTION: xaccTransSetDescription(trans_line->trans, (char*)(prop->value)); break; case GNC_CSV_NUM: xaccTransSetNum(trans_line->trans, (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_RND_ROUND); 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_RND_ROUND); 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); return trans_line; }
/* 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); } } } }