mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Conrad Canterford's register patch.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3440 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
@@ -238,6 +238,8 @@ static void xaccSRSetTransVisible (SplitRegister *reg,
|
|||||||
gboolean only_blank_split);
|
gboolean only_blank_split);
|
||||||
static gboolean trans_has_reconciled_splits (Transaction *trans);
|
static gboolean trans_has_reconciled_splits (Transaction *trans);
|
||||||
static void sr_set_last_num (SplitRegister *reg, const char *num);
|
static void sr_set_last_num (SplitRegister *reg, const char *num);
|
||||||
|
static guint32 sr_split_auto_calc (SplitRegister *reg, Split *split,
|
||||||
|
guint32 changed);
|
||||||
|
|
||||||
|
|
||||||
/** implementations *******************************************************/
|
/** implementations *******************************************************/
|
||||||
@@ -2879,6 +2881,205 @@ sr_set_last_num (SplitRegister *reg, const char *num)
|
|||||||
|
|
||||||
/* ======================================================== */
|
/* ======================================================== */
|
||||||
|
|
||||||
|
static guint32
|
||||||
|
sr_split_auto_calc (SplitRegister *reg, Split *split, guint32 changed)
|
||||||
|
{
|
||||||
|
gboolean recalc_shares = FALSE;
|
||||||
|
gboolean recalc_price = FALSE;
|
||||||
|
gboolean recalc_value = FALSE;
|
||||||
|
GNCAccountType account_type;
|
||||||
|
gnc_numeric calc_value;
|
||||||
|
gnc_numeric value;
|
||||||
|
gnc_numeric price;
|
||||||
|
gnc_numeric amount;
|
||||||
|
Account *account;
|
||||||
|
int denom;
|
||||||
|
|
||||||
|
/* First, check if this is an account other than STOCK or
|
||||||
|
* MUTUAL type. If it is, this is a bank balancing split, so
|
||||||
|
* don't recalc anything.*/
|
||||||
|
|
||||||
|
account = xaccSplitGetAccount (split);
|
||||||
|
account_type = xaccAccountGetType (account);
|
||||||
|
|
||||||
|
if (account_type != STOCK &&
|
||||||
|
account_type != MUTUAL &&
|
||||||
|
account_type != CURRENCY)
|
||||||
|
return changed;
|
||||||
|
|
||||||
|
if (MOD_SHRS & changed)
|
||||||
|
amount = xaccGetPriceCellValue (reg->sharesCell);
|
||||||
|
else
|
||||||
|
amount = xaccSplitGetShareAmount (split);
|
||||||
|
|
||||||
|
if (MOD_PRIC & changed)
|
||||||
|
price = xaccGetPriceCellValue (reg->priceCell);
|
||||||
|
else
|
||||||
|
price = xaccSplitGetSharePrice (split);
|
||||||
|
|
||||||
|
if (MOD_AMNT & changed)
|
||||||
|
{
|
||||||
|
gnc_numeric credit = xaccGetPriceCellValue (reg->creditCell);
|
||||||
|
gnc_numeric debit = xaccGetPriceCellValue (reg->debitCell);
|
||||||
|
value = gnc_numeric_sub_fixed (debit, credit);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
value = xaccSplitGetValue (split);
|
||||||
|
|
||||||
|
/* Check if precisely one value is zero. If so, we can assume that the
|
||||||
|
* zero value needs to be recalculated. */
|
||||||
|
|
||||||
|
if (!gnc_numeric_zero_p (amount))
|
||||||
|
{
|
||||||
|
if (gnc_numeric_zero_p (price))
|
||||||
|
{
|
||||||
|
if (!gnc_numeric_zero_p (value))
|
||||||
|
recalc_price = TRUE;
|
||||||
|
}
|
||||||
|
else if (gnc_numeric_zero_p (value))
|
||||||
|
recalc_value = TRUE;
|
||||||
|
}
|
||||||
|
else if (!gnc_numeric_zero_p (price))
|
||||||
|
if (!gnc_numeric_zero_p (value))
|
||||||
|
recalc_shares = TRUE;
|
||||||
|
|
||||||
|
/* If we have not already flaged a recalc, check if this is a split
|
||||||
|
* which has 2 of the 3 values changed. */
|
||||||
|
|
||||||
|
if((!recalc_shares) &&
|
||||||
|
(!recalc_price) &&
|
||||||
|
(!recalc_value))
|
||||||
|
{
|
||||||
|
if (((MOD_PRIC | MOD_AMNT) & changed) == (MOD_PRIC | MOD_AMNT))
|
||||||
|
{
|
||||||
|
if (!(MOD_SHRS & changed))
|
||||||
|
recalc_shares = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (((MOD_SHRS | MOD_AMNT) & changed) == (MOD_SHRS | MOD_AMNT))
|
||||||
|
recalc_price = TRUE;
|
||||||
|
else
|
||||||
|
if (((MOD_SHRS | MOD_PRIC) & changed) == (MOD_SHRS | MOD_PRIC))
|
||||||
|
recalc_value = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
calc_value = gnc_numeric_mul (price, amount,
|
||||||
|
GNC_DENOM_AUTO, GNC_DENOM_LCD);
|
||||||
|
|
||||||
|
denom = gnc_split_get_value_denom (split);
|
||||||
|
|
||||||
|
/* Now, if we have not flagged one of the recalcs, and value and
|
||||||
|
* calc_value are not the same number, then we need to ask for
|
||||||
|
* help from the user. */
|
||||||
|
|
||||||
|
if (!recalc_shares &&
|
||||||
|
!recalc_price &&
|
||||||
|
!recalc_value &&
|
||||||
|
!gnc_numeric_same (value, calc_value, denom, GNC_RND_ROUND))
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int choice;
|
||||||
|
int default_value;
|
||||||
|
char *radio_list[4] = { NULL, NULL, NULL, NULL };
|
||||||
|
const char *title = _("Recalculate Transaction");
|
||||||
|
const char *message = _("The values entered for this transaction "
|
||||||
|
"are inconsistent.\nWhich value would you "
|
||||||
|
"like to have recalculated?");
|
||||||
|
|
||||||
|
if (MOD_SHRS & changed)
|
||||||
|
radio_list[0] = g_strdup_printf ("%s (%s)", _("Shares"), _("Changed"));
|
||||||
|
else
|
||||||
|
radio_list[0] = g_strdup (_("Shares"));
|
||||||
|
|
||||||
|
if (MOD_PRIC & changed)
|
||||||
|
radio_list[1] = g_strdup_printf ("%s (%s)", _("Price"), _("Changed"));
|
||||||
|
else
|
||||||
|
radio_list[1] = g_strdup (_("Price"));
|
||||||
|
|
||||||
|
if (MOD_AMNT & changed)
|
||||||
|
radio_list[2] = g_strdup_printf ("%s (%s)", _("Value"), _("Changed"));
|
||||||
|
else
|
||||||
|
radio_list[2] = g_strdup (_("Value"));
|
||||||
|
|
||||||
|
if (!(MOD_PRIC & changed))
|
||||||
|
default_value = 1;
|
||||||
|
if (!(MOD_SHRS & changed))
|
||||||
|
default_value = 0;
|
||||||
|
else if (!(MOD_AMNT & changed))
|
||||||
|
default_value = 2;
|
||||||
|
else
|
||||||
|
default_value = 1;
|
||||||
|
|
||||||
|
choice = gnc_choose_radio_option_dialog_parented (xaccSRGetParent(reg),
|
||||||
|
title,
|
||||||
|
message,
|
||||||
|
default_value,
|
||||||
|
radio_list);
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
g_free (radio_list[i]);
|
||||||
|
|
||||||
|
switch(choice)
|
||||||
|
{
|
||||||
|
case 0: /* Modify number of shares */
|
||||||
|
recalc_shares = TRUE;
|
||||||
|
break;
|
||||||
|
case 1: /* Modify the share price */
|
||||||
|
recalc_price = TRUE;
|
||||||
|
break;
|
||||||
|
case 2: /* Modify total value */
|
||||||
|
recalc_value = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recalc_shares)
|
||||||
|
if (!gnc_numeric_zero_p (price))
|
||||||
|
{
|
||||||
|
denom = gnc_split_get_quantity_denom (split);
|
||||||
|
|
||||||
|
amount = gnc_numeric_div (value, price, denom, GNC_RND_ROUND);
|
||||||
|
|
||||||
|
xaccSetPriceCellValue (reg->sharesCell, amount);
|
||||||
|
changed |= MOD_SHRS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recalc_price)
|
||||||
|
if (!gnc_numeric_zero_p (amount))
|
||||||
|
{
|
||||||
|
price = gnc_numeric_div (value, amount,
|
||||||
|
GNC_DENOM_AUTO,
|
||||||
|
GNC_DENOM_EXACT);
|
||||||
|
|
||||||
|
if (gnc_numeric_negative_p (price))
|
||||||
|
{
|
||||||
|
price = gnc_numeric_neg (price);
|
||||||
|
xaccSetDebCredCellValue (reg->debitCell, reg->creditCell,
|
||||||
|
gnc_numeric_neg (value));
|
||||||
|
changed |= MOD_AMNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
xaccSetPriceCellValue (reg->priceCell, price);
|
||||||
|
changed |= MOD_PRIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recalc_value)
|
||||||
|
{
|
||||||
|
denom = gnc_split_get_value_denom (split);
|
||||||
|
|
||||||
|
value = gnc_numeric_mul (price, amount, denom, GNC_RND_ROUND);
|
||||||
|
|
||||||
|
xaccSetDebCredCellValue (reg->debitCell, reg->creditCell, value);
|
||||||
|
changed |= MOD_AMNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ======================================================== */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xaccSRSaveChangedCells (SplitRegister *reg, Transaction *trans, Split *split)
|
xaccSRSaveChangedCells (SplitRegister *reg, Transaction *trans, Split *split)
|
||||||
{
|
{
|
||||||
@@ -3084,216 +3285,15 @@ xaccSRSaveChangedCells (SplitRegister *reg, Transaction *trans, Split *split)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we have a stock, currency or portfolio register type, and
|
||||||
|
* changes have been made to the number of shares, the price, or the
|
||||||
|
* value, then we need to do some calculations to make sure it all
|
||||||
|
* balances properly.*/
|
||||||
if (((MOD_AMNT | MOD_PRIC | MOD_SHRS) & changed) &&
|
if (((MOD_AMNT | MOD_PRIC | MOD_SHRS) & changed) &&
|
||||||
((STOCK_REGISTER == (reg->type)) ||
|
((STOCK_REGISTER == (reg->type)) ||
|
||||||
(CURRENCY_REGISTER == (reg->type)) ||
|
(CURRENCY_REGISTER == (reg->type)) ||
|
||||||
(PORTFOLIO_LEDGER == (reg->type))))
|
(PORTFOLIO_LEDGER == (reg->type))))
|
||||||
{
|
changed = sr_split_auto_calc (reg, split, changed);
|
||||||
gboolean recalc_shares = FALSE;
|
|
||||||
gboolean recalc_price = FALSE;
|
|
||||||
gboolean recalc_value = FALSE;
|
|
||||||
gboolean recalc_none = FALSE;
|
|
||||||
GNCAccountType account_type;
|
|
||||||
gnc_numeric calc_value;
|
|
||||||
gnc_numeric value;
|
|
||||||
gnc_numeric price;
|
|
||||||
gnc_numeric amount;
|
|
||||||
Account *account;
|
|
||||||
int denom;
|
|
||||||
|
|
||||||
if (MOD_SHRS & changed)
|
|
||||||
amount = xaccGetPriceCellValue (reg->sharesCell);
|
|
||||||
else
|
|
||||||
amount = xaccSplitGetShareAmount (split);
|
|
||||||
|
|
||||||
if (MOD_PRIC & changed)
|
|
||||||
price = xaccGetPriceCellValue (reg->priceCell);
|
|
||||||
else
|
|
||||||
price = xaccSplitGetSharePrice (split);
|
|
||||||
|
|
||||||
if (MOD_AMNT & changed)
|
|
||||||
{
|
|
||||||
gnc_numeric credit = xaccGetPriceCellValue (reg->creditCell);
|
|
||||||
gnc_numeric debit = xaccGetPriceCellValue (reg->debitCell);
|
|
||||||
value = gnc_numeric_sub_fixed (debit, credit);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
value = xaccSplitGetValue(split);
|
|
||||||
|
|
||||||
/* First, we check if this is a split which has 2 of the 3 values
|
|
||||||
* changed. */
|
|
||||||
|
|
||||||
if (((MOD_PRIC | MOD_AMNT) & changed) == (MOD_PRIC | MOD_AMNT))
|
|
||||||
{
|
|
||||||
if (!(MOD_SHRS & changed))
|
|
||||||
recalc_shares = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (((MOD_SHRS | MOD_AMNT) & changed) == (MOD_SHRS | MOD_AMNT))
|
|
||||||
recalc_price = TRUE;
|
|
||||||
else
|
|
||||||
if (((MOD_SHRS | MOD_PRIC) & changed) == (MOD_SHRS | MOD_PRIC))
|
|
||||||
recalc_value = TRUE;
|
|
||||||
|
|
||||||
/* Next, check if one value has been changed, and one other value is
|
|
||||||
* zero. */
|
|
||||||
|
|
||||||
if (MOD_SHRS & changed)
|
|
||||||
{
|
|
||||||
if (gnc_numeric_zero_p (price))
|
|
||||||
{
|
|
||||||
if (!gnc_numeric_zero_p (value))
|
|
||||||
recalc_price = TRUE;
|
|
||||||
}
|
|
||||||
else if (gnc_numeric_zero_p (value))
|
|
||||||
recalc_value = TRUE;
|
|
||||||
}
|
|
||||||
else if (MOD_PRIC & changed)
|
|
||||||
{
|
|
||||||
if (gnc_numeric_zero_p (amount))
|
|
||||||
{
|
|
||||||
if (!gnc_numeric_zero_p (value))
|
|
||||||
recalc_shares = TRUE;
|
|
||||||
}
|
|
||||||
else if (gnc_numeric_zero_p (value))
|
|
||||||
recalc_value = TRUE;
|
|
||||||
}
|
|
||||||
else if (MOD_AMNT & changed)
|
|
||||||
{
|
|
||||||
if (gnc_numeric_zero_p (amount))
|
|
||||||
{
|
|
||||||
if (!gnc_numeric_zero_p (price))
|
|
||||||
recalc_shares = TRUE;
|
|
||||||
}
|
|
||||||
else if (gnc_numeric_zero_p (price))
|
|
||||||
recalc_price = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finally, check if this is an account other than STOCK or
|
|
||||||
* MUTUAL type. If it is, this is a bank balancing split, so
|
|
||||||
* don't recalc anything.*/
|
|
||||||
|
|
||||||
account = xaccSplitGetAccount (split);
|
|
||||||
account_type = xaccAccountGetType (account);
|
|
||||||
|
|
||||||
if (account_type != STOCK &&
|
|
||||||
account_type != MUTUAL &&
|
|
||||||
account_type != CURRENCY)
|
|
||||||
recalc_none = TRUE;
|
|
||||||
|
|
||||||
calc_value = gnc_numeric_mul (price, amount,
|
|
||||||
GNC_DENOM_AUTO, GNC_DENOM_LCD);
|
|
||||||
|
|
||||||
denom = gnc_split_get_value_denom (split);
|
|
||||||
|
|
||||||
/* Now, if we have not flagged one of the recalcs, and value and
|
|
||||||
* calc_value are not the same number, then we need to ask for
|
|
||||||
* help from the user. */
|
|
||||||
|
|
||||||
if (!recalc_shares &&
|
|
||||||
!recalc_price &&
|
|
||||||
!recalc_value &&
|
|
||||||
!recalc_none &&
|
|
||||||
!gnc_numeric_same (value, calc_value, denom, GNC_RND_ROUND))
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int choice;
|
|
||||||
int default_value;
|
|
||||||
char *radio_list[4] = { NULL, NULL, NULL, NULL };
|
|
||||||
const char *title = _("Recalculate Transaction");
|
|
||||||
const char *message = _("The values entered for this transaction "
|
|
||||||
"are inconsistent.\nWhich value would you "
|
|
||||||
"like to have recalculated?");
|
|
||||||
|
|
||||||
if (MOD_SHRS & changed)
|
|
||||||
radio_list[0] = g_strdup_printf ("%s (%s)", _("Shares"), _("Changed"));
|
|
||||||
else
|
|
||||||
radio_list[0] = g_strdup (_("Shares"));
|
|
||||||
|
|
||||||
if (MOD_PRIC & changed)
|
|
||||||
radio_list[1] = g_strdup_printf ("%s (%s)", _("Price"), _("Changed"));
|
|
||||||
else
|
|
||||||
radio_list[1] = g_strdup (_("Price"));
|
|
||||||
|
|
||||||
if (MOD_AMNT & changed)
|
|
||||||
radio_list[2] = g_strdup_printf ("%s (%s)", _("Value"), _("Changed"));
|
|
||||||
else
|
|
||||||
radio_list[2] = g_strdup (_("Value"));
|
|
||||||
|
|
||||||
if (!(MOD_PRIC & changed))
|
|
||||||
default_value = 1;
|
|
||||||
if (!(MOD_SHRS & changed))
|
|
||||||
default_value = 0;
|
|
||||||
else if (!(MOD_AMNT & changed))
|
|
||||||
default_value = 2;
|
|
||||||
else
|
|
||||||
default_value = 1;
|
|
||||||
|
|
||||||
choice = gnc_choose_radio_option_dialog_parented (xaccSRGetParent(reg),
|
|
||||||
title,
|
|
||||||
message,
|
|
||||||
default_value,
|
|
||||||
radio_list);
|
|
||||||
|
|
||||||
for (i = 0; i < 3; i++)
|
|
||||||
g_free (radio_list[i]);
|
|
||||||
|
|
||||||
switch(choice)
|
|
||||||
{
|
|
||||||
case 0: /* Modify number of shares */
|
|
||||||
recalc_shares = TRUE;
|
|
||||||
break;
|
|
||||||
case 1: /* Modify the share price */
|
|
||||||
recalc_price = TRUE;
|
|
||||||
break;
|
|
||||||
case 2: /* Modify total value */
|
|
||||||
recalc_value = TRUE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (recalc_shares)
|
|
||||||
if (!gnc_numeric_zero_p (price))
|
|
||||||
{
|
|
||||||
denom = gnc_split_get_quantity_denom (split);
|
|
||||||
|
|
||||||
amount = gnc_numeric_div (value, price, denom, GNC_RND_ROUND);
|
|
||||||
|
|
||||||
xaccSetPriceCellValue (reg->sharesCell, amount);
|
|
||||||
changed |= MOD_SHRS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (recalc_price)
|
|
||||||
if (!gnc_numeric_zero_p (amount))
|
|
||||||
{
|
|
||||||
price = gnc_numeric_div (value, amount,
|
|
||||||
GNC_DENOM_AUTO,
|
|
||||||
GNC_DENOM_EXACT);
|
|
||||||
|
|
||||||
if (gnc_numeric_negative_p (price))
|
|
||||||
{
|
|
||||||
price = gnc_numeric_neg (price);
|
|
||||||
xaccSetDebCredCellValue (reg->debitCell, reg->creditCell,
|
|
||||||
gnc_numeric_neg (value));
|
|
||||||
changed |= MOD_AMNT;
|
|
||||||
}
|
|
||||||
|
|
||||||
xaccSetPriceCellValue (reg->priceCell, price);
|
|
||||||
changed |= MOD_PRIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (recalc_value)
|
|
||||||
{
|
|
||||||
denom = gnc_split_get_value_denom (split);
|
|
||||||
|
|
||||||
value = gnc_numeric_mul (price, amount, denom, GNC_RND_ROUND);
|
|
||||||
|
|
||||||
xaccSetDebCredCellValue (reg->debitCell, reg->creditCell, value);
|
|
||||||
changed |= MOD_AMNT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MOD_SHRS & changed)
|
if (MOD_SHRS & changed)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user