예제 #1
0
/* Is this split part of a multi split transaction */
gboolean
gnc_tree_util_split_reg_is_multi (Split *split)
{
    gboolean multi = FALSE;
    Split *osplit;

    if (!split)
        return FALSE;

    osplit = xaccSplitGetOtherSplit (split);

    if (osplit)
            multi = FALSE;
    else
    {
        /* For multi-split transactions and stock splits,
         * use a special value. */
        osplit = xaccTransGetSplit (xaccSplitGetParent (split), 1);

        if (osplit)
            multi = TRUE;
        else if (g_strcmp0 ("stock-split", xaccSplitGetType (split)) == 0)
            multi = TRUE;
        else
            multi = FALSE;
    }
    return multi;
}
static void
gnc_split_register_save_mxfrm_cell (BasicCell * cell,
                                    gpointer save_data,
                                    gpointer user_data)
{
    SRSaveData *sd = save_data;
    SplitRegister *reg = user_data;
    Split * other_split;

    g_return_if_fail (gnc_basic_cell_has_name (cell, MXFRM_CELL));

    other_split = xaccSplitGetOtherSplit (sd->split);

    /* other_split may be null for two very different reasons:
     * (1) the parent transaction has three or more splits in it,
     *     and so the "other" split is ambiguous, and thus null.
     * (2) the parent transaction has only this one split as a child.
     *     and "other" is null because there is no other.
     *
     * In the case (2), we want to create the other split, so that
     * the user's request to transfer actually works out. */

    if (!other_split)
    {
        other_split = xaccTransGetSplit (sd->trans, 1);

        if (!other_split)
        {
            other_split = xaccMallocSplit (gnc_get_current_book ());
            xaccTransAppendSplit (sd->trans, other_split);
        }
    }

    if (other_split)
    {
        Account *old_acc;
        Account *new_acc;

        /* Do some reparenting. Insertion into new account
         * will automatically delete from the old account. */
        old_acc = xaccSplitGetAccount (other_split);
        new_acc = gnc_split_register_get_account (reg, MXFRM_CELL);

        if ((new_acc != NULL) && (old_acc != new_acc))
            xaccAccountInsertSplit (new_acc, other_split);
    }
}
예제 #3
0
/* Return the string entry for transfer column and if multi */
const char *
gnc_tree_util_split_reg_get_transfer_entry (Split *split, gboolean *is_multi)
{
    static char *name = NULL;
    gboolean multi = FALSE;

    Split *osplit;

    if (is_multi)
        *is_multi = multi;

    if (!split)
        return NULL;

    osplit = xaccSplitGetOtherSplit (split);

    g_free (name);

    if (osplit)
        name = gnc_get_account_name_for_register (xaccSplitGetAccount (osplit));
    else
    {
        /* For multi-split transactions and stock splits,
         * use a special value. */
        osplit = xaccTransGetSplit (xaccSplitGetParent (split), 1);
        if (osplit)
        {
            name = g_strdup (SPLIT_TRANS_STR);
            multi = TRUE;
        }
        else if (g_strcmp0 ("stock-split", xaccSplitGetType (split)) == 0)
        {
            name = g_strdup (STOCK_SPLIT_STR);
            multi = TRUE;
        }
        else
            name = g_strdup ("");
    }

    if (is_multi)
        *is_multi = multi;

    return name;
}
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
        }
    }
}
예제 #5
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("");
}
예제 #6
0
 Split getOtherSplit() const { return xaccSplitGetOtherSplit(get()); }