// Description
static gchar*
add_description (gchar *so_far, Transaction *trans, CsvExportInfo *info)
{
    const gchar *desc;
    gchar       *conv;
    gchar       *result;

    desc = xaccTransGetDescription (trans) ? xaccTransGetDescription (trans) : "" ;
    conv = csv_txn_test_field_string (info, desc);
    result = g_strconcat (so_far, conv, info->mid_sep, NULL);
    g_free (conv);
    g_free (so_far);
    return result;
}
예제 #2
0
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;
}
예제 #3
0
파일: Scrub2.c 프로젝트: Mechtilde/gnucash
gboolean
xaccScrubMergeSubSplits (Split *split, gboolean strict)
{
    gboolean rc = FALSE;
    Transaction *txn;
    SplitList *node;
    GNCLot *lot;

    if (strict && (FALSE == is_subsplit (split))) return FALSE;

    txn = split->parent;

    // Don't mess with splits from an invoice transaction
    // Those are the responsibility of the business code
    if (gncInvoiceGetInvoiceFromTxn (txn)) return FALSE;

    lot = xaccSplitGetLot (split);

    ENTER ("(Lot=%s)", gnc_lot_get_title(lot));
restart:
    for (node = txn->splits; node; node = node->next)
    {
        Split *s = node->data;
        if (xaccSplitGetLot (s) != lot) continue;
        if (s == split) continue;
        if (qof_instance_get_destroying(s)) continue;

        // Don't mess with splits from an invoice transaction
        // Those are the responsibility of the business code
        if (gncInvoiceGetInvoiceFromTxn (s->parent)) return FALSE;

        if (strict)
        {
            /* OK, this split is in the same lot (and thus same account)
             * as the indicated split.  Make sure it is really a subsplit
             * of the split we started with.  It's possible to have two
             * splits in the same lot and transaction that are not subsplits
             * of each other, the test-period test suite does this, for
             * example.  Only worry about adjacent sub-splits.  By
             * repeatedly merging adjacent subsplits, we'll get the non-
             * adjacent ones too. */
            if (!xaccSplitIsPeerSplit (split, s))
                continue;
        }

        merge_splits (split, s);
        rc = TRUE;
        goto restart;
    }
    if (rc && gnc_numeric_zero_p (split->amount))
    {
        time64 pdate = xaccTransGetDate (txn);
        gchar *pdatestr = gnc_ctime (&pdate);
        PWARN ("Result of merge has zero amt!");
        PWARN ("Transaction details - posted date %s - description %s", pdatestr, xaccTransGetDescription(txn));
        g_free (pdatestr);
    }
    LEAVE (" splits merged=%d", rc);
    return rc;
}
예제 #4
0
gboolean gnc_ui_payment_is_customer_payment(const Transaction *txn)
{
    SplitList *slist;
    gboolean result = TRUE;

    Split *assetaccount_split;
    gnc_numeric amount;

    if (!txn)
        return result;

    // We require the txn to have one split in an A/R or A/P account.

    slist = xaccTransGetSplitList(txn);
    if (!slist)
        return result;
    if (countAssetAccounts(slist) == 0)
    {
        g_message("No asset splits in txn \"%s\"; cannot use this for assigning a payment.",
                  xaccTransGetDescription(txn));
        return result;
    }

    assetaccount_split = getFirstAssetAccountSplit(slist);
    amount = xaccSplitGetValue(assetaccount_split);
    result = gnc_numeric_positive_p(amount); // positive amounts == customer
    //g_message("Amount=%s", gnc_numeric_to_string(amount));
    return result;
}
예제 #5
0
static void add_quickfill_completions(TableLayout *layout, Transaction *trans,
                                      Split *split, gboolean has_last_num)
{
    Split *s;
    int i = 0;

    gnc_quickfill_cell_add_completion(
        (QuickFillCell *) gnc_table_layout_get_cell(layout, DESC_CELL),
        xaccTransGetDescription(trans));

    gnc_quickfill_cell_add_completion(
        (QuickFillCell *) gnc_table_layout_get_cell(layout, NOTES_CELL),
        xaccTransGetNotes(trans));

    if (!has_last_num)
        gnc_num_cell_set_last_num(
            (NumCell *) gnc_table_layout_get_cell(layout, NUM_CELL),
            gnc_get_num_action(trans, split));

    while ((s = xaccTransGetSplit(trans, i)) != NULL)
    {
        gnc_quickfill_cell_add_completion(
            (QuickFillCell *) gnc_table_layout_get_cell(layout, MEMO_CELL),
            xaccSplitGetMemo(s));
        i++;
    }
}
예제 #6
0
xmlNodePtr
gnc_transaction_dom_tree_create(Transaction *trn)
{
    xmlNodePtr ret;
    gchar *str = NULL;

    ret = xmlNewNode(NULL, BAD_CAST "gnc:transaction");

    xmlSetProp(ret, BAD_CAST "version",
	       BAD_CAST transaction_version_string);

    xmlAddChild(ret, guid_to_dom_tree("trn:id", xaccTransGetGUID(trn)));

    xmlAddChild(ret, commodity_ref_to_dom_tree("trn:currency",
                xaccTransGetCurrency(trn)));
    str = g_strdup (xaccTransGetNum(trn));
    if (str && (g_strcmp0(str, "") != 0))
    {
        xmlNewTextChild(ret, NULL, BAD_CAST "trn:num",
			checked_char_cast (str));
    }
    g_free (str);

    add_timespec(ret, "trn:date-posted", xaccTransRetDatePostedTS(trn), TRUE);

    add_timespec(ret, "trn:date-entered",
                 xaccTransRetDateEnteredTS(trn), TRUE);

    str = g_strdup (xaccTransGetDescription(trn));
    if (str)
    {
        xmlNewTextChild(ret, NULL, BAD_CAST "trn:description",
                        checked_char_cast (str));
    }
    g_free (str);

    {
        xmlNodePtr kvpnode = kvp_frame_to_dom_tree("trn:slots",
                             xaccTransGetSlots(trn));
        if (kvpnode)
        {
            xmlAddChild(ret, kvpnode);
        }
    }

    add_trans_splits(ret, trn);

    return ret;
}
xmlNodePtr
gnc_transaction_dom_tree_create (Transaction* trn)
{
    xmlNodePtr ret;
    gchar* str = NULL;

    ret = xmlNewNode (NULL, BAD_CAST "gnc:transaction");

    xmlSetProp (ret, BAD_CAST "version",
                BAD_CAST transaction_version_string);

    xmlAddChild (ret, guid_to_dom_tree ("trn:id", xaccTransGetGUID (trn)));

    xmlAddChild (ret, commodity_ref_to_dom_tree ("trn:currency",
                                                 xaccTransGetCurrency (trn)));
    str = g_strdup (xaccTransGetNum (trn));
    if (str && (g_strcmp0 (str, "") != 0))
    {
        xmlNewTextChild (ret, NULL, BAD_CAST "trn:num",
                         checked_char_cast (str));
    }
    g_free (str);

    add_timespec (ret, "trn:date-posted", xaccTransRetDatePostedTS (trn), TRUE);

    add_timespec (ret, "trn:date-entered",
                  xaccTransRetDateEnteredTS (trn), TRUE);

    str = g_strdup (xaccTransGetDescription (trn));
    if (str)
    {
        xmlNewTextChild (ret, NULL, BAD_CAST "trn:description",
                         checked_char_cast (str));
    }
    g_free (str);

    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
    xmlAddChild (ret, qof_instance_slots_to_dom_tree ("trn:slots",
                                                      QOF_INSTANCE (trn)));

    add_trans_splits (ret, trn);

    return ret;
}
예제 #8
0
void
gncScrubBusinessSplit (Split *split)
{
    const gchar *memo = _("Please delete this transaction. Explanation at http://wiki.gnucash.org/wiki/Business_Features_Issues#Double_Posting");
    Transaction *txn;

    if (!split) return;
    ENTER ("(split=%p)", split);

    txn = xaccSplitGetParent (split);
    if (txn)
    {
        gchar txntype = xaccTransGetTxnType (txn);
        const gchar *read_only = xaccTransGetReadOnly (txn);
        gboolean is_void = xaccTransGetVoidStatus (txn);
        GNCLot *lot = xaccSplitGetLot (split);

        /* Look for transactions as a result of double posting an invoice or bill
         * Refer to https://bugzilla.gnome.org/show_bug.cgi?id=754209
         * to learn how this could have happened in the past.
         * Characteristics of such transaction are:
         * - read only
         * - not voided (to ensure read only is set by the business functions)
         * - transaction type is none (should be type invoice for proper post transactions)
         * - assigned to a lot
         */
        if ((txntype == TXN_TYPE_NONE) && read_only && !is_void && lot)
        {
            gchar *txn_date = qof_print_date (xaccTransGetDateEntered (txn));
            xaccTransClearReadOnly (txn);
            xaccSplitSetMemo (split, memo);
            gnc_lot_remove_split (lot, split);
            PWARN("Cleared double post status of transaction \"%s\", dated %s. "
                  "Please delete transaction and verify balance.",
                  xaccTransGetDescription (txn),
                  txn_date);
            g_free (txn_date);
        }

    }

    LEAVE ("(split=%p)", split);
}
static void
downloaded_transaction_changed_cb (GtkTreeSelection *selection,
                                   GNCImportMatchPicker *matcher)
{
    GNCImportMatchInfo * match_info;
    GtkTreeModel *dl_model;
    GtkListStore *match_store;
    GtkTreeIter iter;
    GList * list_element;
    gchar *text;
    const gchar *ro_text;
    /*DEBUG("row: %d%s%d",row,", column: ",column);*/

    /* Get the transaction info from the "downloaded" model.  */
    if (!gtk_tree_selection_get_selected(selection, &dl_model, &iter))
    {
        matcher->selected_trans_info = NULL;
        return;
    }
    gtk_tree_model_get(dl_model, &iter,
                       DOWNLOADED_COL_INFO_PTR, &matcher->selected_trans_info,
                       -1);

    /* Now rewrite the "match" model based on that trans. */
    match_store = GTK_LIST_STORE(gtk_tree_view_get_model(matcher->match_view));
    gtk_list_store_clear(match_store);
    list_element = g_list_first (gnc_import_TransInfo_get_match_list
                                 (matcher->selected_trans_info));
    while (list_element != NULL)
    {
        match_info = list_element->data;

        gtk_list_store_append(match_store, &iter);

        /* Print fields. */

        /* Probability */
        text = g_strdup_printf("%d", gnc_import_MatchInfo_get_probability (match_info));
        gtk_list_store_set(match_store, &iter, MATCHER_COL_CONFIDENCE, text, -1);
        g_free(text);

        /* Date */
        text =
            qof_print_date
            ( xaccTransGetDate
              ( xaccSplitGetParent
                ( gnc_import_MatchInfo_get_split(match_info) ) ));
        gtk_list_store_set(match_store, &iter, MATCHER_COL_DATE, text, -1);
        g_free(text);

        /* Amount */
        ro_text =
            xaccPrintAmount( xaccSplitGetAmount ( gnc_import_MatchInfo_get_split(match_info)  ),
                             gnc_split_amount_print_info(gnc_import_MatchInfo_get_split(match_info), TRUE)
                           );
        gtk_list_store_set(match_store, &iter, MATCHER_COL_AMOUNT, ro_text, -1);

        /*Description*/
        ro_text = xaccTransGetDescription
                  ( xaccSplitGetParent( gnc_import_MatchInfo_get_split(match_info)) );
        gtk_list_store_set(match_store, &iter, MATCHER_COL_DESCRIPTION, ro_text, -1);

        /*Split memo*/
        ro_text = xaccSplitGetMemo(gnc_import_MatchInfo_get_split(match_info) );
        gtk_list_store_set(match_store, &iter, MATCHER_COL_MEMO, ro_text, -1);

        gtk_list_store_set(match_store, &iter, MATCHER_COL_INFO_PTR, match_info, -1);
        if (gnc_import_MatchInfo_get_probability(match_info) != 0)
        {
            if (SHOW_NUMERIC_SCORE == TRUE)
            {
                gtk_list_store_set(match_store, &iter,
                                   MATCHER_COL_CONFIDENCE_PIXBUF,
                                   gen_probability_pixbuf(gnc_import_MatchInfo_get_probability(match_info),
                                           matcher->user_settings,
                                           GTK_WIDGET(matcher->match_view)),
                                   -1);
            }
            else
            {
                gtk_list_store_set(match_store, &iter,
                                   MATCHER_COL_CONFIDENCE_PIXBUF,
                                   gen_probability_pixbuf(gnc_import_MatchInfo_get_probability(match_info),
                                           matcher->user_settings,
                                           GTK_WIDGET(matcher->match_view)),
                                   -1);
            }
        }

        if (match_info ==
                gnc_import_TransInfo_get_selected_match (matcher->selected_trans_info))
        {
            GtkTreeSelection *selection;

            selection = gtk_tree_view_get_selection(matcher->match_view);
            gtk_tree_selection_select_iter(selection, &iter);
        }

        list_element = g_list_next(list_element);
    }
}
예제 #10
0
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;
}
예제 #11
0
/* Either sets the value and amount for split and returns TRUE, or
   does nothing and returns FALSE. */
