Exemple #1
0
// A helper function that takes two splits. If the splits are  of opposite sign
// it reduces the biggest split to have the same value (but with opposite sign)
// of the smaller split.
// To make sure everything still continues to balance in addition a "remainder" split
// will be created that will be added to the same lot and transaction as the biggest
// split.
// The opposite sign restriction is because that's the only scenario that makes sense
// in the context of scrubbing business lots below.
// If we created new splits, return TRUE, otherwise FALSE
static gboolean reduce_biggest_split (Split *splitA, Split *splitB)
{
    gnc_numeric valA = xaccSplitGetValue (splitA);
    gnc_numeric valB = xaccSplitGetValue (splitB);

    if (gnc_numeric_compare (gnc_numeric_abs (valA), gnc_numeric_abs (valB)) >= 0)
        return gncOwnerReduceSplitTo (splitA, gnc_numeric_neg (valB));
    else
        return gncOwnerReduceSplitTo (splitB, gnc_numeric_neg (valA));
}
Exemple #2
0
static void gncOwnerOffsetLots (GNCLot *from_lot, GNCLot *to_lot, const GncOwner *owner)
{
    gnc_numeric target_offset;
    Split *split;

    /* from lot should not be a document lot because we're removing a split from there ! */
    if (gncInvoiceGetInvoiceFromLot (from_lot))
    {
        PWARN ("from_lot %p is a document lot. That is not allowed in gncOwnerOffsetLots", from_lot);
        return;
    }

    /* Get best matching split from from_lot to offset to_lot */
    target_offset = gnc_lot_get_balance (to_lot);
    if (gnc_numeric_zero_p (target_offset))
        return; // to_lot is already balanced, nothing more to do

    split = gncOwnerFindOffsettingSplit (from_lot, target_offset);
    if (!split)
        return; // No suitable offsetting split found, nothing more to do

    /* If the offsetting split is bigger than the amount needed to balance
     * to_lot, reduce the split so its reduced value closes to_lot exactly.
     * Note the negation in the reduction function. The split must be of
     * opposite sign of to_lot's balance in order to be able to close it.
     */
    if (gnc_numeric_compare (gnc_numeric_abs (xaccSplitGetValue (split)),
                             gnc_numeric_abs (target_offset)) > 0)
        gncOwnerReduceSplitTo (split, gnc_numeric_neg (target_offset));

    /* Move the reduced split from from_lot to to_lot */
    gnc_lot_add_split (to_lot, split);

}
static const char * get_taxval_entry (VirtualLocation virt_loc,
                                      gboolean translate,
                                      gboolean *conditionally_changed,
                                      gpointer user_data)
{
    GncEntryLedger *ledger = user_data;
    gnc_numeric value;

    /* Check if this is the current cursor */
    if (virt_cell_loc_equal (ledger->table->current_cursor_loc.vcell_loc,
                             virt_loc.vcell_loc))
    {
        gnc_entry_ledger_compute_value (ledger, NULL, &value);
    }
    else
    {
        GncEntry *entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);

        if (entry == gnc_entry_ledger_get_blank_entry (ledger))
            return NULL;

        value = gncEntryReturnTaxValue (entry, ledger->is_cust_doc);
    }

    /* Credit notes have negative values, but the ledger should
     * display it as on the document, meaning positive.
     * So reverse the value for credit notes.
     */
    if (ledger->is_credit_note)
        value = gnc_numeric_neg (value);

    return xaccPrintAmount (value, gnc_default_print_info (FALSE));
}
static void
check_neg (void)
{
    gnc_numeric a = gnc_numeric_create(2, 6);
    gnc_numeric b = gnc_numeric_create(1, 4);
    gnc_numeric c = gnc_numeric_neg (a);
    gnc_numeric d = gnc_numeric_neg (b);

    check_unary_op (gnc_numeric_eq,
                    gnc_numeric_create (-2, 6), c,
                    a, "expected %s got %s = -(%s)");

    check_unary_op (gnc_numeric_eq,
                    gnc_numeric_create (-1, 4), d,
                    b, "expected %s got %s = -(%s)");

}
Exemple #5
0
void gncEntrySetDocQuantity (GncEntry *entry, gnc_numeric quantity, gboolean is_cn)
{
    if (!entry) return;
    if (gnc_numeric_eq (entry->quantity, quantity)) return;
    gncEntryBeginEdit (entry);
    entry->quantity = (is_cn ? gnc_numeric_neg (quantity) : quantity);
    entry->values_dirty = TRUE;
    mark_entry (entry);
    gncEntryCommitEdit (entry);
}
static void
starting_balance_helper (Account *account, hierarchy_data *data)
{
    gnc_numeric balance;

    balance = get_final_balance (data->balance_hash, account);
    if (gnc_reverse_balance(account))
        balance = gnc_numeric_neg(balance);
    if (!gnc_numeric_zero_p (balance))
        gnc_account_create_opening_balance (account, balance, gnc_time (NULL),
                                            gnc_get_current_book ());
}
Exemple #7
0
static void *
negate_numeric(void *value)
{
    ParserNum *result = value;

    if (value == NULL)
        return NULL;

    result->value = gnc_numeric_neg (result->value);

    return result;
}
Exemple #8
0
static void
test_entry_basics ( Fixture *fixture, gconstpointer pData )
{
    time64 ts1 = gnc_time(NULL), ts2;
    const char *desc = "Test description with éà unicode chars";
    const char *action = "Test action with éà unicode chars";
    const char *note = "Test note with éà unicode chars";
    gnc_numeric quantity = {500000, 100};
    gboolean is_cn = FALSE;

    GncEntry *entry = gncEntryCreate(fixture->book);
    g_assert(entry);

    g_test_message( "Test basic setters/getters" );
    g_test_message( "  Date" );
    gncEntrySetDate (entry, ts1);
    ts2 = gncEntryGetDate (entry);
    g_assert(ts2 == ts1);
    g_test_message( "  DateEntered" );
    gncEntrySetDateEntered (entry, ts1);
    ts2 = gncEntryGetDateEntered (entry);
    g_assert(ts2 == ts1);
    g_test_message( "  Description" );
    gncEntrySetDescription (entry, desc);
    g_assert(g_strcmp0 (gncEntryGetDescription (entry), desc) == 0);
    g_test_message( "  Action" );
    gncEntrySetAction (entry, action);
    g_assert(g_strcmp0 (gncEntryGetAction (entry), action) == 0);
    g_test_message( "  Notes" );
    gncEntrySetNotes (entry, note);
    g_assert(g_strcmp0 (gncEntryGetNotes (entry), note) == 0);
    g_test_message( "  Quantity" );
    gncEntrySetQuantity (entry, quantity);
    g_assert(gnc_numeric_eq (gncEntryGetQuantity (entry), quantity));
    g_test_message( "  DocQuantity (with is_cn = FALSE)" );
    gncEntrySetDocQuantity (entry, quantity, is_cn);
    g_assert(gnc_numeric_eq (gncEntryGetDocQuantity (entry, is_cn), quantity));
    g_assert(gnc_numeric_eq (gncEntryGetQuantity (entry), quantity));
    g_test_message( "  DocQuantity (with is_cn = TRUE)");
    is_cn = TRUE;
    gncEntrySetDocQuantity (entry, quantity, is_cn);
    g_assert(gnc_numeric_eq (gncEntryGetDocQuantity (entry, is_cn), quantity));
    g_assert(gnc_numeric_eq (gncEntryGetQuantity (entry), gnc_numeric_neg (quantity)));
    g_test_message( "  InvAccount" );
    gncEntrySetInvAccount (entry, fixture->account);
    g_assert(gncEntryGetInvAccount (entry) == fixture->account);

}
Exemple #9
0
/* Careful: the returned list is NOT owned by the entry and should be freed by the caller */
AccountValueList * gncEntryGetBalTaxValues (GncEntry *entry, gboolean is_cust_doc)
{
    AccountValueList *int_values = gncEntryGetIntTaxValues (entry, is_cust_doc);
    AccountValueList *values = NULL, *node;

    /* Make a copy of the list with negated values if necessary. */
    for (node = int_values; node; node = node->next)
    {
        GncAccountValue *acct_val = node->data;
        values = gncAccountValueAdd (values, acct_val->account,
                                     (is_cust_doc ? gnc_numeric_neg (acct_val->value)
                                      : acct_val->value));
    }

    return values;
}
Exemple #10
0
void
gnc_price_cell_set_debt_credit_value (PriceCell * debit,
                                      PriceCell * credit,
                                      gnc_numeric amount)
{
    /* debits are positive, credits are negative */
    if (gnc_numeric_positive_p (amount))
    {
        gnc_price_cell_set_value (debit, amount);
        gnc_price_cell_set_value (credit, gnc_numeric_zero ());
    }
    else
    {
        gnc_price_cell_set_value (debit, gnc_numeric_zero ());
        gnc_price_cell_set_value (credit, gnc_numeric_neg (amount));
    }
}
static const char * get_value_entry (VirtualLocation virt_loc,
                                     gboolean translate,
                                     gboolean *conditionally_changed,
                                     gpointer user_data)
{
    GncEntryLedger *ledger = user_data;
    gnc_numeric value;

    /* Credit notes need some attention here: the ledger displays values
     * as on the document, meaning positive for credit notes. Credit note
     * values are negative internally though. So depending on which values
     * are used to calculate the subtotal, the resulting subtotal has to be
     * sign-reversed before displaying.
     */
    /* Check if this is the current cursor */
    if (virt_cell_loc_equal (ledger->table->current_cursor_loc.vcell_loc,
                             virt_loc.vcell_loc))
    {
        gnc_entry_ledger_compute_value (ledger, &value, NULL);
        /* Credit note info: this function works with values as seen
         * on-screen in the ledger, so they are always in the proper sign.
         * As per the above no sign reversal is needed for
         * credit note type ledgers.
         */
    }
    else
    {
        GncEntry *entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);

        if (entry == gnc_entry_ledger_get_blank_entry (ledger))
            return NULL;

        value = gncEntryReturnValue (entry, ledger->is_cust_doc);
        /* Credit note info: this function works with internal values,
         * so they are negative for credit note type ledgers and have to
         * be sign-reversed as per the above.
         */

        if (ledger->is_credit_note)
            value = gnc_numeric_neg (value);
    }

    return xaccPrintAmount (value, gnc_default_print_info (FALSE));
}
Exemple #12
0
static Transaction*
gsr2_create_balancing_transaction (QofBook *book, Account *account,
                             time64 statement_date, gnc_numeric balancing_amount)
{
    Transaction *trans;
    Split *split;

    if (!account)
        return NULL;
    if (gnc_numeric_zero_p (balancing_amount))
        return NULL;

    xaccAccountBeginEdit (account);

    trans = xaccMallocTransaction (book);

    xaccTransBeginEdit (trans);

    // fill Transaction
    xaccTransSetCurrency (trans, gnc_account_or_default_currency (account, NULL));
    xaccTransSetDatePostedSecsNormalized (trans, statement_date);
    xaccTransSetDescription (trans, _("Balancing entry from reconciliation"));

    // 1. Split
    split = xaccMallocSplit (book);
    xaccTransAppendSplit (trans, split);
    xaccAccountInsertSplit  (account, split);
    xaccSplitSetAmount (split, balancing_amount);
    xaccSplitSetValue (split, balancing_amount);

    // 2. Split (no account is defined: split goes to orphan account)
    split = xaccMallocSplit (book);
    xaccTransAppendSplit (trans, split);

    balancing_amount = gnc_numeric_neg (balancing_amount);
    xaccSplitSetAmount (split, balancing_amount);
    xaccSplitSetValue (split, balancing_amount);

    xaccTransCommitEdit (trans);
    xaccAccountCommitEdit (account);
    return trans;
}
Exemple #13
0
void gnc_ui_payment_window_set_amount (PaymentWindow *pw, gnc_numeric amount)
{
    g_assert(pw);

    /* Debits are negative, credits are positive */
    if (gnc_numeric_positive_p (amount))
    {
        gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(pw->amount_credit_edit),
                                    amount);
        gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(pw->amount_debit_edit),
                                    gnc_numeric_zero ());
    }
    else
    {
        gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(pw->amount_debit_edit),
                                    gnc_numeric_neg (amount));
        gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(pw->amount_credit_edit),
                                    gnc_numeric_zero ());
    }

}
Exemple #14
0
/**
 * Duplicate-code reduction function; retreives, formats and updates the
 * GtkLabel with the given amount.
 **/
