mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
* src/register/ledger-core/split-register-control.c:
- Don't grab the register account for multi-split txns. Just return NULL. - Better logic in the exchange-rate handler function for when to pop up the dialog, and what to put into it. - add an error dialog for corner cases where we want to force the user to expand the txn in order to get proper conversions. * src/register/ledger-core/split-register-model-save.c: - export "split_needs_amount()" for use elsewhere - fix the logic in handling debcred changes, in particular for multi-currency cases. Convert amount->value->amount properly. - handle the case where you change the exchange-rate manually (and do nothing else). - fix the logic in the save-split post-processing for what gets converted when. * src/register/ledger-core/split-register-p.h: - export the "split_needs_amount()" api for use in the register. FIXES bug #100489 git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@7648 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
96c1ab0cb9
commit
f559c850a3
24
ChangeLog
24
ChangeLog
@ -1,3 +1,27 @@
|
||||
2002-12-07 Derek Atkins <derek@ihtfp.com>
|
||||
|
||||
* src/register/ledger-core/split-register-control.c:
|
||||
- Don't grab the register account for multi-split txns. Just return NULL.
|
||||
- Better logic in the exchange-rate handler function for when to
|
||||
pop up the dialog, and what to put into it.
|
||||
- add an error dialog for corner cases where we want to force
|
||||
the user to expand the txn in order to get proper conversions.
|
||||
|
||||
* src/register/ledger-core/split-register-model-save.c:
|
||||
- export "split_needs_amount()" for use elsewhere
|
||||
- fix the logic in handling debcred changes, in particular for
|
||||
multi-currency cases. Convert amount->value->amount properly.
|
||||
- handle the case where you change the exchange-rate manually
|
||||
(and do nothing else).
|
||||
- fix the logic in the save-split post-processing for what gets
|
||||
converted when.
|
||||
|
||||
* src/register/ledger-core/split-register-p.h:
|
||||
- export the "split_needs_amount()" api for use in the register.
|
||||
|
||||
FIXES bug #100489
|
||||
|
||||
|
||||
2002-12-7 Benoit Grégoire <bock@step.polymtl.ca>
|
||||
More Doxygenification. Created an Engine module, and a
|
||||
Deprecated list. Unfortunately, unless we turn on EXTRACT_ALL
|
||||
|
@ -961,8 +961,8 @@ gnc_split_register_traverse_check_stock_shares (SplitRegister *reg, const char *
|
||||
}
|
||||
|
||||
static Account *
|
||||
gnc_split_register_get_account_always (SplitRegister *reg, const char * cell_name,
|
||||
gboolean force)
|
||||
gnc_split_register_get_account_always (SplitRegister *reg, const char * cell_name)
|
||||
|
||||
{
|
||||
BasicCell *cell;
|
||||
const char *name;
|
||||
@ -975,10 +975,7 @@ gnc_split_register_get_account_always (SplitRegister *reg, const char * cell_nam
|
||||
|
||||
/* If 'name' is "-- Split Transaction --" then return NULL or the register acct */
|
||||
if (!safe_strcmp (name, _("-- Split Transaction --"))) {
|
||||
if (force)
|
||||
return gnc_split_register_get_default_account (reg);
|
||||
else
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gnc_split_register_get_account_by_name (reg, cell, name, &dummy);
|
||||
@ -1021,15 +1018,15 @@ gboolean
|
||||
gnc_split_register_handle_exchange (SplitRegister *reg, gboolean force_dialog)
|
||||
{
|
||||
Transaction *txn;
|
||||
Split *osplit;
|
||||
Split *split, *osplit;
|
||||
Account *xfer_acc, *reg_acc;
|
||||
gnc_commodity *txn_cur, *xfer_com, *reg_com;
|
||||
gnc_numeric amount, exch_rate;
|
||||
XferDialog *xfer;
|
||||
gboolean used_mxfrm = FALSE;
|
||||
gboolean swap_amounts = FALSE;
|
||||
gboolean expanded = FALSE;
|
||||
PriceCell *rate_cell;
|
||||
const char *message;
|
||||
|
||||
/* Make sure we NEED this for this type of register */
|
||||
rate_cell = (PriceCell*) gnc_table_layout_get_cell (reg->table->layout, RATE_CELL);
|
||||
@ -1045,12 +1042,21 @@ gnc_split_register_handle_exchange (SplitRegister *reg, gboolean force_dialog)
|
||||
expanded = gnc_split_register_current_trans_expanded (reg);
|
||||
|
||||
/* Grab the xfer account */
|
||||
xfer_acc = gnc_split_register_get_account_always (reg, XFRM_CELL, FALSE);
|
||||
if (!xfer_acc) {
|
||||
used_mxfrm = TRUE;
|
||||
xfer_acc = gnc_split_register_get_account_always (reg, MXFRM_CELL, !expanded);
|
||||
if (expanded)
|
||||
xfer_acc = gnc_split_register_get_account_always (reg, XFRM_CELL);
|
||||
else
|
||||
xfer_acc = gnc_split_register_get_account_always (reg, MXFRM_CELL);
|
||||
|
||||
message =
|
||||
_("You need to expand the transaction in order to modify its exchange rates.");
|
||||
|
||||
/* If this is an un-expanded, multi-split transaction, then warn the user */
|
||||
if (force_dialog && !expanded && ! xfer_acc) {
|
||||
gnc_error_dialog (message);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* No account -- don't run the dialog */
|
||||
if (!xfer_acc)
|
||||
return FALSE;
|
||||
|
||||
@ -1064,8 +1070,8 @@ gnc_split_register_handle_exchange (SplitRegister *reg, gboolean force_dialog)
|
||||
reg_com = xaccAccountGetCommodity (reg_acc);
|
||||
|
||||
/* Is this a two-split txn? */
|
||||
osplit = gnc_split_register_get_current_split (reg);
|
||||
osplit = xaccSplitGetOtherSplit (osplit);
|
||||
split = gnc_split_register_get_current_split (reg);
|
||||
osplit = xaccSplitGetOtherSplit (split);
|
||||
|
||||
/* Check if the txn- and xfer- commodities are the same */
|
||||
if (gnc_commodity_equal (txn_cur, xfer_com)) {
|
||||
@ -1088,6 +1094,17 @@ gnc_split_register_handle_exchange (SplitRegister *reg, gboolean force_dialog)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* If this is a non-expanded, two-split txn where BOTH splits need
|
||||
* conversion rates, then require the user to actually expand the
|
||||
* transaction in order to edit it.
|
||||
*/
|
||||
if (!expanded && osplit &&
|
||||
gnc_split_register_split_needs_amount (split) &&
|
||||
gnc_split_register_split_needs_amount (osplit)) {
|
||||
gnc_error_dialog (message);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Ok, we need to grab the exchange rate */
|
||||
amount = gnc_split_register_debcred_cell_value (reg);
|
||||
|
||||
|
@ -370,7 +370,7 @@ gnc_split_register_get_rate_cell (SplitRegister *reg, const char *cell_name)
|
||||
return gnc_numeric_create (100,100);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gboolean
|
||||
gnc_split_register_split_needs_amount (Split *split)
|
||||
{
|
||||
Transaction *txn = xaccSplitGetParent (split);
|
||||
@ -387,7 +387,7 @@ gnc_split_register_save_debcred_cell (BasicCell * bcell,
|
||||
SRSaveData *sd = save_data;
|
||||
SplitRegister *reg = user_data;
|
||||
Account *acc;
|
||||
gnc_numeric new_amount, convrate, oldconvrate, value;
|
||||
gnc_numeric new_amount, convrate, amtconv, value;
|
||||
|
||||
g_return_if_fail (gnc_basic_cell_has_name (bcell, DEBT_CELL) ||
|
||||
gnc_basic_cell_has_name (bcell, CRED_CELL));
|
||||
@ -405,43 +405,53 @@ gnc_split_register_save_debcred_cell (BasicCell * bcell,
|
||||
* 'value' by dividing by the convrate in order to set the value.
|
||||
*/
|
||||
|
||||
/* First, compute the "old" conversion rate -- use the RATE_CELL if it
|
||||
* exists -- if not, then compute from the old amount/value
|
||||
/* First, compute the conversion rate to convert the value to the
|
||||
* amount. Use the RATE_CELL (if it exists) -- if not, then assume
|
||||
* it is 1.
|
||||
*/
|
||||
oldconvrate = gnc_split_register_get_rate_cell (reg, RATE_CELL);
|
||||
if (gnc_numeric_zero_p (oldconvrate)) {
|
||||
convrate = xaccSplitGetAmount (sd->split);
|
||||
value = xaccSplitGetValue (sd->split);
|
||||
convrate = gnc_split_register_get_rate_cell (reg, RATE_CELL);
|
||||
if (gnc_numeric_zero_p (convrate))
|
||||
convrate = gnc_numeric_create (100,100);
|
||||
|
||||
if (! gnc_numeric_zero_p (value))
|
||||
oldconvrate = gnc_numeric_div (convrate, value, GNC_DENOM_AUTO, GNC_DENOM_REDUCE);
|
||||
else
|
||||
oldconvrate = gnc_numeric_create (100,100);
|
||||
}
|
||||
|
||||
/* Now compute/set the split value */
|
||||
/* Now compute/set the split value. Amount is in the register
|
||||
* currency but we need to convert to the txn currency.
|
||||
*/
|
||||
acc = gnc_split_register_get_default_account (reg);
|
||||
if (gnc_split_register_needs_conv_rate (sd->trans, acc)) {
|
||||
gnc_commodity *curr;
|
||||
gnc_commodity *curr, *reg_com, *xfer_com;
|
||||
Account *xfer_acc;
|
||||
|
||||
xfer_acc = xaccSplitGetAccount (sd->split);
|
||||
xfer_com = xaccAccountGetCommodity (xfer_acc);
|
||||
reg_com = xaccAccountGetCommodity (acc);
|
||||
|
||||
/* If we are in an expanded register and the xfer_acc->comm !=
|
||||
* reg_acc->comm then we need to compute the convrate here.
|
||||
* Otherwise, we _can_ use the rate_cell!
|
||||
*/
|
||||
if (sd->reg_expanded && ! gnc_commodity_equal (reg_com, xfer_com))
|
||||
amtconv = gnc_split_register_get_conv_rate (sd->trans, acc);
|
||||
else
|
||||
amtconv = convrate;
|
||||
|
||||
/* convert the amount to the Value ... */
|
||||
convrate = gnc_split_register_get_conv_rate (sd->trans, acc);
|
||||
curr = xaccTransGetCurrency (sd->trans);
|
||||
value = gnc_numeric_div (new_amount, convrate,
|
||||
value = gnc_numeric_div (new_amount, amtconv,
|
||||
gnc_commodity_get_fraction (curr),
|
||||
GNC_RND_ROUND);
|
||||
xaccSplitSetValue (sd->split, value);
|
||||
} else
|
||||
xaccSplitSetValue (sd->split, new_amount);
|
||||
|
||||
/* Now re-compute the Amount -- We may need to convert from the Value back
|
||||
* to the amount here using the conversion in the rate-cell.
|
||||
/* Now re-compute the Amount from the Value. We may need to convert
|
||||
* from the Value back to the amount here using the convrate from
|
||||
* earlier.
|
||||
*/
|
||||
value = xaccSplitGetValue (sd->split);
|
||||
|
||||
if (gnc_split_register_split_needs_amount (sd->split)) {
|
||||
acc = xaccSplitGetAccount (sd->split);
|
||||
new_amount = gnc_numeric_mul (value, oldconvrate,
|
||||
new_amount = gnc_numeric_mul (value, convrate,
|
||||
xaccAccountGetCommoditySCU (acc),
|
||||
GNC_RND_ROUND);
|
||||
xaccSplitSetAmount (sd->split, new_amount);
|
||||
@ -451,6 +461,17 @@ gnc_split_register_save_debcred_cell (BasicCell * bcell,
|
||||
sd->do_scrub = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gnc_split_register_save_rate_cell (BasicCell * bcell,
|
||||
gpointer save_data,
|
||||
gpointer user_data)
|
||||
{
|
||||
SRSaveData *sd = save_data;
|
||||
|
||||
/* if the exchrate cell changed, then make sure to force a scrub */
|
||||
sd->do_scrub = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gnc_split_register_save_cells (gpointer save_data,
|
||||
gpointer user_data)
|
||||
@ -458,6 +479,7 @@ gnc_split_register_save_cells (gpointer save_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);
|
||||
@ -466,6 +488,7 @@ gnc_split_register_save_cells (gpointer save_data,
|
||||
return;
|
||||
|
||||
other_split = xaccSplitGetOtherSplit (sd->split);
|
||||
txn_cur = xaccTransGetCurrency (sd->trans);
|
||||
|
||||
xaccSplitScrub (sd->split);
|
||||
|
||||
@ -473,23 +496,47 @@ gnc_split_register_save_cells (gpointer save_data,
|
||||
|
||||
if (other_split && !sd->reg_expanded)
|
||||
{
|
||||
gnc_numeric value = xaccSplitGetValue (sd->split);
|
||||
gnc_numeric amount, value = xaccSplitGetValue (sd->split);
|
||||
Account *acc;
|
||||
gboolean split_needs_amount;
|
||||
|
||||
split_needs_amount = gnc_split_register_split_needs_amount (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_RND_ROUND);
|
||||
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 (other_split))
|
||||
{
|
||||
Account *acc = xaccSplitGetAccount (other_split);
|
||||
gnc_numeric amount;
|
||||
acc = xaccSplitGetAccount (other_split);
|
||||
|
||||
if (gnc_numeric_zero_p (rate))
|
||||
/* 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 = gnc_split_register_get_conv_rate (xaccSplitGetParent (other_split),
|
||||
acc);
|
||||
|
||||
amount = gnc_numeric_mul (value, rate, xaccAccountGetCommoditySCU (acc),
|
||||
GNC_RND_ROUND);
|
||||
xaccSplitSetAmount (other_split, amount);
|
||||
|
||||
}
|
||||
|
||||
xaccSplitSetValue (other_split, value);
|
||||
|
||||
xaccSplitScrub (other_split);
|
||||
@ -497,13 +544,23 @@ gnc_split_register_save_cells (gpointer save_data,
|
||||
else if (gnc_split_register_split_needs_amount (sd->split) &&
|
||||
! gnc_numeric_zero_p (rate))
|
||||
{
|
||||
Account *acc = xaccSplitGetAccount (sd->split);
|
||||
gnc_numeric value, amount;
|
||||
/* 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_numeric value, amount;
|
||||
|
||||
value = xaccSplitGetValue (sd->split);
|
||||
amount = gnc_numeric_mul (value, rate, xaccAccountGetCommoditySCU (acc),
|
||||
GNC_RND_ROUND);
|
||||
xaccSplitSetAmount (sd->split, amount);
|
||||
amount = xaccSplitGetAmount (sd->split);
|
||||
value = gnc_numeric_div (amount, rate, gnc_commodity_get_fraction (txn_cur),
|
||||
GNC_RND_ROUND);
|
||||
xaccSplitSetValue (sd->split, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -701,6 +758,10 @@ gnc_split_register_model_add_save_handlers (TableModel *model)
|
||||
gnc_split_register_save_debcred_cell,
|
||||
CRED_CELL);
|
||||
|
||||
gnc_table_model_set_save_handler (model,
|
||||
gnc_split_register_save_rate_cell,
|
||||
RATE_CELL);
|
||||
|
||||
gnc_table_model_set_post_save_handler (model, gnc_split_register_save_cells);
|
||||
}
|
||||
|
||||
|
@ -163,6 +163,7 @@ gnc_numeric gnc_split_register_debcred_cell_value (SplitRegister *reg);
|
||||
/* Determine if we need to perform any conversion on the splits in this
|
||||
* transaction, and if so, what conversion we need
|
||||
*/
|
||||
gboolean gnc_split_register_split_needs_amount (Split *split);
|
||||
gboolean gnc_split_register_needs_conv_rate (Transaction *txn, Account *acc);
|
||||
gnc_numeric gnc_split_register_get_conv_rate (Transaction *txn, Account *acc);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user