static gboolean
gtu_sr_handle_exchange_rate (GncTreeViewSplitReg *view, gnc_numeric amount, Transaction *trans, Split *split, gboolean force)
{
    GncTreeModelSplitReg *model;
    XferDialog *xfer;
    gboolean rate_split_ok, rate_reg_ok;
    gnc_numeric rate_split, rate_reg, value;
    Account *reg_acc;
    gnc_commodity *xfer_comm = xaccAccountGetCommodity (xaccSplitGetAccount (split));
    gnc_commodity *reg_comm = gnc_tree_view_split_reg_get_reg_commodity (view);
    gnc_commodity *trans_curr = xaccTransGetCurrency (trans);
    gboolean expanded;
    gboolean have_rate = TRUE;

    ENTER("handle_exchange_rate amount %s, trans %p and split %p force %d", gnc_numeric_to_string (amount), trans, split, force);


    model = gnc_tree_view_split_reg_get_model_from_view (view);

    reg_acc = gnc_tree_model_split_reg_get_anchor (model);

    /* Rate from trans-curr to split-comm */
    rate_split_ok = xaccTransGetRateForCommodity (trans, xfer_comm, split, &rate_split);
    DEBUG("rate_split_ok %d and xfer_comm %s", rate_split_ok, gnc_commodity_get_fullname (xfer_comm));

    /* Rate from trans-curr to reg-comm */
    rate_reg_ok = xaccTransGetRateForCommodity (trans, reg_comm, split, &rate_reg);
    DEBUG("rate_reg_ok %d and reg_comm %s", rate_reg_ok, gnc_commodity_get_fullname (reg_comm));

    /* Are we expanded */
    expanded = gnc_tree_view_split_reg_trans_expanded (view, trans);

    if (gnc_commodity_equal (trans_curr, xfer_comm) && rate_split_ok)
    {
        xaccSplitSetAmount (split, amount);
        xaccSplitSetValue (split, amount);
        return TRUE;
    }

    if (rate_reg_ok && rate_split_ok && !force)
    {
        value = gnc_numeric_div (amount, rate_reg, gnc_commodity_get_fraction (trans_curr), GNC_HOW_DENOM_REDUCE);
        amount = gnc_numeric_mul (value, rate_split, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND);
    }
    else
    {
        if (!rate_split_ok)
            rate_split = gtu_sr_get_rate_from_db (reg_comm, xfer_comm);

        /* create the exchange-rate dialog */
        xfer = gnc_xfer_dialog (NULL, NULL);

        gnc_xfer_dialog_is_exchange_dialog (xfer, &rate_split);

        /* fill in the dialog entries */
        gnc_xfer_dialog_set_description (xfer, xaccTransGetDescription (trans));
        gnc_xfer_dialog_set_memo (xfer, xaccSplitGetMemo (split));

        /* Get per book option */
        gnc_xfer_dialog_set_num (xfer, gnc_get_num_action (trans, split));
        gnc_xfer_dialog_set_date (xfer, timespecToTime64 (xaccTransRetDatePostedTS (trans)));

        value = amount;
        if (gnc_xfer_dialog_run_exchange_dialog (xfer, &rate_split, value, reg_acc, trans, xfer_comm, expanded))
        {
            if (!rate_split_ok)
                rate_split = gnc_numeric_create (1, 1);
            have_rate = FALSE;
        }
        else
            have_rate = TRUE;

        amount = gnc_numeric_mul (value, rate_split, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND);
    }
    xaccSplitSetAmount (split, amount);
    xaccSplitSetValue (split, value);

    LEAVE("handle_exchange_rate set split %p amt=%s; and val=%s", split, gnc_numeric_to_string (amount), gnc_numeric_to_string (value));
    return have_rate;
}
static const char*
node_and_transaction_equal (xmlNodePtr node, Transaction* trn)
{
    xmlNodePtr mark;

    while (g_strcmp0 ((char*)node->name, "text") == 0)
        node = node->next;

    if (!check_dom_tree_version (node, "2.0.0"))
    {
        return "version wrong.  Not 2.0.0 or not there";
    }

    if (!node->name || g_strcmp0 ((char*)node->name, "gnc:transaction"))
    {
        return "Name of toplevel node is bad";
    }

    for (mark = node->xmlChildrenNode; mark; mark = mark->next)
    {
        if (g_strcmp0 ((char*)mark->name, "text") == 0)
        {
        }
        else if (g_strcmp0 ((char*)mark->name, "trn:id") == 0)
        {
            if (!equals_node_val_vs_guid (mark, xaccTransGetGUID (trn)))
            {
                return "ids differ";
            }
        }

        /* This test will fail for many splits where the transaction has
         * splits in different commodities -- eg, buying or selling a
         * stock. jralls 2010-11-02 */
        else if (g_strcmp0 ((char*)mark->name, "trn:currency") == 0)
        {
#if 0
            if (!equals_node_val_vs_commodity (
                    mark, xaccTransGetCurrency (trn), xaccTransGetBook (trn)))
            {
                return g_strdup ("currencies differ");
            }
#endif
        }
        else if (g_strcmp0 ((char*)mark->name, "trn:num") == 0)
        {
            if (!equals_node_val_vs_string (mark, xaccTransGetNum (trn)))
            {
                return "nums differ";
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "trn:date-posted") == 0)
        {
            if (!equals_node_val_vs_date (mark, xaccTransRetDatePostedTS (trn)))
            {
                return "posted dates differ";
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "trn:date-entered") == 0)
        {
            if (!equals_node_val_vs_date (mark, xaccTransRetDateEnteredTS (trn)))
            {
                return "entered dates differ";
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "trn:description") == 0)
        {
            if (!equals_node_val_vs_string (mark, xaccTransGetDescription (trn)))
            {
                return "descriptions differ";
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "trn:slots") == 0)
        {
            if (!equals_node_val_vs_kvp_frame (mark,
                                               qof_instance_get_slots (QOF_INSTANCE (trn))))
            {
                return "slots differ";
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "trn:splits") == 0)
        {
            const char* msg = equals_node_val_vs_splits (mark, trn);
            if (msg != NULL)
            {
                return msg;
            }
        }
        else
        {
            return "unknown node";
        }
    }

    return NULL;
}
예제 #13
0
/*******************************************************
 * 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 );
}
예제 #14
0
void
xaccLotScrubDoubleBalance (GNCLot *lot)
{
    gnc_commodity *currency = NULL;
    SplitList *snode;
    GList *node;
    gnc_numeric zero = gnc_numeric_zero();
    gnc_numeric value = zero;

    if (!lot) return;

    ENTER ("lot=%s", kvp_frame_get_string (gnc_lot_get_slots (lot), "/title"));

    for (snode = gnc_lot_get_split_list(lot); snode; snode = snode->next)
    {
        Split *s = snode->data;
        xaccSplitComputeCapGains (s, NULL);
    }

    /* We double-check only closed lots */
    if (FALSE == gnc_lot_is_closed (lot)) return;

    for (snode = gnc_lot_get_split_list(lot); snode; snode = snode->next)
    {
        Split *s = snode->data;
        Transaction *trans = s->parent;

        /* Check to make sure all splits in the lot have a common currency */
        if (NULL == currency)
        {
            currency = trans->common_currency;
        }
        if (FALSE == gnc_commodity_equiv (currency, trans->common_currency))
        {
            /* This lot has mixed currencies. Can't double-balance.
             * Silently punt */
            PWARN ("Lot with multiple currencies:\n"
                   "\ttrans=%s curr=%s", xaccTransGetDescription(trans),
                   gnc_commodity_get_fullname(trans->common_currency));
            break;
        }

        /* Now, total up the values */
        value = gnc_numeric_add (value, xaccSplitGetValue (s),
                                 GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);
        PINFO ("Split=%p value=%s Accum Lot value=%s", s,
               gnc_num_dbg_to_string (s->value),
               gnc_num_dbg_to_string (value));

    }

    if (FALSE == gnc_numeric_equal (value, zero))
    {
        /* Unhandled error condition. Not sure what to do here,
         * Since the ComputeCapGains should have gotten it right.
         * I suppose there might be small rounding errors, a penny or two,
         * the ideal thing would to figure out why there's a rounding
         * error, and fix that.
         */
        PERR ("Closed lot fails to double-balance !! lot value=%s",
              gnc_num_dbg_to_string (value));
        for (node = gnc_lot_get_split_list(lot); node; node = node->next)
        {
            Split *s = node->data;
            PERR ("s=%p amt=%s val=%s", s,
                  gnc_num_dbg_to_string(s->amount),
                  gnc_num_dbg_to_string(s->value));
        }
    }

    LEAVE ("lot=%s", kvp_frame_get_string (gnc_lot_get_slots (lot), "/title"));
}
예제 #15
0
void
xaccScrubSubSplitPrice (Split *split, int maxmult, int maxamtscu)
{
    gnc_numeric src_amt, src_val;
    SplitList *node;

    if (FALSE == is_subsplit (split)) return;

    ENTER (" ");
    /* Get 'price' of the indicated split */
    src_amt = xaccSplitGetAmount (split);
    src_val = xaccSplitGetValue (split);

    /* Loop over splits, adjust each so that it has the same
     * ratio (i.e. price).  Change the value to get things
     * right; do not change the amount */
    for (node = split->parent->splits; node; node = node->next)
    {
        Split *s = node->data;
        Transaction *txn = s->parent;
        gnc_numeric dst_amt, dst_val, target_val;
        gnc_numeric frac, delta;
        int scu;

        /* Skip the reference split */
        if (s == split) continue;

        scu = gnc_commodity_get_fraction (txn->common_currency);

        dst_amt = xaccSplitGetAmount (s);
        dst_val = xaccSplitGetValue (s);
        frac = gnc_numeric_div (dst_amt, src_amt,
                                GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
        target_val = gnc_numeric_mul (frac, src_val,
                                      scu, GNC_HOW_DENOM_EXACT | GNC_HOW_RND_ROUND_HALF_UP);
        if (gnc_numeric_check (target_val))
        {
            PERR ("Numeric overflow of value\n"
                  "\tAcct=%s txn=%s\n"
                  "\tdst_amt=%s src_val=%s src_amt=%s\n",
                  xaccAccountGetName (s->acc),
                  xaccTransGetDescription(txn),
                  gnc_num_dbg_to_string(dst_amt),
                  gnc_num_dbg_to_string(src_val),
                  gnc_num_dbg_to_string(src_amt));
            continue;
        }

        /* If the required price changes are 'small', do nothing.
         * That is a case that the user will have to deal with
         * manually.  This routine is really intended only for
         * a gross level of synchronization.
         */
        delta = gnc_numeric_sub_fixed (target_val, dst_val);
        delta = gnc_numeric_abs (delta);
        if (maxmult * delta.num  < delta.denom) continue;

        /* If the amount is small, pass on that too */
        if ((-maxamtscu < dst_amt.num) && (dst_amt.num < maxamtscu)) continue;

        /* Make the actual adjustment */
        xaccTransBeginEdit (txn);
        xaccSplitSetValue (s, target_val);
        xaccTransCommitEdit (txn);
    }
    LEAVE (" ");
}
예제 #16
0
static gboolean
gncScrubLotDanglingPayments (GNCLot *lot)
{
    SplitList * split_list, *filtered_list = NULL, *match_list = NULL, *node;
    Split *ll_split = gnc_lot_get_earliest_split (lot);
    Transaction *ll_trans = xaccSplitGetParent (ll_split);
    gnc_numeric ll_val = xaccSplitGetValue (ll_split);
    time64 ll_date = xaccTransGetDate (ll_trans);
    const char *ll_desc = xaccTransGetDescription (ll_trans);

    // look for free splits (i.e. not in any lot) which,
    // compared to the lot link split
    // - have the same date
    // - have the same description
    // - have an opposite sign amount
    // - free split's abs value is less than or equal to ll split's abs value
    split_list = xaccAccountGetSplitList(gnc_lot_get_account (lot));
    for (node = split_list; node; node = node->next)
    {
        Split *free_split = node->data;
        Transaction *free_trans;
        gnc_numeric free_val;

        if (NULL != xaccSplitGetLot(free_split))
            continue;

        free_trans = xaccSplitGetParent (free_split);
        if (ll_date != xaccTransGetDate (free_trans))
            continue;

        if (0 != g_strcmp0 (ll_desc, xaccTransGetDescription (free_trans)))
            continue;

        free_val = xaccSplitGetValue (free_split);
        if (gnc_numeric_positive_p (ll_val) ==
                gnc_numeric_positive_p (free_val))
            continue;

        if (gnc_numeric_compare (gnc_numeric_abs (free_val), gnc_numeric_abs (ll_val)) > 0)
            continue;

        filtered_list = g_list_append(filtered_list, free_split);
    }

    match_list = gncSLFindOffsSplits (filtered_list, ll_val);
    g_list_free (filtered_list);

    for (node = match_list; node; node = node->next)
    {
        Split *match_split = node->data;
        gnc_lot_add_split (lot, match_split);
    }

    if (match_list)
    {
        g_list_free (match_list);
        return TRUE;
    }
    else
        return FALSE;
}
예제 #17
0
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;
}
예제 #18
0
static gint
sxftd_init( SXFromTransInfo *sxfti )
{
    GtkWidget *w;
    const char *transName;
    gint pos;
    GList *schedule = NULL;
    time_t start_tt;
    struct tm *tmpTm;
    GDate date, nextDate;

    if ( ! sxfti->sx )
    {
        return -1;
    }
    if ( ! sxfti->trans )
    {
        return -2;
    }
    if ( xaccTransIsOpen( sxfti->trans ) )
    {
        return SXFTD_ERRNO_OPEN_XACTION;
    }

    sxfti_attach_callbacks(sxfti);

    /* Setup the example calendar and related data structures. */
    {
        int num_marks = SXFTD_EXCAL_NUM_MONTHS * 31;

        w = GTK_WIDGET(glade_xml_get_widget( sxfti->gxml, SXFTD_EX_CAL_FRAME ));
        sxfti->dense_cal_model = gnc_dense_cal_store_new(num_marks);
        sxfti->example_cal = GNC_DENSE_CAL(gnc_dense_cal_new_with_model(GNC_DENSE_CAL_MODEL(sxfti->dense_cal_model)));
        g_object_ref_sink(sxfti->example_cal);

        g_assert(sxfti->example_cal);
        gnc_dense_cal_set_num_months( sxfti->example_cal, SXFTD_EXCAL_NUM_MONTHS );
        gnc_dense_cal_set_months_per_col( sxfti->example_cal, SXFTD_EXCAL_MONTHS_PER_COL );
        gtk_container_add( GTK_CONTAINER(w), GTK_WIDGET(sxfti->example_cal) );
    }

    /* Setup the start and end dates as GNCDateEdits */
    {
        GtkWidget *paramTable = glade_xml_get_widget( sxfti->gxml,
                                SXFTD_PARAM_TABLE );
        sxfti->startDateGDE =
            GNC_DATE_EDIT( gnc_date_edit_new( time( NULL ),
                                              FALSE, FALSE ) );
        gtk_table_attach( GTK_TABLE(paramTable),
                          GTK_WIDGET( sxfti->startDateGDE ),
                          1, 2, 2, 3,
                          (GTK_EXPAND | GTK_FILL),
                          GTK_FILL,
                          0, 0 );
        g_signal_connect( sxfti->startDateGDE, "date-changed",
                          G_CALLBACK( sxftd_update_excal_adapt ),
                          sxfti );
    }
    {
        GtkWidget *endDateBox = glade_xml_get_widget( sxfti->gxml,
                                SXFTD_END_DATE_BOX );
        sxfti->endDateGDE =
            GNC_DATE_EDIT( gnc_date_edit_new( time( NULL ),
                                              FALSE, FALSE ) );
        gtk_box_pack_start( GTK_BOX( endDateBox ),
                            GTK_WIDGET( sxfti->endDateGDE ),
                            FALSE, TRUE, 0 );
        g_signal_connect( sxfti->endDateGDE, "date-changed",
                          G_CALLBACK( sxftd_update_excal_adapt ),
                          sxfti );
    }

    /* Get the name from the transaction, try that as the initial SX name. */
    transName = xaccTransGetDescription( sxfti->trans );
    xaccSchedXactionSetName( sxfti->sx, transName );

    /* Setup the initial start date for user display/confirmation */
    /* compute good initial date. */
    start_tt = xaccTransGetDate( sxfti->trans );
    g_date_set_time_t( &date, start_tt );
    w = glade_xml_get_widget(sxfti->gxml,
                             SXFTD_FREQ_COMBO_BOX);
    gtk_combo_box_set_active(GTK_COMBO_BOX(w), 0);
    g_signal_connect( w, "changed",
                      G_CALLBACK(sxftd_freq_combo_changed),
                      sxfti );
    sxftd_update_schedule( sxfti, &date, &schedule);
    recurrenceListNextInstance(schedule, &date, &nextDate);
    recurrenceListFree(&schedule);

    tmpTm = g_new0( struct tm, 1 );
    g_date_to_struct_tm( &nextDate, tmpTm );
    start_tt = mktime( tmpTm );
    g_free( tmpTm );
    gnc_date_edit_set_time( sxfti->startDateGDE, start_tt );

    w = glade_xml_get_widget( sxfti->gxml, SXFTD_NAME_ENTRY );
    pos = 0;
    gtk_editable_insert_text( GTK_EDITABLE(w), transName,
                              (strlen(transName) * sizeof(char)), &pos );

    g_signal_connect( GTK_OBJECT(w), "destroy",
                      G_CALLBACK(sxftd_destroy),
                      sxfti );

    sxftd_update_example_cal( sxfti );

    return 0;
}
static void
refresh_model_row (GNCImportMainMatcher *gui,
                   GtkTreeModel *model,
                   GtkTreeIter *iter,
                   GNCImportTransInfo *info)
{
    GtkListStore *store;
    GtkTreeSelection *selection;
    gchar *tmp, *imbalance, *text, *color;
    const gchar *ro_text;
    Split *split;
    g_assert (gui);
    g_assert (model);
    g_assert (info);
    /*DEBUG("Begin");*/

    store = GTK_LIST_STORE(model);
    gtk_list_store_set(store, iter, DOWNLOADED_COL_DATA, info, -1);

    /*Account:*/
    split = gnc_import_TransInfo_get_fsplit (info);
    g_assert(split); // Must not be NULL
    ro_text = xaccAccountGetName(xaccSplitGetAccount(split));
    gtk_list_store_set(store, iter, DOWNLOADED_COL_ACCOUNT, ro_text, -1);

    /*Date*/
    text = qof_print_date ( xaccTransGetDate( gnc_import_TransInfo_get_trans(info) ) );
    gtk_list_store_set(store, iter, DOWNLOADED_COL_DATE, text, -1);
    g_free(text);

    /*Amount*/
    ro_text = xaccPrintAmount
              (xaccSplitGetAmount (split),
               gnc_split_amount_print_info(split, TRUE)
              );
    gtk_list_store_set(store, iter, DOWNLOADED_COL_AMOUNT, ro_text, -1);

    /*Description*/
    ro_text = xaccTransGetDescription(gnc_import_TransInfo_get_trans(info) );
    gtk_list_store_set(store, iter, DOWNLOADED_COL_DESCRIPTION, ro_text, -1);

    /*Memo*/
    ro_text = xaccSplitGetMemo(split);
    gtk_list_store_set(store, iter, DOWNLOADED_COL_MEMO, ro_text, -1);

    /*Actions*/

    /* Action informations */
    ro_text = text = color = NULL;
    switch (gnc_import_TransInfo_get_action(info))
    {
    case GNCImport_ADD:
        if (gnc_import_TransInfo_is_balanced(info) == TRUE)
        {
            ro_text = _("New, already balanced");
            color = COLOR_GREEN;
        }
        else
        {
            /* Assume that importers won't create transactions in two or more
               currencies so we can use xaccTransGetImbalanceValue */
            imbalance =
                g_strdup
                (xaccPrintAmount
                 (gnc_numeric_neg(xaccTransGetImbalanceValue
                                  (gnc_import_TransInfo_get_trans(info) )),
                  gnc_commodity_print_info
                  (xaccTransGetCurrency(gnc_import_TransInfo_get_trans (info)),
                   TRUE) ));
            if (gnc_import_TransInfo_get_destacc (info) != NULL)
            {
                color = COLOR_GREEN;
                tmp = gnc_account_get_full_name
                      (gnc_import_TransInfo_get_destacc (info));
                if (gnc_import_TransInfo_get_destacc_selected_manually(info)
                        == TRUE)
                {
                    text =
                        /* Translators: %1$s is the amount to be
                           transferred. %2$s is the destination account. */
                        g_strdup_printf(_("New, transfer %s to (manual) \"%s\""),
                                        imbalance, tmp);
                }
                else
                {
                    text =
                        /* Translators: %1$s is the amount to be
                           transferred. %2$s is the destination account. */
                        g_strdup_printf(_("New, transfer %s to (auto) \"%s\""),
                                        imbalance, tmp);
                }
                g_free (tmp);

            }
            else
            {
                color = COLOR_YELLOW;
                text =
                    /* Translators: %s is the amount to be transferred. */
                    g_strdup_printf(_("New, UNBALANCED (need acct to transfer %s)!"),
                                    imbalance);
            }
            g_free (imbalance);
        }
        break;
    case GNCImport_CLEAR:
        if (gnc_import_TransInfo_get_selected_match(info))
        {
            color = COLOR_GREEN;
            if (gnc_import_TransInfo_get_match_selected_manually(info) == TRUE)
            {
                ro_text = _("Reconcile (manual) match");
            }
            else
            {
                ro_text = _("Reconcile (auto) match");
            }
        }
        else
        {
            color = COLOR_RED;
            ro_text = _("Match missing!");
        }
        break;
    case GNCImport_UPDATE:
        if (gnc_import_TransInfo_get_selected_match(info))
        {
            color = COLOR_GREEN;
            if (gnc_import_TransInfo_get_match_selected_manually(info) == TRUE)
            {
                ro_text = _("Update and reconcile (manual) match");
            }
            else
            {
                ro_text = _("Update and reconcile (auto) match");
            }
        }
        else
        {
            color = COLOR_RED;
            ro_text = _("Match missing!");
        }
        break;
    case GNCImport_SKIP:
        color = COLOR_RED;
        ro_text = _("Do not import (no action selected)");
        break;
    default:
        color = "white";
        ro_text = "WRITEME, this is an unknown action";
        break;
    }

    gtk_list_store_set(store, iter,
                       DOWNLOADED_COL_COLOR, color,
                       DOWNLOADED_COL_ACTION_INFO, ro_text ? ro_text : text,
                       -1);
    if (text)
        g_free(text);

    /* Set the pixmaps */
    gtk_list_store_set(store, iter,
                       DOWNLOADED_COL_ACTION_ADD,
                       gnc_import_TransInfo_get_action(info) == GNCImport_ADD,
                       -1);
    if (gnc_import_TransInfo_get_action(info) == GNCImport_SKIP)
    {
        /*Show the best match's confidence pixmap in the info column*/
        gtk_list_store_set(store, iter,
                           DOWNLOADED_COL_ACTION_PIXBUF,
                           gen_probability_pixbuf( gnc_import_MatchInfo_get_probability
                                   ( gnc_import_TransInfo_get_selected_match (info)),
                                   gui->user_settings,
                                   GTK_WIDGET(gui->view)),
                           -1);
    }

    gtk_list_store_set(store, iter,
                       DOWNLOADED_COL_ACTION_CLEAR,
                       gnc_import_TransInfo_get_action(info) == GNCImport_CLEAR,
                       -1);
    if (gnc_import_TransInfo_get_action(info) == GNCImport_CLEAR)
    {
        /*Show the best match's confidence pixmap in the info column*/
        gtk_list_store_set(store, iter,
                           DOWNLOADED_COL_ACTION_PIXBUF,
                           gen_probability_pixbuf( gnc_import_MatchInfo_get_probability
                                   ( gnc_import_TransInfo_get_selected_match (info)),
                                   gui->user_settings,
                                   GTK_WIDGET(gui->view)),
                           -1);
    }

    gtk_list_store_set(store, iter,
                       DOWNLOADED_COL_ACTION_UPDATE,
                       gnc_import_TransInfo_get_action(info) == GNCImport_UPDATE,
                       -1);
    if (gnc_import_TransInfo_get_action(info) == GNCImport_UPDATE)
    {
        /*Show the best match's confidence pixmap in the info column*/
        gtk_list_store_set(store, iter,
                           DOWNLOADED_COL_ACTION_PIXBUF,
                           gen_probability_pixbuf( gnc_import_MatchInfo_get_probability
                                   ( gnc_import_TransInfo_get_selected_match (info)),
                                   gui->user_settings,
                                   GTK_WIDGET(gui->view)),
                           -1);
    }

    selection = gtk_tree_view_get_selection(gui->view);
    gtk_tree_selection_unselect_all(selection);
}
예제 #20
0
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();
            }