static
void
gsr2_update_summary_label (GtkWidget *label,
                          xaccGetBalanceFn getter,
                          Account *leader,
                          GNCPrintAmountInfo print_info,
                          gnc_commodity *cmdty,
                          gboolean reverse,
                          gboolean euroFlag)
{
    gnc_numeric amount;
    char string[256];

    if ( label == NULL )
        return;

    amount = (*getter)( leader );

    if ( reverse )
    {
        amount = gnc_numeric_neg( amount );
    }

    xaccSPrintAmount( string, amount, print_info );

    if ( euroFlag )
    {
        strcat( string, " / " );
        xaccSPrintAmount( string + strlen( string ),
                          gnc_convert_to_euro( cmdty, amount ),
                          gnc_commodity_print_info( gnc_get_euro(), TRUE ) );
    }

    gnc_set_label_color( label, amount );
    gtk_label_set_text( GTK_LABEL(label), string );
}
static const char * get_qty_entry (VirtualLocation virt_loc,
                                   gboolean translate,
                                   gboolean *conditionally_changed,
                                   gpointer user_data)
{
    GncEntryLedger *ledger = user_data;
    GncEntry *entry;
    gnc_numeric qty;

    entry = gnc_entry_ledger_get_entry (ledger, virt_loc.vcell_loc);
    qty = gncEntryGetQuantity (entry);

    if (gnc_numeric_zero_p (qty))
        return NULL;

    /* Credit notes have negative quantities, but the ledger should
     * display it as on the document, meaning positive.
     * So reverse the quantity for credit notes.
     */
    if (ledger->is_credit_note)
        qty = gnc_numeric_neg (qty);

    return xaccPrintAmount (qty, gnc_default_print_info (FALSE));
}
Exemple #16
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;
}
Exemple #17
0
/** Create a Transaction from a TransPropertyList.
 * @param list The list of properties
 * @param error Contains an error on failure
 * @return On success, a GncCsvTransLine; on failure, the trans pointer is NULL
 */
