// Split line start static gchar* begin_split_string (Transaction *trans, Split *split, gboolean t_void, CsvExportInfo *info) { const gchar *str_rec_date; const gchar *start; gchar *conv; gchar *result; Timespec ts = {0,0}; if (xaccSplitGetReconcile (split) == YREC) { xaccSplitGetDateReconciledTS (split, &ts); str_rec_date = gnc_print_date (ts); } else str_rec_date = ""; if (t_void) { start = xaccTransGetVoidReason (trans) ? xaccTransGetVoidReason (trans) : "" ; conv = csv_txn_test_field_string (info, start); result = g_strconcat (info->end_sep, info->mid_sep, info->mid_sep, str_rec_date, info->mid_sep, info->mid_sep, info->mid_sep, info->mid_sep, conv, info->mid_sep, NULL); g_free (conv); } else result = g_strconcat (info->end_sep, info->mid_sep, info->mid_sep, str_rec_date, info->mid_sep, info->mid_sep, info->mid_sep, info->mid_sep, info->mid_sep, NULL); return result; }
static /*@ dependent @*//*@ null @*/ gpointer get_split_reconcile_state( gpointer pObject ) { static gchar c[2]; g_return_val_if_fail( pObject != NULL, NULL ); g_return_val_if_fail( GNC_IS_SPLIT(pObject), NULL ); c[0] = xaccSplitGetReconcile( GNC_SPLIT(pObject) ); c[1] = '\0'; return (gpointer)c; }
// Reconcile static gchar* add_reconcile (gchar *so_far, Split *split, CsvExportInfo *info) { const gchar *recon; gchar *conv; gchar *result; recon = gnc_get_reconcile_str (xaccSplitGetReconcile (split)); conv = csv_txn_test_field_string (info, recon); result = g_strconcat (so_far, conv, info->mid_sep, NULL); g_free (conv); g_free (so_far); return result; }
GtkWidget * gnc_reconcile_view_new (Account *account, GNCReconcileViewType type, time64 statement_date) { GNCReconcileView *view; GtkListStore *liststore; gboolean include_children, auto_check; GList *accounts = NULL; GList *splits; Query *query; g_return_val_if_fail (account, NULL); g_return_val_if_fail ((type == RECLIST_DEBIT) || (type == RECLIST_CREDIT), NULL); view = g_object_new (GNC_TYPE_RECONCILE_VIEW, NULL); /* Create the list store with 6 columns and add to treeview, column 0 will be a pointer to the entry */ liststore = gtk_list_store_new (6, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN ); gtk_tree_view_set_model (GTK_TREE_VIEW (view), GTK_TREE_MODEL (liststore)); g_object_unref (liststore); view->account = account; view->view_type = type; view->statement_date = statement_date; query = qof_query_create_for (GNC_ID_SPLIT); qof_query_set_book (query, gnc_get_current_book ()); include_children = xaccAccountGetReconcileChildrenStatus (account); if (include_children) accounts = gnc_account_get_descendants (account); /* match the account */ accounts = g_list_prepend (accounts, account); xaccQueryAddAccountMatch (query, accounts, QOF_GUID_MATCH_ANY, QOF_QUERY_AND); g_list_free (accounts); /* limit the matches to CREDITs and DEBITs only, depending on the type */ if (type == RECLIST_CREDIT) xaccQueryAddValueMatch(query, gnc_numeric_zero (), QOF_NUMERIC_MATCH_CREDIT, QOF_COMPARE_GTE, QOF_QUERY_AND); else xaccQueryAddValueMatch(query, gnc_numeric_zero (), QOF_NUMERIC_MATCH_DEBIT, QOF_COMPARE_GTE, QOF_QUERY_AND); /* limit the matches only to Cleared and Non-reconciled splits */ xaccQueryAddClearedMatch (query, CLEARED_NO | CLEARED_CLEARED, QOF_QUERY_AND); /* Initialize the QueryList */ gnc_reconcile_view_construct (view, query); /* find the list of splits to auto-reconcile */ auto_check = gnc_prefs_get_bool (GNC_PREFS_GROUP_RECONCILE, GNC_PREF_CHECK_CLEARED); if (auto_check) { time64 statement_date_day_end = gnc_time64_get_day_end(statement_date); for (splits = qof_query_run (query); splits; splits = splits->next) { Split *split = splits->data; char recn = xaccSplitGetReconcile (split); time64 trans_date = xaccTransGetDate (xaccSplitGetParent (split)); /* Just an extra verification that our query is correct ;) */ g_assert (recn == NREC || recn == CREC); if (recn == CREC && gnc_difftime (trans_date, statement_date_day_end) <= 0) g_hash_table_insert (view->reconciled, split, split); } } /* Free the query -- we don't need it anymore */ qof_query_destroy (query); return GTK_WIDGET (view); }
/******************************************************* * account_splits * * gather the splits / transactions for an account and * send them to a file *******************************************************/ static void account_splits (CsvExportInfo *info, Account *acc, FILE *fh ) { Query *q; GSList *p1, *p2; GList *splits; QofBook *book; gchar *end_sep; gchar *mid_sep; q = qof_query_create_for(GNC_ID_SPLIT); book = gnc_get_current_book(); qof_query_set_book (q, book); /* Set up separators */ if (info->use_quotes) { end_sep = "\""; mid_sep = g_strconcat ( "\"", info->separator_str, "\"", NULL); } else { end_sep = ""; mid_sep = g_strconcat ( info->separator_str, NULL); } /* Sort by transaction date */ p1 = g_slist_prepend (NULL, TRANS_DATE_POSTED); p1 = g_slist_prepend (p1, SPLIT_TRANS); p2 = g_slist_prepend (NULL, QUERY_DEFAULT_SORT); qof_query_set_sort_order (q, p1, p2, NULL); xaccQueryAddSingleAccountMatch (q, acc, QOF_QUERY_AND); xaccQueryAddDateMatchTT (q, TRUE, info->csvd.start_time, TRUE, info->csvd.end_time, QOF_QUERY_AND); /* Run the query */ for (splits = qof_query_run(q); splits; splits = splits->next) { Split *split; Transaction *trans; SplitList *s_list; GList *node; Split *t_split; int nSplits; int cnt; gchar *part1; gchar *part2; gchar *date; const gchar *currentSel; const gchar *split_amount; split = splits->data; trans = xaccSplitGetParent(split); nSplits = xaccTransCountSplits(trans); s_list = xaccTransGetSplitList(trans); /* Date */ date = qof_print_date ( xaccTransGetDate(trans)); part1 = g_strconcat ( end_sep, date, mid_sep, NULL); g_free(date); /* Name */ currentSel = xaccAccountGetName(acc); part2 = g_strconcat ( part1, currentSel, mid_sep, NULL); g_free(part1); /* Number */ currentSel = gnc_get_num_action(trans, NULL); part1 = g_strconcat ( part2, currentSel, mid_sep, NULL); g_free(part2); /* Description */ currentSel = xaccTransGetDescription(trans); part2 = g_strconcat ( part1, currentSel, mid_sep, NULL); g_free(part1); /* Notes */ currentSel = xaccTransGetNotes(trans); if (currentSel == NULL) part1 = g_strconcat ( part2, mid_sep, NULL); else part1 = g_strconcat ( part2, currentSel, mid_sep, NULL); g_free(part2); /* Memo */ currentSel = xaccSplitGetMemo(split); part2 = g_strconcat ( part1, currentSel, mid_sep, NULL); g_free(part1); /* Category */ currentSel = xaccSplitGetCorrAccountName(split); part1 = g_strconcat ( part2, currentSel, mid_sep, "T", mid_sep, NULL); g_free(part2); /* Action */ currentSel = gnc_get_num_action(NULL, split); part2 = g_strconcat ( part1, currentSel, mid_sep, NULL); g_free(part1); /* Reconcile */ switch (xaccSplitGetReconcile (split)) { case NREC: currentSel = "N"; break; case CREC: currentSel = "C"; break; case YREC: currentSel = "Y"; break; case FREC: currentSel = "F"; break; case VREC: currentSel = "V"; break; default: currentSel = "N"; } part1 = g_strconcat ( part2, currentSel, mid_sep, NULL); g_free(part2); /* To with Symbol */ split_amount = xaccPrintAmount(xaccSplitGetAmount(split), gnc_split_amount_print_info(split, TRUE)); part2 = g_strconcat ( part1, split_amount, mid_sep, NULL); g_free(part1); /* From with Symbol */ part1 = g_strconcat ( part2, "", mid_sep, NULL); g_free(part2); /* To Number Only */ split_amount = xaccPrintAmount(xaccSplitGetAmount(split), gnc_split_amount_print_info(split, FALSE)); part2 = g_strconcat ( part1, split_amount, mid_sep, NULL); g_free(part1); /* From Number Only */ part1 = g_strconcat ( part2, "", mid_sep, "", mid_sep, "", end_sep, "\n", NULL); g_free(part2); /* Write to file */ if (!write_line_to_file(fh, part1)) { info->failed = TRUE; break; } g_free(part1); /* Loop through the list of splits for the Transcation */ node = s_list; cnt = 0; while ( (cnt < nSplits) && (info->failed == FALSE)) { t_split = node->data; /* Start of line */ part1 = g_strconcat ( end_sep, mid_sep, mid_sep, mid_sep, mid_sep, mid_sep, NULL); /* Memo */ currentSel = xaccSplitGetMemo(t_split); part2 = g_strconcat ( part1, currentSel, mid_sep, NULL); g_free(part1); /* Account */ currentSel = xaccAccountGetName( xaccSplitGetAccount(t_split)); part1 = g_strconcat ( part2, currentSel, mid_sep, "S", mid_sep, NULL); g_free(part2); /* Action */ currentSel = gnc_get_num_action(NULL, t_split); part2 = g_strconcat ( part1, currentSel, mid_sep, NULL); g_free(part1); /* Reconcile */ switch (xaccSplitGetReconcile (split)) { case NREC: currentSel = "N"; break; case CREC: currentSel = "C"; break; case YREC: currentSel = "Y"; break; case FREC: currentSel = "F"; break; case VREC: currentSel = "V"; break; default: currentSel = "N"; } part1 = g_strconcat ( part2, currentSel, mid_sep, NULL); g_free(part2); /* From / To with Symbol */ split_amount = xaccPrintAmount(xaccSplitGetAmount(t_split), gnc_split_amount_print_info(t_split, TRUE)); if (xaccSplitGetAccount(t_split) == acc) part2 = g_strconcat ( part1, split_amount, mid_sep, mid_sep, NULL); else part2 = g_strconcat ( part1, mid_sep, split_amount, mid_sep, NULL); g_free(part1); /* From / To Numbers only */ split_amount = xaccPrintAmount(xaccSplitGetAmount(t_split), gnc_split_amount_print_info(t_split, FALSE)); if (xaccSplitGetAccount(t_split) == acc) part1 = g_strconcat ( part2, split_amount, mid_sep, mid_sep, NULL); else part1 = g_strconcat ( part2, mid_sep, split_amount, mid_sep, NULL); g_free(part2); /* From / To - Share Price / Conversion factor */ split_amount = xaccPrintAmount(xaccSplitGetSharePrice(t_split), gnc_split_amount_print_info(t_split, FALSE)); if (xaccSplitGetAccount(t_split) == acc) part2 = g_strconcat ( part1, split_amount, mid_sep, end_sep, "\n", NULL); else part2 = g_strconcat ( part1, mid_sep, split_amount, end_sep, "\n", NULL); g_free(part1); if (!write_line_to_file(fh, part2)) info->failed = TRUE; g_free(part2); cnt++; node = node->next; } } g_free(mid_sep); qof_query_destroy (q); g_list_free( splits ); }
gboolean gnc_tree_util_split_reg_rotate (GncTreeViewSplitReg *view, GtkTreeViewColumn *col, Transaction *trans, Split *split) { GtkCellRenderer *cr0 = NULL; GList *renderers; ViewCol viewcol; // Get the first renderer, it has the view-column value. renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (col)); cr0 = g_list_nth_data (renderers, 0); g_list_free (renderers); viewcol = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cr0), "view_column")); if (viewcol == COL_RECN) { const char recn_flags[] = {NREC, CREC, 0}; // List of reconciled flags const gchar *flags; const gchar *text; gchar *this_flag; gint index = 0; char rec; flags = recn_flags; text = g_strdup_printf("%c", xaccSplitGetReconcile (split)); /* Find the existing text in the list of flags */ this_flag = strstr (flags, text); if (this_flag != NULL && *this_flag != '\0') { /* In the list, choose the next item in the list (wrapping around as necessary). */ index = this_flag - flags; if (flags[index + 1] != '\0') index = index + 1; else index = 0; rec = recn_flags[index]; } else rec = NREC; gnc_tree_view_split_reg_set_dirty_trans (view, trans); if (!xaccTransIsOpen (trans)) xaccTransBeginEdit (trans); xaccSplitSetReconcile (split, rec); return TRUE; } if (viewcol == COL_TYPE) { const char type_flags[] = {TXN_TYPE_INVOICE, TXN_TYPE_PAYMENT, 0}; // list of type flags const gchar *flags; const gchar *text; gchar *this_flag; gint index = 0; char type; flags = type_flags; text = g_strdup_printf("%c", xaccTransGetTxnType (trans)); /* Find the existing text in the list of flags */ this_flag = strstr (flags, text); if (this_flag != NULL && *this_flag != '\0') { /* In the list, choose the next item in the list (wrapping around as necessary). */ index = this_flag - flags; if (flags[index + 1] != '\0') index = index + 1; else index = 0; type = type_flags[index]; } else type = TXN_TYPE_NONE; gnc_tree_view_split_reg_set_dirty_trans (view, trans); if (!xaccTransIsOpen (trans)) xaccTransBeginEdit (trans); xaccTransSetTxnType (trans, type); return TRUE; } return FALSE; }
static const char* equals_node_val_vs_split_internal (xmlNodePtr node, Split* spl) { xmlNodePtr mark; for (mark = node->children; mark != NULL; mark = mark->next) { if (g_strcmp0 ((char*)mark->name, "split:id") == 0) { GncGUID* id = dom_tree_to_guid (mark); if (!guid_equal (id, xaccSplitGetGUID (spl))) { g_free (id); return "ids differ"; } g_free (id); } else if (g_strcmp0 ((char*)mark->name, "split:memo") == 0) { char* memo = dom_tree_to_text (mark); if (g_strcmp0 (memo, xaccSplitGetMemo (spl)) != 0) { g_free (memo); return "memos differ"; } g_free (memo); } else if (g_strcmp0 ((char*)mark->name, "split:reconciled-state") == 0) { char* rs = dom_tree_to_text (mark); if (rs[0] != xaccSplitGetReconcile (spl)) { g_free (rs); return "states differ"; } g_free (rs); } else if (g_strcmp0 ((char*)mark->name, "split:value") == 0) { gnc_numeric* num = dom_tree_to_gnc_numeric (mark); gnc_numeric val = xaccSplitGetValue (spl); if (!gnc_numeric_equal (*num, val)) { g_free (num); return g_strdup_printf ("values differ: %" G_GINT64_FORMAT "/%" G_GINT64_FORMAT " v %" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, (*num).num, (*num).denom, val.num, val.denom); } g_free (num); } else if (g_strcmp0 ((char*)mark->name, "split:quantity") == 0) { gnc_numeric* num = dom_tree_to_gnc_numeric (mark); gnc_numeric val = xaccSplitGetAmount (spl); if (!gnc_numeric_equal (*num, val)) { return g_strdup_printf ("quantities differ under _equal: %" G_GINT64_FORMAT "/%" G_GINT64_FORMAT " v %" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, (*num).num, (*num).denom, val.num, val.denom); } if (!gnc_numeric_equal (*num, val)) { g_free (num); return g_strdup_printf ("quantities differ: %" G_GINT64_FORMAT "/%" G_GINT64_FORMAT " v %" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, (*num).num, (*num).denom, val.num, val.denom); } g_free (num); } else if (g_strcmp0 ((char*)mark->name, "split:account") == 0) { GncGUID* id = dom_tree_to_guid (mark); Account* account = xaccSplitGetAccount (spl); if (!guid_equal (id, xaccAccountGetGUID (account))) { g_free (id); return "accounts differ"; } g_free (id); } } return NULL; }
static xmlNodePtr split_to_dom_tree(const gchar *tag, Split *spl) { xmlNodePtr ret; ret = xmlNewNode(NULL, BAD_CAST tag); xmlAddChild(ret, guid_to_dom_tree("split:id", xaccSplitGetGUID(spl))); { char *memo = g_strdup (xaccSplitGetMemo(spl)); if (memo && g_strcmp0(memo, "") != 0) { xmlNewTextChild(ret, NULL, BAD_CAST "split:memo", checked_char_cast (memo)); } g_free (memo); } { char *action = g_strdup (xaccSplitGetAction(spl)); if (action && g_strcmp0(action, "") != 0) { xmlNewTextChild(ret, NULL, BAD_CAST "split:action", checked_char_cast (action)); } g_free (action); } { char tmp[2]; tmp[0] = xaccSplitGetReconcile(spl); tmp[1] = '\0'; xmlNewTextChild(ret, NULL, BAD_CAST "split:reconciled-state", BAD_CAST tmp); } add_timespec(ret, "split:reconcile-date", xaccSplitRetDateReconciledTS(spl), FALSE); add_gnc_num(ret, "split:value", xaccSplitGetValue(spl)); add_gnc_num(ret, "split:quantity", xaccSplitGetAmount(spl)); { Account * account = xaccSplitGetAccount (spl); xmlAddChild (ret, guid_to_dom_tree("split:account", xaccAccountGetGUID (account))); } { GNCLot * lot = xaccSplitGetLot (spl); if (lot) { xmlAddChild (ret, guid_to_dom_tree("split:lot", gnc_lot_get_guid(lot))); } } { xmlNodePtr kvpnode = kvp_frame_to_dom_tree("split:slots", xaccSplitGetSlots(spl)); if (kvpnode) { xmlAddChild(ret, kvpnode); } } return ret; }
char getReconcile() const { return xaccSplitGetReconcile(get()); }
void gnc_autoclear_window_ok_cb (GtkWidget *widget, AutoClearWindow *data) { GList *node, *nc_list = 0, *toclear_list = 0; gnc_numeric toclear_value; GHashTable *sack; gtk_label_set_text(data->status_label, _("Searching for splits to clear ...")); /* Value we have to reach */ toclear_value = gnc_amount_edit_get_amount(data->end_value); toclear_value = gnc_numeric_convert(toclear_value, xaccAccountGetCommoditySCU(data->account), GNC_HOW_RND_NEVER); /* Extract which splits are not cleared and compute the amount we have to clear */ for (node = xaccAccountGetSplitList(data->account); node; node = node->next) { Split *split = (Split *)node->data; char recn; gnc_numeric value; recn = xaccSplitGetReconcile (split); value = xaccSplitGetAmount (split); if (recn == NREC) nc_list = g_list_append(nc_list, split); else toclear_value = gnc_numeric_sub_fixed(toclear_value, value); } /* Pretty print information */ PINFO("Amount to clear: %s\n", gnc_numeric_to_string(toclear_value)); PINFO("Available splits:\n"); for (node = nc_list; node; node = node->next) { Split *split = (Split *)node->data; gnc_numeric value = xaccSplitGetAmount (split); PINFO(" %s\n", gnc_numeric_to_string(value)); } /* Run knapsack */ /* Entries in the hash table are: * - key = amount to which we know how to clear (freed by GHashTable) * - value = last split we used to clear this amount (not managed by GHashTable) */ PINFO("Knapsacking ...\n"); sack = g_hash_table_new_full (ght_gnc_numeric_hash, ght_gnc_numeric_equal, g_free, NULL); for (node = nc_list; node; node = node->next) { Split *split = (Split *)node->data; gnc_numeric split_value = xaccSplitGetAmount(split); GList *node; struct _sack_foreach_data_t data[1]; data->split_value = split_value; data->reachable_list = 0; PINFO(" Split value: %s\n", gnc_numeric_to_string(split_value)); /* For each value in the sack, compute a new reachable value */ g_hash_table_foreach (sack, sack_foreach_func, data); /* Add the value of the split itself to the reachable_list */ data->reachable_list = g_list_append(data->reachable_list, g_memdup(&split_value, sizeof(gnc_numeric))); /* Add everything to the sack, looking out for duplicates */ for (node = data->reachable_list; node; node = node->next) { gnc_numeric *reachable_value = node->data; Split *toinsert_split = split; PINFO(" Reachable value: %s ", gnc_numeric_to_string(*reachable_value)); /* Check if it already exists */ if (g_hash_table_lookup_extended(sack, reachable_value, NULL, NULL)) { /* If yes, we are in trouble, we reached an amount using two solutions */ toinsert_split = NULL; PINFO("dup"); } g_hash_table_insert (sack, reachable_value, toinsert_split); PINFO("\n"); } g_list_free(data->reachable_list); } /* Check solution */ PINFO("Rebuilding solution ...\n"); while (!gnc_numeric_zero_p(toclear_value)) { gpointer psplit = NULL; PINFO(" Left to clear: %s\n", gnc_numeric_to_string(toclear_value)); if (g_hash_table_lookup_extended(sack, &toclear_value, NULL, &psplit)) { if (psplit != NULL) { /* Cast the gpointer to the kind of pointer we actually need */ Split *split = (Split *)psplit; toclear_list = g_list_prepend(toclear_list, split); toclear_value = gnc_numeric_sub_fixed(toclear_value, xaccSplitGetAmount(split)); PINFO(" Cleared: %s -> %s\n", gnc_numeric_to_string(xaccSplitGetAmount(split)), gnc_numeric_to_string(toclear_value)); } else { /* We couldn't reconstruct the solution */ PINFO(" Solution not unique.\n"); gtk_label_set_text(data->status_label, _("Cannot uniquely clear splits. Found multiple possibilities.")); return; } } else { PINFO(" No solution found.\n"); gtk_label_set_text(data->status_label, _("The selected amount cannot be cleared.")); return; } } g_hash_table_destroy (sack); /* Show solution */ PINFO("Clearing splits:\n"); for (node = toclear_list; node; node = node->next) { Split *split = node->data; char recn; gnc_numeric value; recn = xaccSplitGetReconcile (split); value = xaccSplitGetAmount (split); PINFO(" %c %s\n", recn, gnc_numeric_to_string(value)); xaccSplitSetReconcile (split, CREC); } if (toclear_list == 0) PINFO(" None\n"); /* Free lists */ g_list_free(nc_list); g_list_free(toclear_list); /* Close window */ gtk_widget_destroy(data->window); g_free(data); }
static xmlNodePtr split_to_dom_tree (const gchar* tag, Split* spl) { xmlNodePtr ret; ret = xmlNewNode (NULL, BAD_CAST tag); xmlAddChild (ret, guid_to_dom_tree ("split:id", xaccSplitGetGUID (spl))); { char* memo = g_strdup (xaccSplitGetMemo (spl)); if (memo && g_strcmp0 (memo, "") != 0) { xmlNewTextChild (ret, NULL, BAD_CAST "split:memo", checked_char_cast (memo)); } g_free (memo); } { char* action = g_strdup (xaccSplitGetAction (spl)); if (action && g_strcmp0 (action, "") != 0) { xmlNewTextChild (ret, NULL, BAD_CAST "split:action", checked_char_cast (action)); } g_free (action); } { char tmp[2]; tmp[0] = xaccSplitGetReconcile (spl); tmp[1] = '\0'; xmlNewTextChild (ret, NULL, BAD_CAST "split:reconciled-state", BAD_CAST tmp); } add_timespec (ret, "split:reconcile-date", xaccSplitRetDateReconciledTS (spl), FALSE); add_gnc_num (ret, "split:value", xaccSplitGetValue (spl)); add_gnc_num (ret, "split:quantity", xaccSplitGetAmount (spl)); { Account* account = xaccSplitGetAccount (spl); xmlAddChild (ret, guid_to_dom_tree ("split:account", xaccAccountGetGUID (account))); } { GNCLot* lot = xaccSplitGetLot (spl); if (lot) { xmlAddChild (ret, guid_to_dom_tree ("split:lot", gnc_lot_get_guid (lot))); } } /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */ xmlAddChild (ret, qof_instance_slots_to_dom_tree ("split:slots", QOF_INSTANCE (spl))); return ret; }