예제 #21
0
static gint
sxftd_init( SXFromTransInfo *sxfti )
{
    GtkWidget *w;
    const char *transName;
    gint pos;
    GList *schedule = NULL;
    time64 start_tt;
    struct tm *tmpTm;
    GDate date, nextDate;

    if ( ! sxfti->sx )
    {
        return -1;
    }
    if ( ! sxfti->trans )
    {
        return -2;
    }
    if ( xaccTransIsOpen( sxfti->trans ) )
    {
        return SXFTD_ERRNO_OPEN_XACTION;
    }

    /* Setup Widgets */
    {
        sxfti->ne_but = GTK_TOGGLE_BUTTON(gtk_builder_get_object(sxfti->builder, "never_end_button"));
        sxfti->ed_but = GTK_TOGGLE_BUTTON(gtk_builder_get_object(sxfti->builder, "end_on_date_button"));
        sxfti->oc_but = GTK_TOGGLE_BUTTON(gtk_builder_get_object(sxfti->builder, "n_occurrences_button"));
        sxfti->n_occurences = GTK_ENTRY(gtk_builder_get_object(sxfti->builder, "n_occurrences_entry"));
    }

    /* Get the name from the transaction, try that as the initial SX name. */
    transName = xaccTransGetDescription( sxfti->trans );
    xaccSchedXactionSetName( sxfti->sx, transName );

    sxfti->name = GTK_ENTRY(gtk_builder_get_object(sxfti->builder, "name_entry" ));
    pos = 0;
    gtk_editable_insert_text( GTK_EDITABLE(sxfti->name), transName,
                              (strlen(transName) * sizeof(char)), &pos );

    sxfti_attach_callbacks(sxfti);

    /* Setup the example calendar and related data structures. */
    {
        int num_marks = SXFTD_EXCAL_NUM_MONTHS * 31;

        w = GTK_WIDGET(gtk_builder_get_object(sxfti->builder, "ex_cal_frame" ));
        sxfti->dense_cal_model = gnc_dense_cal_store_new(num_marks);
        sxfti->example_cal = GNC_DENSE_CAL(gnc_dense_cal_new_with_model(GNC_DENSE_CAL_MODEL(sxfti->dense_cal_model)));
        g_object_ref_sink(sxfti->example_cal);

        g_assert(sxfti->example_cal);
        gnc_dense_cal_set_num_months( sxfti->example_cal, SXFTD_EXCAL_NUM_MONTHS );
        gnc_dense_cal_set_months_per_col( sxfti->example_cal, SXFTD_EXCAL_MONTHS_PER_COL );
        gtk_container_add( GTK_CONTAINER(w), GTK_WIDGET(sxfti->example_cal) );
    }

    /* Setup the start and end dates as GNCDateEdits */
    {
        GtkWidget *paramTable = GTK_WIDGET(gtk_builder_get_object(sxfti->builder, "param_table" ));
        sxfti->startDateGDE =
            GNC_DATE_EDIT( gnc_date_edit_new (gnc_time (NULL),
                                              FALSE, FALSE));
        gtk_table_attach( GTK_TABLE(paramTable),
                          GTK_WIDGET( sxfti->startDateGDE ),
                          1, 2, 2, 3,
                          (GTK_EXPAND | GTK_FILL),
                          GTK_FILL,
                          0, 0 );
        g_signal_connect( sxfti->startDateGDE, "date-changed",
                          G_CALLBACK( sxftd_update_excal_adapt ),
                          sxfti );
    }
    {
        GtkWidget *endDateBox = GTK_WIDGET(gtk_builder_get_object(sxfti->builder, "end_date_hbox" ));
        sxfti->endDateGDE =
            GNC_DATE_EDIT( gnc_date_edit_new (gnc_time (NULL),
                                              FALSE, FALSE));
        gtk_box_pack_start( GTK_BOX( endDateBox ),
                            GTK_WIDGET( sxfti->endDateGDE ),
                            TRUE, TRUE, 0 );
        g_signal_connect( sxfti->endDateGDE, "date-changed",
                          G_CALLBACK( sxftd_update_excal_adapt ),
                          sxfti );
    }

    /* Setup the initial start date for user display/confirmation */
    /* compute good initial date. */
    start_tt = xaccTransGetDate( sxfti->trans );
    gnc_gdate_set_time64( &date, start_tt );
    sxfti->freq_combo = GTK_COMBO_BOX(gtk_builder_get_object(sxfti->builder, "freq_combo_box"));
    gtk_combo_box_set_active(GTK_COMBO_BOX(sxfti->freq_combo), 0);
    g_signal_connect( sxfti->freq_combo, "changed",
                      G_CALLBACK(sxftd_freq_combo_changed),
                      sxfti );
    sxftd_update_schedule( sxfti, &date, &schedule);
    recurrenceListNextInstance(schedule, &date, &nextDate);
    recurrenceListFree(&schedule);
    start_tt = gnc_time64_get_day_start_gdate (&nextDate);
    gnc_date_edit_set_time( sxfti->startDateGDE, start_tt );

    g_signal_connect( G_OBJECT(sxfti->name), "destroy",
                      G_CALLBACK(sxftd_destroy),
                      sxfti );

    sxftd_update_example_cal( sxfti );

    return 0;
}
static void
downloaded_transaction_append(GNCImportMatchPicker * matcher,
                              GNCImportTransInfo * transaction_info)
{
    GtkListStore *store;
    GtkTreeIter iter;
    GtkTreeSelection *selection;
    Transaction *trans;
    Split *split;
    gchar *text;
    const gchar *ro_text;
    gboolean found = FALSE;
    GNCImportTransInfo *local_info;

    g_assert(matcher);
    g_assert(transaction_info);

    /*DEBUG("Begin");*/

    /* Has the transaction already been added? */
    store = GTK_LIST_STORE(gtk_tree_view_get_model(matcher->downloaded_view));
    if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
    {
        do
        {
            gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
                               DOWNLOADED_COL_INFO_PTR, &local_info,
                               -1);
            if (local_info == transaction_info)
            {
                found = TRUE;
                break;
            }
        }
        while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
    }
    if (!found)
        gtk_list_store_append(store, &iter);

    split = gnc_import_TransInfo_get_fsplit(transaction_info);
    trans = gnc_import_TransInfo_get_trans(transaction_info);

    /*Account*/
    ro_text = xaccAccountGetName(xaccSplitGetAccount(split));
    gtk_list_store_set(store, &iter, DOWNLOADED_COL_ACCOUNT, ro_text, -1);

    /*Date*/
    text = qof_print_date(xaccTransGetDate(trans));
    gtk_list_store_set(store, &iter, DOWNLOADED_COL_DATE, text, -1);
    g_free(text);

    /*Amount*/
    ro_text = xaccPrintAmount(xaccSplitGetAmount(split),
                              gnc_split_amount_print_info(split, TRUE));
    gtk_list_store_set(store, &iter, DOWNLOADED_COL_AMOUNT, ro_text, -1);

    /*Description*/
    ro_text = xaccTransGetDescription(trans);
    gtk_list_store_set(store, &iter, DOWNLOADED_COL_DESCRIPTION, ro_text, -1);

    /*Memo*/
    ro_text = xaccSplitGetMemo(split);
    gtk_list_store_set(store, &iter, DOWNLOADED_COL_MEMO, ro_text, -1);

    /*Imbalance*/
    /* Assume that the importer won't create a transaction that involves two or more
       currencies and no non-currency commodity.  In that case can use the simpler
       value imbalance check. */
    ro_text = xaccPrintAmount(xaccTransGetImbalanceValue(trans),
                              gnc_default_print_info(TRUE));
    gtk_list_store_set(store, &iter, DOWNLOADED_COL_BALANCED, ro_text, -1);

    gtk_list_store_set(store, &iter, DOWNLOADED_COL_INFO_PTR,
                       transaction_info, -1);

    selection = gtk_tree_view_get_selection(matcher->downloaded_view);
    gtk_tree_selection_select_iter(selection, &iter);
}