static GncCsvTransLine* trans_property_list_to_trans (TransPropertyList* list, gchar** error)
{
    GncCsvTransLine* trans_line = g_new (GncCsvTransLine, 1);
    GList* properties_begin = list->properties;
    QofBook* book = gnc_account_get_book (list->account);
    gnc_commodity* currency = xaccAccountGetCommodity (list->account);
    gnc_numeric amount = double_to_gnc_numeric (0.0, xaccAccountGetCommoditySCU (list->account),
                         GNC_HOW_RND_ROUND_HALF_UP);
    gchar *num = NULL;

    /* This flag is set to TRUE if we can use the "Deposit" or "Withdrawal" column. */
    gboolean amount_set = FALSE;

    /* The balance is 0 by default. */
    trans_line->balance_set = FALSE;
    trans_line->balance = amount;
    trans_line->num = NULL;

    /* We make the line_no -1 just to mark that it hasn't been set. We
     * may get rid of line_no soon anyway, so it's not particularly
     * important. */
    trans_line->line_no = -1;

    /* Make sure this is a transaction with all the columns we need. */
    if (!trans_property_list_verify_essentials (list, error))
    {
        g_free(trans_line);
        return NULL;
    }

    trans_line->trans = xaccMallocTransaction (book);
    xaccTransBeginEdit (trans_line->trans);
    xaccTransSetCurrency (trans_line->trans, currency);

    /* Go through each of the properties and edit the transaction accordingly. */
    list->properties = properties_begin;
    while (list->properties != NULL)
    {
        TransProperty* prop = (TransProperty*)(list->properties->data);
        switch (prop->type)
        {
        case GNC_CSV_DATE:
            xaccTransSetDatePostedSecsNormalized (trans_line->trans, *((time64*)(prop->value)));
            break;

        case GNC_CSV_DESCRIPTION:
            xaccTransSetDescription (trans_line->trans, (char*)(prop->value));
            break;

        case GNC_CSV_NOTES:
            xaccTransSetNotes (trans_line->trans, (char*)(prop->value));
            break;

        case GNC_CSV_NUM:
            /* the 'num' is saved and passed to 'trans_add_split' below where
             * 'gnc_set_num_action' is used to set tran-num and/or split-action
             * per book option */
            num = g_strdup ((char*)(prop->value));
            /* the 'num' is also saved and used in 'gnc_csv_parse_to_trans' when
             * it calls 'trans_add_split' after deleting the splits added below
             * when a balance is used by the user */
            trans_line->num = g_strdup ((char*)(prop->value));
            break;

        case GNC_CSV_DEPOSIT: /* Add deposits to the existing amount. */
            if (prop->value != NULL)
            {
                amount = gnc_numeric_add (*((gnc_numeric*)(prop->value)),
                                         amount,
                                         xaccAccountGetCommoditySCU (list->account),
                                         GNC_HOW_RND_ROUND_HALF_UP);
                amount_set = TRUE;
                /* We will use the "Deposit" and "Withdrawal" columns in preference to "Balance". */
                trans_line->balance_set = FALSE;
            }
            break;

        case GNC_CSV_WITHDRAWAL: /* Withdrawals are just negative deposits. */
            if (prop->value != NULL)
            {
                amount = gnc_numeric_add (gnc_numeric_neg(*((gnc_numeric*)(prop->value))),
                                         amount,
                                         xaccAccountGetCommoditySCU (list->account),
                                         GNC_HOW_RND_ROUND_HALF_UP);
                amount_set = TRUE;
                /* We will use the "Deposit" and "Withdrawal" columns in preference to "Balance". */
                trans_line->balance_set = FALSE;
            }
            break;

        case GNC_CSV_BALANCE: /* The balance gets stored in a separate field in trans_line. */
            /* We will use the "Deposit" and "Withdrawal" columns in preference to "Balance". */
            if (!amount_set && prop->value != NULL)
            {
                /* This gets put into the actual transaction at the end of gnc_csv_parse_to_trans. */
                trans_line->balance = *((gnc_numeric*)(prop->value));
                trans_line->balance_set = TRUE;
            }
            break;
        }
        list->properties = g_list_next (list->properties);
    }

    /* Add a split with the cumulative amount value. */
    trans_add_split (trans_line->trans, list->account, book, amount, num);
    if (num)
        g_free (num);

    return trans_line;
}
void
gnc_stock_split_assistant_finish (GtkAssistant *assistant,
                                  gpointer user_data)
{
    StockSplitInfo *info = user_data;
    GList *account_commits;
    GList *node;

    gnc_numeric amount;
    Transaction *trans;
    Account *account;
    Split *split;
    time64 date;

    account = info->acct;
    g_return_if_fail (account != NULL);

    amount = gnc_amount_edit_get_amount
             (GNC_AMOUNT_EDIT (info->distribution_edit));
    g_return_if_fail (!gnc_numeric_zero_p (amount));

    gnc_suspend_gui_refresh ();

    trans = xaccMallocTransaction (gnc_get_current_book ());

    xaccTransBeginEdit (trans);

    xaccTransSetCurrency (trans, gnc_default_currency ());

    date = gnc_date_edit_get_date (GNC_DATE_EDIT (info->date_edit));
    xaccTransSetDatePostedSecsNormalized (trans, date);

    {
        const char *description;

        description = gtk_entry_get_text (GTK_ENTRY (info->description_entry));
        xaccTransSetDescription (trans, description);
    }

    split = xaccMallocSplit (gnc_get_current_book ());

    xaccAccountBeginEdit (account);
    account_commits = g_list_prepend (NULL, account);

    xaccTransAppendSplit (trans, split);

    xaccAccountInsertSplit (account, split);

    xaccSplitSetAmount (split, amount);
    xaccSplitMakeStockSplit (split);
    /* Set split-action with gnc_set_num_action which is the same as
     * xaccSplitSetAction with these arguments */
    /* Translators: This string has a disambiguation prefix */
    gnc_set_num_action (NULL, split, NULL, Q_("Action Column|Split"));

    amount = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (info->price_edit));
    if (gnc_numeric_positive_p (amount))
    {
        QofBook *book;
        GNCPrice *price;
        GNCPriceDB *pdb;
        GNCCurrencyEdit *ce;
        Timespec ts;

        ce = GNC_CURRENCY_EDIT (info->price_currency_edit);

        ts.tv_sec = date;
        ts.tv_nsec = 0;

        price = gnc_price_create (gnc_get_current_book ());

        gnc_price_begin_edit (price);
        gnc_price_set_commodity (price, xaccAccountGetCommodity (account));
        gnc_price_set_currency (price, gnc_currency_edit_get_currency (ce));
        gnc_price_set_time (price, ts);
        gnc_price_set_source (price, PRICE_SOURCE_STOCK_SPLIT);
        gnc_price_set_typestr (price, PRICE_TYPE_UNK);
        gnc_price_set_value (price, amount);
        gnc_price_commit_edit (price);

        book = gnc_get_current_book ();
        pdb = gnc_pricedb_get_db (book);

        if (!gnc_pricedb_add_price (pdb, price))
            gnc_error_dialog (info->window, "%s", _("Error adding price."));

    }

    amount = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (info->cash_edit));
    if (gnc_numeric_positive_p (amount))
    {
        const char *memo;

        memo = gtk_entry_get_text (GTK_ENTRY (info->memo_entry));

        /* asset split */
        account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(info->asset_tree));

        split = xaccMallocSplit (gnc_get_current_book ());

        xaccAccountBeginEdit (account);
        account_commits = g_list_prepend (account_commits, account);

        xaccAccountInsertSplit (account, split);

        xaccTransAppendSplit (trans, split);

        xaccSplitSetAmount (split, amount);
        xaccSplitSetValue (split, amount);

        xaccSplitSetMemo (split, memo);


        /* income split */
        account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(info->income_tree));

        split = xaccMallocSplit (gnc_get_current_book ());

        xaccAccountBeginEdit (account);
        account_commits = g_list_prepend (account_commits, account);

        xaccAccountInsertSplit (account, split);

        xaccTransAppendSplit (trans, split);

        xaccSplitSetAmount (split, gnc_numeric_neg (amount));
        xaccSplitSetValue (split, gnc_numeric_neg (amount));

        xaccSplitSetMemo (split, memo);
    }

    xaccTransCommitEdit (trans);

    for (node = account_commits; node; node = node->next)
        xaccAccountCommitEdit (node->data);
    g_list_free (account_commits);

    gnc_resume_gui_refresh ();

    gnc_close_gui_component_by_data (ASSISTANT_STOCK_SPLIT_CM_CLASS, info);
}
Exemple #19
0
static void
check_add_subtract (void)
{
    int i;
    gnc_numeric a, b, c, d, z;

    a = gnc_numeric_create(2, 6);
    b = gnc_numeric_create(1, 4);

    /* Well, actually 14/24 would be acceptable/better in this case */
    check_binary_op (gnc_numeric_create(7, 12),
                     gnc_numeric_add(a, b, GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT),
                     a, b, "expected %s got %s = %s + %s for add exact");

    check_binary_op (gnc_numeric_create(58, 100),
                     gnc_numeric_add(a, b, 100, GNC_HOW_RND_ROUND),
                     a, b, "expected %s got %s = %s + %s for add 100ths (banker's)");

    check_binary_op (gnc_numeric_create(5833, 10000),
                     gnc_numeric_add(a, b, GNC_DENOM_AUTO,
                                     GNC_HOW_DENOM_SIGFIGS(4) |
                                     GNC_HOW_RND_ROUND),
                     a, b, "expected %s got %s = %s + %s for add 4 sig figs");

    check_binary_op (gnc_numeric_create(583333, 1000000),
                     gnc_numeric_add(a, b, GNC_DENOM_AUTO,
                                     GNC_HOW_DENOM_SIGFIGS(6) |
                                     GNC_HOW_RND_ROUND),
                     a, b, "expected %s got %s = %s + %s for add 6 sig figs");

    check_binary_op (gnc_numeric_create(1, 12),
                     gnc_numeric_sub(a, b, GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT),
                     a, b, "expected %s got %s = %s - %s for sub exact");

    /* We should try something trickier for reduce & lcd */
    check_binary_op (gnc_numeric_create(1, 12),
                     gnc_numeric_sub(a, b, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE),
                     a, b, "expected %s got %s = %s - %s for sub reduce");

    check_binary_op (gnc_numeric_create(1, 12),
                     gnc_numeric_sub(a, b, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD),
                     a, b, "expected %s got %s = %s - %s for sub reduce");

    check_binary_op (gnc_numeric_create(8, 100),
                     gnc_numeric_sub(a, b, 100, GNC_HOW_RND_ROUND),
                     a, b, "expected %s got %s = %s - %s for sub 100ths (banker's)");

    /* ------------------------------------------------------------ */
    /* This test has failed before */
    c = gnc_numeric_neg (a);
    d = gnc_numeric_neg (b);
    z = gnc_numeric_zero();
    check_binary_op (c, gnc_numeric_add_fixed(z, c),
                     z, c, "expected %s got %s = %s + %s for add fixed");

    check_binary_op (d, gnc_numeric_add_fixed(z, d),
                     z, d, "expected %s got %s = %s + %s for add fixed");

    /* ------------------------------------------------------------ */
    /* Same as above, but with signs reviersed */
    a = c;
    b = d;
    /* Well, actually 14/24 would be acceptable/better in this case */
    check_binary_op (gnc_numeric_create(-7, 12),
                     gnc_numeric_add(a, b, GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT),
                     a, b, "expected %s got %s = %s + %s for add exact");

    check_binary_op (gnc_numeric_create(-58, 100),
                     gnc_numeric_add(a, b, 100, GNC_HOW_RND_ROUND),
                     a, b, "expected %s got %s = %s + %s for add 100ths (banker's)");

    check_binary_op (gnc_numeric_create(-5833, 10000),
                     gnc_numeric_add(a, b, GNC_DENOM_AUTO,
                                     GNC_HOW_DENOM_SIGFIGS(4) |
                                     GNC_HOW_RND_ROUND),
                     a, b, "expected %s got %s = %s + %s for add 4 sig figs");

    check_binary_op (gnc_numeric_create(-583333, 1000000),
                     gnc_numeric_add(a, b, GNC_DENOM_AUTO,
                                     GNC_HOW_DENOM_SIGFIGS(6) |
                                     GNC_HOW_RND_ROUND),
                     a, b, "expected %s got %s = %s + %s for add 6 sig figs");

    check_binary_op (gnc_numeric_create(-1, 12),
                     gnc_numeric_sub(a, b, GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT),
                     a, b, "expected %s got %s = %s - %s for sub exact");

    /* We should try something trickier for reduce & lcd */
    check_binary_op (gnc_numeric_create(-1, 12),
                     gnc_numeric_sub(a, b, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE),
                     a, b, "expected %s got %s = %s - %s for sub reduce");

    check_binary_op (gnc_numeric_create(-1, 12),
                     gnc_numeric_sub(a, b, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD),
                     a, b, "expected %s got %s = %s - %s for sub reduce");

    check_binary_op (gnc_numeric_create(-8, 100),
                     gnc_numeric_sub(a, b, 100, GNC_HOW_RND_ROUND),
                     a, b, "expected %s got %s = %s - %s for sub 100ths (banker's)");

    /* ------------------------------------------------------------ */
    /* Add and subtract some random numbers */
    for (i = 0; i < NREPS; i++)
    {
        gnc_numeric e;
        gint64 deno = rand() + 1;
        gint64 na = get_random_gint64();
        gint64 nb = get_random_gint64();
        gint64 ne;

        /* avoid overflow; */
        na /= 2;
        nb /= 2;

        a = gnc_numeric_create(na, deno);
        b = gnc_numeric_create(nb, deno);

        /* Add */
        ne = na + nb;
        e = gnc_numeric_create(ne, deno);
        check_binary_op (e,
                         gnc_numeric_add(a, b, GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT),
                         a, b, "expected %s got %s = %s + %s for exact addition");

        /* Subtract */
        ne = na - nb;
        e = gnc_numeric_create(ne, deno);
        check_binary_op (e,
                         gnc_numeric_sub(a, b, GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT),
                         a, b, "expected %s got %s = %s - %s for exact subtraction");
    }
}
static void gnc_entry_ledger_save_cells (gpointer save_data,
        gpointer user_data)
{
    GncEntryLedger *ledger = user_data;
    GncEntry *entry = save_data;

    g_return_if_fail (entry != NULL);

    /* copy the contents from the cursor to the split */

    if (gnc_table_layout_get_cell_changed (ledger->table->layout,
                                           ENTRY_IACCT_CELL, TRUE))
    {
        Account *acc;

        acc = gnc_entry_ledger_get_account (ledger, ENTRY_IACCT_CELL);

        if (acc != NULL)
            gncEntrySetInvAccount (entry, acc);
    }

    if (gnc_table_layout_get_cell_changed (ledger->table->layout,
                                           ENTRY_BACCT_CELL, TRUE))
    {
        Account *acc;

        acc = gnc_entry_ledger_get_account (ledger, ENTRY_BACCT_CELL);

        if (acc != NULL)
            gncEntrySetBillAccount (entry, acc);
    }

    if (gnc_table_layout_get_cell_changed (ledger->table->layout,
                                           ENTRY_ACTN_CELL, TRUE))
    {
        const char *value;

        value = gnc_table_layout_get_cell_value (ledger->table->layout,
                ENTRY_ACTN_CELL);
        gncEntrySetAction (entry, value);
    }

    if (gnc_table_layout_get_cell_changed (ledger->table->layout,
                                           ENTRY_DATE_CELL, TRUE))
    {
        BasicCell *cell;
        GDate date;

        cell = gnc_table_layout_get_cell (ledger->table->layout, ENTRY_DATE_CELL);

        /* commit any pending changes */
        gnc_date_cell_commit ((DateCell *) cell);

        gnc_date_cell_get_date_gdate ((DateCell *) cell, &date);
        gncEntrySetDateGDate (entry, &date);
    }

    if (gnc_table_layout_get_cell_changed (ledger->table->layout,
                                           ENTRY_DESC_CELL, TRUE))
    {
        const char *value;

        value = gnc_table_layout_get_cell_value (ledger->table->layout,
                ENTRY_DESC_CELL);
        gncEntrySetDescription (entry, value);
    }

    if (gnc_table_layout_get_cell_changed (ledger->table->layout,
                                           ENTRY_DISC_CELL, TRUE))
    {
        gnc_numeric amount;

        if (gnc_entry_ledger_get_numeric (ledger, ENTRY_DISC_CELL, &amount))
            gncEntrySetInvDiscount (entry, amount);
    }

    if (gnc_table_layout_get_cell_changed (ledger->table->layout,
                                           ENTRY_DISTYPE_CELL, TRUE))
    {
        gint type;

        type = gnc_entry_ledger_get_type (ledger, ENTRY_DISTYPE_CELL);

        if (type != -1)
            gncEntrySetInvDiscountType (entry, type);
    }

    if (gnc_table_layout_get_cell_changed (ledger->table->layout,
                                           ENTRY_DISHOW_CELL, TRUE))
    {
        gint type;

        type = gnc_entry_ledger_get_type (ledger, ENTRY_DISHOW_CELL);

        if (type != -1)
            gncEntrySetInvDiscountHow (entry, type);
    }

    if (gnc_table_layout_get_cell_changed (ledger->table->layout,
                                           ENTRY_QTY_CELL, TRUE))
    {
        gnc_numeric amount;

        if (gnc_entry_ledger_get_numeric (ledger, ENTRY_QTY_CELL, &amount))
        {
            /* Credit notes have negative quantities, but the ledger should
             * display it as on the document, meaning positive.
             * So reverse the quantity for credit notes.
             */
            if (ledger->is_credit_note)
                amount = gnc_numeric_neg (amount);
            gncEntrySetQuantity (entry, amount);
        }
    }

    if (gnc_table_layout_get_cell_changed (ledger->table->layout,
                                           ENTRY_BILLABLE_CELL, TRUE))
    {
        gboolean billable;

        billable = gnc_entry_ledger_get_checkmark (ledger, ENTRY_BILLABLE_CELL);
        gncEntrySetBillable (entry, billable);
    }

    if (gnc_table_layout_get_cell_changed (ledger->table->layout,
                                           ENTRY_PAYMENT_CELL, TRUE))
    {
        const char *value;

        value = gnc_table_layout_get_cell_value (ledger->table->layout,
                ENTRY_PAYMENT_CELL);
        if (!safe_strcmp (value, _("Cash")))
            gncEntrySetBillPayment (entry, GNC_PAYMENT_CASH);
        else if (!safe_strcmp (value, _("Charge")))
            gncEntrySetBillPayment (entry, GNC_PAYMENT_CARD);
        else
            g_warning ("Invalid Payment cell: %s", value ? value : "(null)");
    }

    if (gnc_table_layout_get_cell_changed (ledger->table->layout,
                                           ENTRY_PRIC_CELL, TRUE))
    {
        gnc_numeric amount;

        if (gnc_entry_ledger_get_numeric (ledger, ENTRY_PRIC_CELL, &amount))
        {
            if (ledger->is_cust_doc)
                gncEntrySetInvPrice (entry, amount);
            else
                gncEntrySetBillPrice (entry, amount);
        }
    }

    if (gnc_table_layout_get_cell_changed (ledger->table->layout,
                                           ENTRY_TAXABLE_CELL, TRUE))
    {
        gboolean taxable;

        taxable = gnc_entry_ledger_get_checkmark (ledger, ENTRY_TAXABLE_CELL);
        if (ledger->is_cust_doc)
            gncEntrySetInvTaxable (entry, taxable);
        else
            gncEntrySetBillTaxable (entry, taxable);
    }

    /* XXX: Only (re-set) these if taxable is TRUE? */
    if (gnc_table_layout_get_cell_changed (ledger->table->layout,
                                           ENTRY_TAXTABLE_CELL, TRUE))
    {
        GncTaxTable *table;

        table = gnc_entry_ledger_get_taxtable (ledger, ENTRY_TAXTABLE_CELL);
        if (table)
        {
            if (ledger->is_cust_doc)
                gncEntrySetInvTaxTable (entry, table);
            else
                gncEntrySetBillTaxTable (entry, table);
        }
    }

    if (gnc_table_layout_get_cell_changed (ledger->table->layout,
                                           ENTRY_TAXINCLUDED_CELL, TRUE))
    {
        gboolean taxincluded;

        taxincluded = gnc_entry_ledger_get_checkmark (ledger,
                      ENTRY_TAXINCLUDED_CELL);
        if (ledger->is_cust_doc)
            gncEntrySetInvTaxIncluded (entry, taxincluded);
        else
            gncEntrySetBillTaxIncluded (entry, taxincluded);
    }

    if (ledger->type == GNCENTRY_INVOICE_ENTRY ||
        ledger->type == GNCENTRY_CUST_CREDIT_NOTE_ENTRY)
    {
        gboolean inv_value;

        inv_value = gnc_entry_ledger_get_checkmark (ledger, ENTRY_INV_CELL);

        if (inv_value)
        {
            /* Add this to the invoice (if it's not already attached) */
            if (gncEntryGetInvoice (entry) == NULL)
                gncInvoiceAddEntry (ledger->invoice, entry);

        }
        else
        {
            /* Remove from the invoice iff we're attached to an order or bill */
            if ((gncEntryGetOrder (entry) != NULL) ||
                    (gncEntryGetBill (entry) != NULL))
                gncInvoiceRemoveEntry (ledger->invoice, entry);
        }
    }
}
Exemple #21
0
gboolean
gnc_tree_util_split_reg_get_debcred_entry (GncTreeViewSplitReg *view,
                                      Transaction *trans, Split *split,
                                      gboolean is_blank, gnc_numeric *ret_num,
                                      GNCPrintAmountInfo *ret_print_info)

