Exemplo n.º 1
0
/** Adds a split to a transaction.
 * @param trans The transaction to add a split to
 * @param account The split's account
 * @param amount The split's amount
 * @param rec_state The split's reconcile status
 * @param rec_date The split's reconcile date
 * @param price The split's conversion rate from account commodity to transaction commodity
 */
static void trans_add_split (Transaction* trans, Account* account, GncNumeric amount,
                            const boost::optional<std::string>& action,
                            const boost::optional<std::string>& memo,
                            const boost::optional<char>& rec_state,
                            const boost::optional<GncDate>& rec_date,
                            const boost::optional<GncNumeric> price)
{
    QofBook* book = xaccTransGetBook (trans);
    auto split = xaccMallocSplit (book);
    xaccSplitSetAccount (split, account);
    xaccSplitSetParent (split, trans);
    xaccSplitSetAmount (split, static_cast<gnc_numeric>(amount));
    auto trans_curr = xaccTransGetCurrency(trans);
    auto acct_comm = xaccAccountGetCommodity(account);
    GncNumeric value;
    if (gnc_commodity_equiv(trans_curr, acct_comm))
        value = amount;
    else if (price)
        value = amount * *price;
    else
    {
        auto time = xaccTransRetDatePosted (trans);
        /* Import data didn't specify price, let's lookup the nearest in time */
        auto nprice =
            gnc_pricedb_lookup_nearest_in_time64(gnc_pricedb_get_db(book),
                                                 acct_comm, trans_curr, time);
        if (nprice)
        {
            /* Found a usable price. Let's check if the conversion direction is right */
            GncNumeric rate;
            if (gnc_commodity_equiv(gnc_price_get_currency(nprice), trans_curr))
                rate = gnc_price_get_value(nprice);
            else
                rate = static_cast<GncNumeric>(gnc_price_get_value(nprice)).inv();

            value = amount * rate;
        }
        else
        {
            PWARN("No price found, using a price of 1.");
            value = amount;
        }
    }
    xaccSplitSetValue (split, static_cast<gnc_numeric>(value));

    if (memo)
        xaccSplitSetMemo (split, memo->c_str());
    /* Note, this function assumes the num/action switch is done at a higher level
     * if needed by the book option */
    if (action)
        xaccSplitSetAction (split, action->c_str());

    if (rec_state && *rec_state != 'n')
        xaccSplitSetReconcile (split, *rec_state);
    if (rec_state && *rec_state == YREC && rec_date)
        xaccSplitSetDateReconciledSecs (split,
                static_cast<time64>(GncDateTime(*rec_date, DayPart::neutral)));

}
Exemplo n.º 2
0
static Split *
DirectionPolicyGetSplit (GNCPolicy *pcy, GNCLot *lot, short reverse)
{
    Split *split;
    SplitList *node;
    gnc_commodity *common_currency;
    gboolean want_positive;
    gnc_numeric baln;
    Split *osplit;
    Transaction *otrans;
    time64 open_time;
    Account* lot_account;

    if (!pcy || !lot || !gnc_lot_get_split_list(lot)) return NULL;
    lot_account = gnc_lot_get_account(lot);
    if (!lot_account) return NULL;

    /* Recomputing the balance re-evaluates the lot closure */
    baln = gnc_lot_get_balance (lot);
    if (gnc_lot_is_closed(lot)) return NULL;

    want_positive = gnc_numeric_negative_p (baln);

    /* All splits in lot must share a common transaction currency. */
    split = gnc_lot_get_split_list(lot)->data;
    common_currency = split->parent->common_currency;

    /* Don't add a split to the lot unless it will be the new last
       split in the lot.  Otherwise our balance tests will be wrong
       and the lot may end up too thin or too fat. */
    osplit = gnc_lot_get_latest_split (lot);
    otrans = osplit ? xaccSplitGetParent (osplit) : 0;
    open_time = xaccTransRetDatePosted (otrans);

    /* Walk over *all* splits in the account, till we find one that
     * hasn't been assigned to a lot.  Return that split.
     * Make use of the fact that the splits in an account are
     * already in date order; so we don't have to sort. */
    node = xaccAccountGetSplitList (lot_account);
    if (reverse)
    {
        node = g_list_last (node);
    }
    while (node)
    {
        gboolean is_match;
        gboolean is_positive;
        time64 this_time;
        split = node->data;
        if (split->lot) goto donext;

        /* Skip it if it's too early */
        this_time = xaccTransRetDatePosted ( xaccSplitGetParent (split));
        if (this_time < open_time)
        {
            if (reverse)
                /* Going backwards, no point in looking further */
                break;
            goto donext;
        }

        /* Allow equiv currencies */
        is_match = gnc_commodity_equiv (common_currency,
                                        split->parent->common_currency);
        if (FALSE == is_match) goto donext;

        /* Disallow zero-amount splits in general. */
        if (gnc_numeric_zero_p(split->amount)) goto donext;

        is_positive = gnc_numeric_positive_p (split->amount);
        if ((want_positive && is_positive) ||
                ((!want_positive) && (!is_positive))) return split;
donext:
        if (reverse)
        {
            node = node->prev;
        }
        else
        {
            node = node->next;
        }
    }
    return NULL;
}
Exemplo n.º 3
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 (GTK_WIDGET (view), 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, xaccTransRetDatePosted (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;
}