{
    GncTreeModelSplitReg *model;
    gnc_commodity *currency;

    model = gnc_tree_view_split_reg_get_model_from_view (view);

    currency = xaccTransGetCurrency (trans);
    if (!currency)
        currency = gnc_default_currency ();

    if (is_blank)
    {
        gnc_numeric imbalance;
        Account *acc;

        imbalance = xaccTransGetImbalanceValue (trans);

        if (gnc_numeric_zero_p (imbalance))
            return FALSE;

        if (xaccTransUseTradingAccounts (trans))
        {
            MonetaryList *imbal_list;
            gnc_monetary *imbal_mon;
            imbal_list = xaccTransGetImbalance (trans);

            if (!imbal_list)
            {
                /* No commodity imbalance, there shouldn't be a value imablance. */
                return FALSE;
            }

            if (imbal_list->next)
            {
                /* Multiple currency imbalance. */
                gnc_monetary_list_free (imbal_list);
                return FALSE;
            }

            imbal_mon = imbal_list->data;
            if (!gnc_commodity_equal (gnc_monetary_commodity (*imbal_mon), currency))
            {
                /* Imbalance is in wrong currency */
                gnc_monetary_list_free (imbal_list);
                return FALSE;
            }

            if (!gnc_numeric_equal (gnc_monetary_value (*imbal_mon), imbalance))
            {
                /* Value and commodity imbalances differ */
                gnc_monetary_list_free (imbal_list);
                return FALSE;
            }

            /* Done with the imbalance list */
            gnc_monetary_list_free (imbal_list);
        }

        imbalance = gnc_numeric_neg (imbalance);

        acc = gnc_tree_model_split_reg_get_anchor (model);

        if (gnc_tree_util_split_reg_needs_conv_rate (view, trans, acc))
        {
            imbalance = gnc_numeric_mul (imbalance,
                                         xaccTransGetAccountConvRate (trans, acc),
                                         gnc_commodity_get_fraction (currency),
                                         GNC_HOW_RND_ROUND_HALF_UP);
        }
        else
        {
            imbalance = gnc_numeric_convert (imbalance,
                                             gnc_commodity_get_fraction (currency),
                                             GNC_HOW_RND_ROUND_HALF_UP);
        }

        *ret_num = imbalance;
        *ret_print_info = gnc_account_print_info (acc, FALSE);
         return TRUE;
    }

    {
        gnc_numeric amount;
        gnc_commodity *split_commodity;
        GNCPrintAmountInfo print_info;
        Account *account;
        gnc_commodity *commodity;

        account = gnc_tree_model_split_reg_get_anchor (model);

        commodity = xaccAccountGetCommodity (account);
        split_commodity = xaccAccountGetCommodity (xaccSplitGetAccount (split));

        if (xaccTransUseTradingAccounts (trans))
        {
            gboolean use_symbol, is_current = FALSE;
            Split *current_split = gnc_tree_view_split_reg_get_current_split (view);
            RowDepth depth = gnc_tree_view_reg_get_selected_row_depth (view);

            if ((split == current_split) && (depth == SPLIT3))
                is_current = TRUE;

            if (model->type == STOCK_REGISTER2 ||
                    model->type == CURRENCY_REGISTER2 ||
                    model->type == PORTFOLIO_LEDGER2)
            {
                gnc_commodity *amount_commodity;
                /* security register.  If this split has price and shares columns,
                   use the value, otherwise use the amount.  */
                if (gtu_sr_use_security (view))
                {
                    amount = xaccSplitGetValue (split);
                    amount_commodity = currency;
                }
                else
                {
                    amount = xaccSplitGetAmount (split);
                    amount_commodity = split_commodity;
                }
                /* Show the currency if it is not the default currency */
                if (is_current ||
                        gnc_commodity_equiv (amount_commodity, gnc_default_currency ()))
                    use_symbol = FALSE;
                else
                    use_symbol = TRUE;
                print_info = gnc_commodity_print_info (amount_commodity, use_symbol);
            }
            else
            {
                /* non-security register, always use the split amount. */
                amount = xaccSplitGetAmount (split);
                if (is_current ||
                        gnc_commodity_equiv (split_commodity, commodity))
                    use_symbol = FALSE;
                else
                    use_symbol = TRUE;
                print_info = gnc_commodity_print_info (split_commodity, use_symbol);
            }
        }
        else
        {
            /* If this account is not a stock/mutual/currency account, and
            * currency != the account commodity, then use the SplitAmount
            * instead of the SplitValue.
            */
            switch (model->type)
            {
            case STOCK_REGISTER2:
            case CURRENCY_REGISTER2:
            case PORTFOLIO_LEDGER2:
                amount = xaccSplitGetValue (split);
                print_info = gnc_commodity_print_info (currency, FALSE);
                break;

            default:
                if (commodity && !gnc_commodity_equal (commodity, currency))
                    /* Convert this to the "local" value */
                    amount = xaccSplitConvertAmount (split, account);
                else
                    amount = xaccSplitGetValue (split);
                print_info = gnc_account_print_info (account, FALSE);
                break;
            }
        }

        if (gnc_numeric_zero_p (amount))
            return FALSE;

        *ret_num = amount;
        *ret_print_info = print_info;
         return TRUE;
    }
}
Exemple #22
0
/* Takes the input with column and sets the price / amount / value so they are consistent */
void
gnc_tree_util_set_number_for_input (GncTreeViewSplitReg *view, Transaction *trans, Split *split, gnc_numeric input, gint viewcol)
{
    GncTreeModelSplitReg *model;
    gnc_numeric  price;
    gnc_numeric  amount;
    gnc_numeric  value;

    gboolean price_changed = FALSE;   // Price of each share
    gboolean value_changed = FALSE;   // Total value of shares
    gboolean amount_changed = FALSE;  // No of shares

    gboolean recalc_amount = FALSE;
    gboolean recalc_price = FALSE;
    gboolean recalc_value = FALSE;
    gboolean expanded = FALSE;
    int denom;
    Account *account = NULL;

    ENTER("trans %p and split %p and input is %s and viewcol is %d", trans, split, gnc_numeric_to_string (input), viewcol);

    model = gnc_tree_view_split_reg_get_model_from_view (view);

    /* Check for sub account view */
    if (!gnc_tree_model_split_reg_get_sub_account (model))
        account = gnc_tree_model_split_reg_get_anchor (model);

    expanded = gnc_tree_view_split_reg_trans_expanded (view, trans);

    if (!account)
        account = xaccSplitGetAccount (split);

    if (!xaccAccountIsPriced (account))
        return;

    /* If we are using commodity trading accounts then the value may
       not really be the value.  Punt if so. */
    if (xaccTransUseTradingAccounts (xaccSplitGetParent (split)))
    {
        gnc_commodity *acc_commodity;
        acc_commodity = xaccAccountGetCommodity (account);
        if (!(xaccAccountIsPriced (account) || !gnc_commodity_is_iso (acc_commodity)))
            return;
    }

    if (gnc_numeric_zero_p (input))
    {
        xaccSplitSetValue (split, input);
        xaccSplitSetAmount (split, input);
        LEAVE("zero");
        return;
    }

    amount = xaccSplitGetAmount (split);
    value = xaccSplitGetValue (split);

    if (viewcol == COL_AMTVAL && !expanded)
    {
        value_changed = TRUE;
        if (gnc_numeric_zero_p (amount))
        {
            xaccSplitSetValue (split, input);
            xaccSplitSetAmount (split, input);
            LEAVE("");
            return;
        }
    }
    else if (viewcol == COL_AMTVAL && expanded)
    {
        amount_changed = TRUE;
        if (gnc_numeric_zero_p (value))
        {
            xaccSplitSetValue (split, input);
            xaccSplitSetAmount (split, input);
            LEAVE("");
            return;
        }
    }

    if (viewcol == COL_PRICE)
    {
        price_changed = TRUE;
        if (gnc_numeric_zero_p (value))
        {
            amount = gnc_numeric_create (1,1);
            value = gnc_numeric_mul (input, amount, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND);
            xaccSplitSetValue (split, input);
            xaccSplitSetAmount (split, amount);
            LEAVE("");
            return;
        }
    }

    if ((viewcol == COL_CREDIT || viewcol == COL_DEBIT) && !expanded)
    {
        amount_changed = TRUE;
        if (gnc_numeric_zero_p (value))
        {
            xaccSplitSetValue (split, input);
            xaccSplitSetAmount (split, input);
            LEAVE("");
            return;
        }
    }
    else if ((viewcol == COL_CREDIT || viewcol == COL_DEBIT) && expanded)
    {
        value_changed = TRUE;
        if (gnc_numeric_zero_p (value))
        {
            xaccSplitSetValue (split, input);
            xaccSplitSetAmount (split, input);
            LEAVE("");
            return;
        }
    }

    DEBUG("value_changed %d, price_changed %d, amount_changed %d", value_changed, price_changed, amount_changed);

    {
        int choice;
        int default_value;
        GList *node;
        GList *radio_list = NULL;
        const char *title = _("Recalculate Transaction");
        const char *message = _("The values entered for this transaction "
                                "are inconsistent. Which value would you "
                                "like to have recalculated?");

        if (amount_changed)
            radio_list = g_list_append (radio_list,
                                        g_strdup_printf ("%s (%s)",
                                                _("_Shares"), _("Changed")));
        else
            radio_list = g_list_append (radio_list, g_strdup (_("_Shares")));

        if (price_changed)
            radio_list = g_list_append (radio_list,
                                        g_strdup_printf ("%s (%s)",
                                                _("_Price"), _("Changed")));
        else
            radio_list = g_list_append (radio_list, g_strdup (_("_Price")));

        if (value_changed)
            radio_list = g_list_append (radio_list,
                                        g_strdup_printf ("%s (%s)",
                                                _("_Value"), _("Changed")));
        else
            radio_list = g_list_append (radio_list, g_strdup (_("_Value")));

        if(expanded)
        {
            if (price_changed)
                default_value = 2;  /* change the value */
            else
                default_value = 1;  /* change the price */
        }
        else
        {
            if (price_changed)
                default_value = 0;  /* change the amount / shares */
            else
                default_value = 1;  /* change the price */
        }
        choice = gnc_choose_radio_option_dialog
                 (gnc_tree_view_split_reg_get_parent (view),
                  title,
                  message,
                  _("_Recalculate"),
                  default_value,
                  radio_list);

        for (node = radio_list; node; node = node->next)
            g_free (node->data);

        g_list_free (radio_list);

        switch (choice)
        {
        case 0: /* Modify number of shares */
            recalc_amount = TRUE;
            break;
        case 1: /* Modify the share price */
            recalc_price = TRUE;
            break;
        case 2: /* Modify total value */
            recalc_value = TRUE;
            break;
        default: /* Cancel */
            LEAVE(" " );
            return;
        }
    }

    DEBUG("recalc_value %d, recalc_price %d, recalc_amount %d", recalc_value, recalc_price, recalc_amount);

    if (recalc_amount)
    {
        denom = gtu_sr_get_amount_denom (split);

        if (amount_changed)
        {
            LEAVE("");
            return;
        }

        if (price_changed)
            price = input;
        else
            price = gnc_numeric_div (value, amount, GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);

        if (value_changed)
        {
            xaccSplitSetValue (split, input);
            amount = gnc_numeric_div (input, price, denom, GNC_HOW_RND_ROUND_HALF_UP);
            xaccSplitSetAmount (split, amount);
        }
        else
        {
            amount = gnc_numeric_div (value, price, denom, GNC_HOW_RND_ROUND_HALF_UP);
            xaccSplitSetAmount (split, amount);
        }
    }

    if (recalc_price)
    {
        if (price_changed)
        {
            LEAVE("");
            return;
        }

        if (amount_changed)
        {
            xaccSplitSetAmount (split, input);
            xaccSplitSetValue (split, value);
        }

        if (value_changed)
        {
            xaccSplitSetValue (split, input);
            xaccSplitSetAmount (split, amount);
        }
    }

    if (recalc_value)
    {
        denom = gtu_sr_get_value_denom (split);

        if (value_changed)
        {
            LEAVE("");
            return;
        }

        if (price_changed)
            price = input;
        else
            price = gnc_numeric_div (value, amount, GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);

        if (amount_changed)
        {
            xaccSplitSetAmount (split, input);
            value = gnc_numeric_mul (input, price, denom, GNC_HOW_RND_ROUND_HALF_UP);
            xaccSplitSetValue (split, value);
        }
        else
        {
            value = gnc_numeric_mul (amount, price, denom, GNC_HOW_RND_ROUND_HALF_UP);
            xaccSplitSetValue (split, value);
        }
    }

    /* If the number of splits is two, change other split to balance */
    if (!gnc_tree_util_split_reg_is_multi (split) && expanded)
    {
        Split *osplit;
        gnc_commodity *osplit_com;

        osplit = xaccSplitGetOtherSplit (split);

        value = xaccSplitGetValue (split);

        osplit_com = xaccAccountGetCommodity (xaccSplitGetAccount (osplit));

        if (gnc_commodity_is_currency (osplit_com))
        {
            xaccSplitSetValue (osplit, gnc_numeric_neg (value));
            xaccSplitSetAmount (osplit, gnc_numeric_neg (value));
        }
    }
    LEAVE("");
}
Exemple #23
0
static
void
gsr2_redraw_all_cb (GncTreeViewSplitReg *view, gpointer user_data)
{
    GNCSplitReg2 *gsr = user_data;
    gnc_commodity * commodity;
    GNCPrintAmountInfo print_info;
    gnc_numeric amount = gnc_numeric_zero();
    Account *leader;
    gboolean reverse;
    gboolean euro;

    if ( gsr->summarybar == NULL )
        return;

    leader = gnc_ledger_display2_leader( gsr->ledger );

    commodity = xaccAccountGetCommodity( leader );

    /* no EURO converson, if account is already EURO or no EURO currency */
    if (commodity != NULL)
        euro = (gnc_is_euro_currency( commodity ) &&
                (strncasecmp(gnc_commodity_get_mnemonic(commodity), "EUR", 3)));
    else
        euro = FALSE;

    print_info = gnc_account_print_info( leader, TRUE );
    reverse = gnc_reverse_balance( leader );

    gsr2_update_summary_label( gsr->balance_label,
                              xaccAccountGetPresentBalance,
                              leader, print_info, commodity, reverse, euro );
    gsr2_update_summary_label( gsr->cleared_label,
                              xaccAccountGetClearedBalance,
                              leader, print_info, commodity, reverse, euro );
    gsr2_update_summary_label( gsr->reconciled_label,
                              xaccAccountGetReconciledBalance,
                              leader, print_info, commodity, reverse, euro );
    gsr2_update_summary_label( gsr->future_label,
                              xaccAccountGetBalance,
                              leader, print_info, commodity, reverse, euro );
    gsr2_update_summary_label( gsr->projectedminimum_label,
                              xaccAccountGetProjectedMinimumBalance,
                              leader, print_info, commodity, reverse, euro );

   /* Print the summary share amount */
    if (gsr->shares_label != NULL)
    {
        char string[256];
        print_info = gnc_account_print_info( leader, TRUE );
        amount = xaccAccountGetBalance( leader );
        if ( reverse )
            amount = gnc_numeric_neg( amount );
        xaccSPrintAmount( string, amount, print_info );
        gnc_set_label_color( gsr->shares_label, amount );
        gtk_label_set_text( GTK_LABEL(gsr->shares_label), string );
    }

    /* Print the summary share value */
    if (gsr->value_label != NULL)
    {
        char string[256];
        gnc_commodity *currency = gnc_default_currency ();
        print_info = gnc_commodity_print_info (currency, TRUE);
        xaccSPrintAmount (string, amount, print_info);
        gnc_set_label_color (gsr->value_label, amount);
        gtk_label_set_text (GTK_LABEL (gsr->value_label), string);

    }
}
static void
gnc_split_register_save_cells (gpointer save_data,
                               gpointer user_data)
{
    SRSaveData *sd = save_data;
    SplitRegister *reg = user_data;
    Split *other_split;
    gnc_commodity *txn_cur;
    gnc_numeric rate = gnc_numeric_zero();

    g_return_if_fail (sd != NULL);

    if (!sd->do_scrub)
        return;

    other_split = xaccSplitGetOtherSplit (sd->split);
    txn_cur = xaccTransGetCurrency (sd->trans);

    xaccSplitScrub (sd->split);

    rate = gnc_split_register_get_rate_cell (reg, RATE_CELL);

    if (other_split && !sd->reg_expanded)
    {
        gnc_numeric amount, value = xaccSplitGetValue (sd->split);
        Account *acc;
        gboolean split_needs_amount;

        split_needs_amount = gnc_split_register_split_needs_amount(reg, sd->split);

        /* We are changing the rate on the current split, but it was not
         * handled in the debcred handler, so we need to do it here.
         */
        if (!sd->handled_dc && split_needs_amount && !gnc_numeric_zero_p (rate))
        {
            gnc_numeric amount = xaccSplitGetAmount (sd->split);
            value = gnc_numeric_div(
                        amount, rate, gnc_commodity_get_fraction(txn_cur), GNC_HOW_RND_ROUND_HALF_UP);
            xaccSplitSetValue (sd->split, value);

            /* XXX: do we need to set the amount on the other split? */
        }

        /* Now reverse the value for the other split */
        value = gnc_numeric_neg (value);

        if (gnc_split_register_split_needs_amount (reg, other_split))
        {
            acc = xaccSplitGetAccount (other_split);

            /* If we don't have an exchange rate then figure it out.  Or, if
             * BOTH splits require an amount, then most likely we're in the
             * strange case of having a transaction currency different than
             * _both_ accounts -- so grab the other exchange rate.
             */
            if (gnc_numeric_zero_p (rate) || split_needs_amount)
                rate = xaccTransGetAccountConvRate(xaccSplitGetParent (other_split),
                                                   acc);

            amount = gnc_numeric_mul (value, rate, xaccAccountGetCommoditySCU (acc),
                                      GNC_HOW_RND_ROUND_HALF_UP);
            xaccSplitSetAmount (other_split, amount);

        }

        xaccSplitSetValue (other_split, value);

        xaccSplitScrub (other_split);
    }
    else if (gnc_split_register_split_needs_amount (reg, sd->split) &&
             ! gnc_numeric_zero_p (rate))
    {
        /* this is either a multi-split or expanded transaction, so only
         * deal with this split...  In particular we need to reset the
         * Value if the conv-rate changed.
         *
         * If we handled the debcred then no need to do anything there --
         * the debcred handler did all the computation.  If NOT, then the
         * convrate changed -- reset the value from the amount.
         */
        if (!sd->handled_dc)
        {
            gnc_split_register_save_amount_values (sd, reg);
#if 0
            gnc_numeric value, amount;

            amount = xaccSplitGetAmount (sd->split);
            value = gnc_numeric_div (amount, rate, gnc_commodity_get_fraction (txn_cur),
                                     GNC_HOW_RND_ROUND_HALF_UP);
            xaccSplitSetValue (sd->split, value);
#endif
        }
    }
}
Exemple #25
0
void gncOwnerAutoApplyPaymentsWithLots (const GncOwner *owner, GList *lots)
{
    GList *base_iter;

    /* General note: in the code below the term "payment" can
     * both mean a true payment or a document of
     * the opposite sign (invoice vs credit note) relative to
     * the lot being processed. In general this function will
     * perform a balancing action on a set of lots, so you
     * will also find frequent references to balancing instead. */

    /* Payments can only be applied when at least an owner
     * and a list of lots to use are given */
    if (!owner) return;
    if (!lots) return;

    for (base_iter = lots; base_iter; base_iter = base_iter->next)
    {
        GNCLot *base_lot = base_iter->data;
        QofBook *book;
        Account *acct;
        const gchar *name;
        GList *lot_list, *lot_iter;
        Transaction *txn = NULL;
        gnc_numeric base_lot_bal, val_to_pay, val_paid = { 0, 1 };
        gboolean base_bal_is_pos;
        const gchar *action, *memo;

        /* Only attempt to apply payments to open lots.
         * Note that due to the iterative nature of this function lots
         * in the list may become closed before they are evaluated as
         * base lot, so we should check this for each lot. */
        base_lot_bal = gnc_lot_get_balance (base_lot);
        if (gnc_numeric_zero_p (base_lot_bal))
            continue;

        book = gnc_lot_get_book (base_lot);
        acct = gnc_lot_get_account (base_lot);
        name = gncOwnerGetName (gncOwnerGetEndOwner (owner));
        lot_list = base_iter->next;

        /* Strings used when creating splits later on. */
        action = _("Lot Link");
        memo   = _("Internal link between invoice and payment lots");

        /* Note: to balance the lot the payment to assign
         * must have the opposite sign of the existing lot balance */
        val_to_pay = gnc_numeric_neg (base_lot_bal);
        base_bal_is_pos = gnc_numeric_positive_p (base_lot_bal);


        /* Create splits in a linking transaction between lots until
         * - either the invoice lot is balanced
         * - or there are no more balancing lots.
         */
        for (lot_iter = lot_list; lot_iter; lot_iter = lot_iter->next)
        {
            gnc_numeric payment_lot_balance;
            Split *split;
            Account *bal_acct;
            gnc_numeric  split_amt;

            GNCLot *balancing_lot = lot_iter->data;

            /* Only attempt to use open lots to balance the base lot.
             * Note that due to the iterative nature of this function lots
             * in the list may become closed before they are evaluated as
             * base lot, so we should check this for each lot. */
            if (gnc_lot_is_closed (balancing_lot))
                continue;

            /* Balancing transactions for invoice/payments can only happen
             * in the same account. */
            bal_acct = gnc_lot_get_account (balancing_lot);
            if (acct != bal_acct)
                continue;

            payment_lot_balance = gnc_lot_get_balance (balancing_lot);

            /* Only attempt to balance if the base lot and balancing lot are
             * of the opposite sign. (Otherwise we would increase the balance
             * of the lot - Duh */
            if (base_bal_is_pos == gnc_numeric_positive_p (payment_lot_balance))
                continue;

            /*
             * If there is less to pay than there's open in the lot; we're done -- apply the base_lot_vale.
             * Note that payment_value and balance are opposite in sign, so we have to compare absolute values here
             *
             * Otherwise, apply the balance, subtract that from the payment_value,
             * and move on to the next one.
             */
            if (gnc_numeric_compare (gnc_numeric_abs (val_to_pay), gnc_numeric_abs (payment_lot_balance)) <= 0)
            {
                /* abs(val_to_pay) <= abs(balance) */
                split_amt = val_to_pay;
            }
            else
            {
                /* abs(val_to_pay) > abs(balance)
                 * Remember payment_value and balance are opposite in sign,
                 * and we want a payment to neutralize the current balance
                 * so we need to negate here */
                split_amt = payment_lot_balance;
            }

            /* If not created yet, create a new transaction linking
             * the base lot and the balancing lot(s) */
            if (!txn)
            {
                Timespec ts = xaccTransRetDatePostedTS (xaccSplitGetParent (gnc_lot_get_latest_split (base_lot)));

                xaccAccountBeginEdit (acct);

                txn = xaccMallocTransaction (book);
                xaccTransBeginEdit (txn);

                xaccTransSetDescription (txn, name ? name : "");
                xaccTransSetCurrency (txn, xaccAccountGetCommodity(acct));
                xaccTransSetDateEnteredSecs (txn, gnc_time (NULL));
                xaccTransSetDatePostedTS (txn, &ts);
                xaccTransSetTxnType (txn, TXN_TYPE_LINK);
            }

            /* Create the split for this link in current balancing lot */
            split = xaccMallocSplit (book);
            xaccSplitSetMemo (split, memo);
            /* set Action using utility function */
            gnc_set_num_action (NULL, split, NULL, action);
            xaccAccountInsertSplit (acct, split);
            xaccTransAppendSplit (txn, split);
            xaccSplitSetBaseValue (split, gnc_numeric_neg (split_amt), xaccAccountGetCommodity(acct));
            gnc_lot_add_split (balancing_lot, split);

            /* If the balancing lot was linked to a document (invoice/credit note),
             * send an event for it as well so it gets potentially updated as paid */
            {
                GncInvoice *this_invoice = gncInvoiceGetInvoiceFromLot(balancing_lot);
                if (this_invoice)
                    qof_event_gen (QOF_INSTANCE(this_invoice), QOF_EVENT_MODIFY, NULL);
            }

            val_paid   = gnc_numeric_add (val_paid, split_amt, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
            val_to_pay = gnc_numeric_sub (val_to_pay, split_amt, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
            if (gnc_numeric_zero_p (val_to_pay))
                break;
        }


        /* If the above loop managed to create a transaction and some balancing splits,
         * create the final split for the link transaction in the base lot */
        if (txn)
        {
            GncInvoice *this_invoice;
            Split *split = xaccMallocSplit (book);

            xaccSplitSetMemo (split, memo);
            /* set Action with utiltity function */
            gnc_set_num_action (NULL, split, NULL, action);
            xaccAccountInsertSplit (acct, split);
            xaccTransAppendSplit (txn, split);
            xaccSplitSetBaseValue (split, val_paid, xaccAccountGetCommodity(acct));
            gnc_lot_add_split (base_lot, split);

            xaccTransCommitEdit (txn);
            xaccAccountCommitEdit (acct);

            /* If the base lot was linked to a document (invoice/credit note),
             * send an event for it as well so it gets potentially updated as paid */
            this_invoice = gncInvoiceGetInvoiceFromLot(base_lot);
            if (this_invoice)
                qof_event_gen (QOF_INSTANCE(this_invoice), QOF_EVENT_MODIFY, NULL);

        }

    }
}
Exemple #26
0
gnc_numeric gncEntryGetBalDiscountValue (GncEntry *entry, gboolean round, gboolean is_cust_doc)
{
    gnc_numeric value = gncEntryGetIntDiscountValue (entry, round, is_cust_doc);
    return (is_cust_doc ? gnc_numeric_neg (value) : value);
}
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);
}
Exemple #28
0
gnc_numeric gncEntryGetDocTaxValue (GncEntry *entry, gboolean round, gboolean is_cust_doc, gboolean is_cn)
{
    gnc_numeric value = gncEntryGetIntTaxValue (entry, round, is_cust_doc);
    return (is_cn ? gnc_numeric_neg (value) : value);
}
Exemple #29
0
gnc_numeric gncEntryGetDocQuantity (const GncEntry *entry, gboolean is_cn)
{
    gnc_numeric value = gncEntryGetQuantity (entry);
    return (is_cn ? gnc_numeric_neg (value) : value);
}
Exemple #30
0
void
gnc_payment_window_fill_docs_list (PaymentWindow *pw)
{
    GtkListStore *store;
    GList *list = NULL, *node;

    g_return_if_fail (pw->docs_list_tree_view && GTK_IS_TREE_VIEW(pw->docs_list_tree_view));

    /* Get a list of open lots for this owner and post account */
    if (pw->owner.owner.undefined)
        list = xaccAccountFindOpenLots (pw->post_acct, gncOwnerLotMatchOwnerFunc,
                                        &pw->owner, NULL);

    /* Clear the existing list */
    store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(pw->docs_list_tree_view)));
    gtk_list_store_clear(store);

    /* Add the documents and overpayments to the tree view */
    for (node = list; node; node = node->next)
    {
        GNCLot *lot = node->data;
        time64 doc_date_time = 0;
        const gchar *doc_type_str = NULL;
        const gchar *doc_id_str   = NULL;
        const gchar *doc_deb_str  = NULL;
        const gchar *doc_cred_str = NULL;
        GtkTreeIter iter;
        Timespec doc_date;
        GncInvoice *document;
        gnc_numeric value = gnc_numeric_zero();
        gnc_numeric debit = gnc_numeric_zero();
        gnc_numeric credit = gnc_numeric_zero();

        /* Find the lot's document if it exists,
         * it could also be a prepayment lot. */
        document = gncInvoiceGetInvoiceFromLot (lot);

        /* Find the document's date or pre-payment date */
        if (document)
            doc_date = gncInvoiceGetDatePosted (document);
        else
        {
            /* Calculate the payment date based on the lot splits */
            Transaction *trans = xaccSplitGetParent (gnc_lot_get_latest_split (lot));
            if (trans)
                doc_date = xaccTransRetDatePostedTS (trans);
            else
                continue; /* No valid split in this lot, skip it */
        }
        doc_date_time = timespecToTime64 (doc_date);

        /* Find the document type. No type means pre-payment in this case */
        if (document)
        {
            doc_type_str = gncInvoiceGetTypeString (document);
        }
        else
            doc_type_str = _("Pre-Payment");

        /* Find the document id. Empty for pre-payments. */
        if (document)
        {
            doc_id_str = gncInvoiceGetID (document);
        }

        /* Find the debit/credit amount.
         * Invoices/vendor credit notes are debit (increasing the balance)
         * Customer credit notes/bills are credit (decreasing the balance)
         * Pre-payments are debit or credit depending on their sign
         */
        value = gnc_lot_get_balance (lot);

        if (gnc_numeric_positive_p (value))
            debit = value;
        else
            credit = gnc_numeric_neg (value);

        /* Only display non-zero debits/credits */
        if (!gnc_numeric_zero_p (debit))
            doc_deb_str = xaccPrintAmount (debit, gnc_default_print_info (FALSE));
        if (!gnc_numeric_zero_p (credit))
            doc_cred_str = xaccPrintAmount (credit, gnc_default_print_info (FALSE));

        gtk_list_store_append (store, &iter);
        gtk_list_store_set (store, &iter,
                            0, doc_date_time,
                            1, doc_id_str,
                            2, doc_type_str,
                            3, doc_deb_str,
                            4, doc_cred_str,
                            5, (gpointer)lot,
                            -1);

    }

    g_list_free (list);

    /* Highlight the preset invoice if it's in the new list */
    gnc_payment_dialog_highlight_document (pw);
}