gnucash maint: Multiple changes pushed
John Ralls
jralls at code.gnucash.org
Tue Sep 15 15:07:10 EDT 2015
Updated via https://github.com/Gnucash/gnucash/commit/bc9285bb (commit)
via https://github.com/Gnucash/gnucash/commit/05bb4bd9 (commit)
via https://github.com/Gnucash/gnucash/commit/74d11b27 (commit)
via https://github.com/Gnucash/gnucash/commit/cfa5aa1c (commit)
via https://github.com/Gnucash/gnucash/commit/4259255a (commit)
via https://github.com/Gnucash/gnucash/commit/6b6920fd (commit)
via https://github.com/Gnucash/gnucash/commit/585cc488 (commit)
via https://github.com/Gnucash/gnucash/commit/d9a0f311 (commit)
via https://github.com/Gnucash/gnucash/commit/7db7e0cf (commit)
via https://github.com/Gnucash/gnucash/commit/7d8b51e8 (commit)
via https://github.com/Gnucash/gnucash/commit/d52a0b60 (commit)
via https://github.com/Gnucash/gnucash/commit/d4968d3b (commit)
via https://github.com/Gnucash/gnucash/commit/157c7e30 (commit)
via https://github.com/Gnucash/gnucash/commit/890cfe21 (commit)
via https://github.com/Gnucash/gnucash/commit/96471379 (commit)
via https://github.com/Gnucash/gnucash/commit/d7fb92d0 (commit)
via https://github.com/Gnucash/gnucash/commit/93bb5c0f (commit)
via https://github.com/Gnucash/gnucash/commit/ffe96b30 (commit)
via https://github.com/Gnucash/gnucash/commit/bfbb5087 (commit)
via https://github.com/Gnucash/gnucash/commit/86320a4d (commit)
via https://github.com/Gnucash/gnucash/commit/c0683976 (commit)
via https://github.com/Gnucash/gnucash/commit/e12c89b5 (commit)
via https://github.com/Gnucash/gnucash/commit/6b520778 (commit)
via https://github.com/Gnucash/gnucash/commit/c7c97be6 (commit)
via https://github.com/Gnucash/gnucash/commit/73233a5e (commit)
via https://github.com/Gnucash/gnucash/commit/3a51c0d5 (commit)
via https://github.com/Gnucash/gnucash/commit/06f70bad (commit)
via https://github.com/Gnucash/gnucash/commit/ea48ed88 (commit)
via https://github.com/Gnucash/gnucash/commit/0b033281 (commit)
via https://github.com/Gnucash/gnucash/commit/c6a67f4e (commit)
via https://github.com/Gnucash/gnucash/commit/407d61cb (commit)
via https://github.com/Gnucash/gnucash/commit/47f91c02 (commit)
via https://github.com/Gnucash/gnucash/commit/e1b4e45d (commit)
via https://github.com/Gnucash/gnucash/commit/9a611a2a (commit)
from https://github.com/Gnucash/gnucash/commit/e921de8b (commit)
commit bc9285bbfbb80bb8a38b19fe70117b31874b151f
Merge: e921de8 05bb4bd
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 15 12:06:46 2015 -0700
Merge branch 'single-price' into maint
commit 05bb4bd955f87ab2934f5dc80611c8757c395cfe
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 15 12:03:39 2015 -0700
Prevent F::Q from updating PRICE_SOURCE_EDIT_DLG prices.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 6cb0899..4a3ed05 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1325,7 +1325,7 @@ gnc_xfer_dialog_set_fetch_sensitive (GtkWidget *fetch)
if (gnc_quote_source_fq_installed ())
{
gtk_widget_set_sensitive (fetch, TRUE);
- gtk_widget_set_tooltip_text (fetch, _("Retrieve the current online quote"));
+ gtk_widget_set_tooltip_text (fetch, _("Retrieve the current online quote. This will fail if there is a manually-created price for today."));
return;
}
gtk_widget_set_sensitive (fetch, FALSE);
diff --git a/src/scm/price-quotes.scm b/src/scm/price-quotes.scm
index c078822..68c67bf 100644
--- a/src/scm/price-quotes.scm
+++ b/src/scm/price-quotes.scm
@@ -426,14 +426,16 @@
(if (not (null? saved-price))
(set! price (gnc-numeric-invert(price))))))
(if (not (null? saved-price))
- (begin
- (gnc-price-begin-edit saved-price)
- (gnc-price-set-time saved-price gnc-time)
+ (if (> (gnc-price-get-source saved-price) PRICE-SOURCE-FQ)
+ (begin
+ (gnc-price-begin-edit saved-price)
+ (gnc-price-set-time saved-price gnc-time)
(gnc-price-set-source saved-price PRICE-SOURCE-FQ)
- (gnc-price-set-typestr saved-price price-type)
- (gnc-price-set-value saved-price price)
- (gnc-price-commit-edit saved-price)
- #f)
+ (gnc-price-set-typestr saved-price price-type)
+ (gnc-price-set-value saved-price price)
+ (gnc-price-commit-edit saved-price)
+ #f)
+ #f)
(let ((gnc-price (gnc-price-create book)))
(if (not gnc-price)
(string-append
commit 74d11b273616909de2c58aad0421d99e04fe9143
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Sep 12 12:09:46 2015 -0700
Remove unnecessary and harmful price rounding.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 24fbb84..6cb0899 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -332,10 +332,7 @@ gnc_xfer_dialog_update_price (XferDialog *xferData)
/* grab the price from the pricedb */
price_value = gnc_price_get_value (pr.price);
if (pr.reverse)
- {
price_value = gnc_numeric_invert (price_value);
- price_value = round_price(pr.from, pr.to, price_value);
- }
gnc_price_unref(pr.price);
/* and set the price entry */
@@ -1088,8 +1085,6 @@ gnc_xfer_to_amount_update_cb(GtkWidget *widget, GdkEventFocus *event,
gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->to_amount_edit));
price_value = gnc_xfer_dialog_compute_price_value(xferData);
- price_value = round_price(xferData->from_commodity, xferData->to_commodity,
- price_value);
gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit),
price_value);
xferData->price_source = PRICE_SOURCE_XFER_DLG_VAL;
@@ -1581,7 +1576,6 @@ swap_commodities(gnc_commodity **from, gnc_commodity **to, gnc_numeric value)
*to = *from;
*from = tmp;
value = gnc_numeric_invert(value);
- value = round_price(*from, *to, value);
return value;
}
@@ -1861,8 +1855,7 @@ gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData)
{
gnc_numeric price_value = gnc_price_get_value(pr.price);
if (pr.reverse)
- price_value = round_price(pr.from, pr.to,
- gnc_numeric_invert(price_value));
+ price_value = gnc_numeric_invert(price_value);
_gnc_xfer_dialog_set_price_edit(xferData, price_value);
gnc_price_unref (pr.price);
}
@@ -2479,10 +2472,7 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
gnc_xfer_dialog_select_to_currency(xfer, txn_cur);
gnc_xfer_dialog_select_from_currency(xfer, xfer_com);
if (!gnc_numeric_zero_p(*exch_rate))
- {
dialog_rate = gnc_numeric_invert(*exch_rate);
- dialog_rate = round_price(xfer_com, txn_cur, *exch_rate);
- }
amount = gnc_numeric_neg(amount);
}
else
commit cfa5aa1cb24e59611ee46f1b36c27afdab8b8bcd
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Sep 12 12:04:34 2015 -0700
Remove the preference for storing prices relative to the base currency.
It interferes with the preference for storing the price in the direction
in which the price is >1 for preserving sigfigs.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 4580217..24fbb84 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1602,12 +1602,6 @@ create_price(XferDialog *xferData, Timespec ts)
return;
value = gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->price_edit));
- /* Try to be consistent about how quotes are installed. */
- if (from == gnc_default_currency() ||
- ((to != gnc_default_currency()) &&
- (strcmp (gnc_commodity_get_mnemonic(from),
- gnc_commodity_get_mnemonic(to)) < 0)))
- swap_amount (&from, &to, &value, &from_amt, &to_amt);
/* Normally we want to store currency rates such that the rate > 1 and commodity
* prices in terms of a currency regardless of value. However, if we already
commit 4259255af1287794a7c5ea9c327ed1e56f381507
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Sep 12 12:02:28 2015 -0700
Export the price-source enums to Guile and use them in price-quotes.scm.
diff --git a/src/engine/engine.i b/src/engine/engine.i
index 99a1039..6f51011 100644
--- a/src/engine/engine.i
+++ b/src/engine/engine.i
@@ -334,7 +334,7 @@ KvpValue * kvp_frame_get_slot_path_gslist (KvpFrame *frame, GSList *key_path);
SET_ENUM("TRANS-DATE-POSTED");
SET_ENUM("TRANS-DESCRIPTION");
SET_ENUM("TRANS-NUM");
-
+
SET_ENUM("KVP-OPTION-PATH");
SET_ENUM("OPTION-SECTION-ACCOUNTS");
@@ -355,6 +355,15 @@ KvpValue * kvp_frame_get_slot_path_gslist (KvpFrame *frame, GSList *key_path);
SET_ENUM("GNC-HOW-RND-ROUND");
SET_ENUM("GNC-HOW-RND-NEVER");
+ SET_ENUM("PRICE-SOURCE-EDIT-DLG");
+ SET_ENUM("PRICE-SOURCE-FQ");
+ SET_ENUM("PRICE-SOURCE-USER-PRICE");
+ SET_ENUM("PRICE-SOURCE-XFER-DLG-VAL");
+ SET_ENUM("PRICE-SOURCE-SPLIT-REG");
+ SET_ENUM("PRICE-SOURCE-STOCK-SPLIT");
+ SET_ENUM("PRICE-SOURCE-INVOICE");
+ SET_ENUM("PRICE-SOURCE-INVALID");
+
#undef SET_ENUM
}
diff --git a/src/scm/price-quotes.scm b/src/scm/price-quotes.scm
index e72fdae..c078822 100644
--- a/src/scm/price-quotes.scm
+++ b/src/scm/price-quotes.scm
@@ -429,7 +429,7 @@
(begin
(gnc-price-begin-edit saved-price)
(gnc-price-set-time saved-price gnc-time)
- (gnc-price-set-source-string saved-price "Finance::Quote")
+ (gnc-price-set-source saved-price PRICE-SOURCE-FQ)
(gnc-price-set-typestr saved-price price-type)
(gnc-price-set-value saved-price price)
(gnc-price-commit-edit saved-price)
@@ -443,7 +443,7 @@
(gnc-price-set-commodity gnc-price commodity)
(gnc-price-set-currency gnc-price currency)
(gnc-price-set-time gnc-price gnc-time)
- (gnc-price-set-source-string gnc-price "Finance::Quote")
+ (gnc-price-set-source gnc-price PRICE-SOURCE-FQ)
(gnc-price-set-typestr gnc-price price-type)
(gnc-price-set-value gnc-price price)
(gnc-price-commit-edit gnc-price)
commit 6b6920fd04621845d6c2042ed4ef18bbda3d2813
Author: John Ralls <jralls at ceridwen.us>
Date: Wed Sep 9 15:25:06 2015 -0700
Remove static function swap_amount(), not used.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index a42f68b..4580217 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1573,20 +1573,6 @@ create_transaction(XferDialog *xferData, Timespec *ts,
xferData->transaction_cb(trans, xferData->transaction_user_data);
}
-static void
-swap_amount (gnc_commodity **from, gnc_commodity **to, gnc_numeric *value,
- gnc_numeric *from_amt, gnc_numeric *to_amt)
-{
- gnc_commodity *tmp = *from;
- gnc_numeric *tmp_amt = from_amt;
- *from = *to;
- *to = tmp;
- from_amt = to_amt;
- to_amt = tmp_amt;
- *value = gnc_numeric_invert (*value);
- *value = round_price(*from, *to, *value);
-}
-
static gnc_numeric
swap_commodities(gnc_commodity **from, gnc_commodity **to, gnc_numeric value)
{
commit 585cc4883ffae9af2824bad9651aac808f48e83f
Author: John Ralls <jralls at ceridwen.us>
Date: Wed Sep 9 15:06:56 2015 -0700
Implement user-entered-price preference.
Add user:price as a source and prefer values with lower PriceSource enum
values over higher ones: In other words a price with a lower PriceSource
value (e.g. user:price-editor) will overwrite one with a higher value (e.g.
user:split-register) and not the other way around.
diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c
index 8cb841b..bdc8e41 100644
--- a/src/engine/gnc-pricedb.c
+++ b/src/engine/gnc-pricedb.c
@@ -71,8 +71,12 @@ gnc_price_init(GNCPrice* price)
*/
static const char* source_names[] =
{
- "user:price-editor", //sync with price_to_gui in dialog-price-editor.c
- "Finance::Quote", //sync with
+ /* sync with price_to_gui in dialog-price-editor.c */
+ "user:price-editor",
+ /* sync with commidity-tz-quote->price in price-quotes.scm */
+ "Finance::Quote",
+ "user:price",
+ /* String retained for backwards compatibility. */
"user:xfer-dialog",
"user:split-register",
"user:stock-split",
@@ -1004,7 +1008,7 @@ insert_or_replace_price(GNCPriceDB *db, GNCPrice *p)
p->currency, p->tmspec);
if (old_price == NULL)
return TRUE;
- if (p->source != PRICE_SOURCE_FQ)
+ if (p->source < old_price->source)
return TRUE;
return FALSE;
diff --git a/src/engine/gnc-pricedb.h b/src/engine/gnc-pricedb.h
index 00a4126..e3966b3 100644
--- a/src/engine/gnc-pricedb.h
+++ b/src/engine/gnc-pricedb.h
@@ -165,7 +165,8 @@ typedef enum
{
PRICE_SOURCE_EDIT_DLG, // "user:price-editor"
PRICE_SOURCE_FQ, // "Finance::Quote"
- PRICE_SOURCE_XFER_DLG, // "user:xfer-dialog"
+ PRICE_SOURCE_USER_PRICE, // "user:price"
+ PRICE_SOURCE_XFER_DLG_VAL, // "user:xfer-dialog"
PRICE_SOURCE_SPLIT_REG, // "user:split-register"
PRICE_SOURCE_STOCK_SPLIT, // "user:stock-split"
PRICE_SOURCE_INVOICE, // "user:invoice-post"
@@ -174,7 +175,7 @@ typedef enum
#define PRICE_TYPE_LAST "last"
#define PRICE_TYPE_UNK "unknown"
-
+#define PRICE_TYPE_TRN "transaction"
/* ------------------ */
/** @name Constructors
@{ */
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index b7931ad..a42f68b 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -121,6 +121,8 @@ struct _xferDialog
* creating a transaction)
*/
gnc_numeric *exch_rate;
+ PriceSource price_source;
+ const char *price_type;
/* Callback function to notify of the newly created Transaction */
gnc_xfer_dialog_cb transaction_cb;
@@ -1058,6 +1060,9 @@ gnc_xfer_price_update_cb(GtkWidget *widget, GdkEventFocus *event,
XferDialog *xferData = data;
gnc_xfer_update_to_amount (xferData);
+ xferData->price_source = PRICE_SOURCE_USER_PRICE;
+ xferData->price_type = PRICE_TYPE_TRN;
+
return FALSE;
}
@@ -1087,6 +1092,8 @@ gnc_xfer_to_amount_update_cb(GtkWidget *widget, GdkEventFocus *event,
price_value);
gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit),
price_value);
+ xferData->price_source = PRICE_SOURCE_XFER_DLG_VAL;
+ xferData->price_type = PRICE_TYPE_TRN;
gnc_xfer_dialog_update_conv_info(xferData);
return FALSE;
@@ -1635,9 +1642,9 @@ create_price(XferDialog *xferData, Timespec ts)
gnc_price_unref (pr.price);
return;
}
- if (gnc_price_get_source(pr.price) == PRICE_SOURCE_FQ)
+ if (gnc_price_get_source(pr.price) < xferData->price_source)
{
- PINFO("Existing price is from Finance::Quote, so won't supersede.");
+ PINFO("Existing price is preferred, so won't supersede.");
gnc_price_unref (pr.price);
return;
}
@@ -1650,7 +1657,8 @@ create_price(XferDialog *xferData, Timespec ts)
value = round_price(pr.from, pr.to, value);
gnc_price_begin_edit (pr.price);
gnc_price_set_time (pr.price, ts);
- gnc_price_set_source (pr.price, PRICE_SOURCE_XFER_DLG);
+ gnc_price_set_source (pr.price, xferData->price_source);
+ gnc_price_set_typestr(pr.price, xferData->price_type);
gnc_price_set_value (pr.price, value);
gnc_price_commit_edit (pr.price);
PINFO("Modified price: 1 %s = %f %s",
@@ -1683,7 +1691,8 @@ create_price(XferDialog *xferData, Timespec ts)
gnc_price_set_commodity (price, from);
gnc_price_set_currency (price, to);
gnc_price_set_time (price, ts);
- gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
+ gnc_price_set_source (price, xferData->price_source);
+ gnc_price_set_typestr (price, xferData->price_type);
gnc_price_set_value (price, value);
gnc_pricedb_add_price (xferData->pricedb, price);
gnc_price_commit_edit (price);
diff --git a/src/register/ledger-core/split-register.c b/src/register/ledger-core/split-register.c
index 1332bf1..3e4eb74 100644
--- a/src/register/ledger-core/split-register.c
+++ b/src/register/ledger-core/split-register.c
@@ -2044,7 +2044,8 @@ recalculate_value (Split *split, SplitRegister *reg,
}
static void
-record_price (SplitRegister *reg, Account *account, gnc_numeric value)
+record_price (SplitRegister *reg, Account *account, gnc_numeric value,
+ PriceSource source)
{
Transaction *trans = gnc_split_register_get_current_trans (reg);
QofBook *book = qof_instance_get_book (QOF_INSTANCE (account));
@@ -2084,8 +2085,9 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
gnc_price_unref (price);
return;
}
- if (gnc_price_get_source(price) == PRICE_SOURCE_FQ)
+ if (gnc_price_get_source(price) < PRICE_SOURCE_XFER_DLG_VAL)
{
+ /* Existing price is preferred over this one. */
gnc_price_unref(price);
return;
}
@@ -2098,7 +2100,8 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
GNC_HOW_RND_ROUND_HALF_UP);
gnc_price_begin_edit (price);
gnc_price_set_time (price, ts);
- gnc_price_set_source (price, PRICE_SOURCE_SPLIT_REG);
+ gnc_price_set_source (price, source);
+ gnc_price_set_typestr (price, PRICE_TYPE_TRN);
gnc_price_set_value (price, value);
gnc_price_commit_edit (price);
gnc_price_unref (price);
@@ -2112,7 +2115,8 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
gnc_price_set_commodity (price, comm);
gnc_price_set_currency (price, curr);
gnc_price_set_time (price, ts);
- gnc_price_set_source (price, PRICE_SOURCE_SPLIT_REG);
+ gnc_price_set_source (price, source);
+ gnc_price_set_typestr (price, PRICE_TYPE_TRN);
gnc_price_set_value (price, value);
gnc_pricedb_add_price (pricedb, price);
gnc_price_commit_edit (price);
@@ -2135,6 +2139,7 @@ gnc_split_register_auto_calc (SplitRegister *reg, Split *split)
Account *account;
int denom;
int choice;
+ PriceSource source = PRICE_SOURCE_USER_PRICE;
if (STOCK_REGISTER != reg->type &&
CURRENCY_REGISTER != reg->type &&
@@ -2283,6 +2288,7 @@ gnc_split_register_auto_calc (SplitRegister *reg, Split *split)
{
recalculate_price (split, reg, value, amount);
price_changed = TRUE;
+ source = PRICE_SOURCE_SPLIT_REG;
}
if (recalc_value)
recalculate_value (split, reg, price, amount, shares_changed);
@@ -2293,7 +2299,7 @@ gnc_split_register_auto_calc (SplitRegister *reg, Split *split)
PRIC_CELL);
price = gnc_price_cell_get_value (cell);
if (gnc_numeric_positive_p(price))
- record_price (reg, account, price);
+ record_price (reg, account, price, source);
}
return TRUE;
}
commit d9a0f311a4adac7968ed0a09646e1d1216bb8e7d
Author: John Ralls <jralls at ceridwen.us>
Date: Wed Sep 9 11:22:52 2015 -0700
Fold separate call of gnc_pricedb_lookup_latest() into lookup_price.
Requires a 3-state enum instead of a boolean for the second arg to lookup_price.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 2bb173f..b7931ad 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -216,6 +216,13 @@ round_price(gnc_commodity *from, gnc_commodity *to, gnc_numeric value)
return value;
}
+typedef enum
+{
+ SAME_DAY,
+ NEAREST,
+ LATEST
+} PriceDate;
+
typedef struct
{
GNCPrice *price;
@@ -240,7 +247,7 @@ price_request_from_xferData(PriceReq *pr, XferDialog *xd)
}
static gboolean
-lookup_price(PriceReq *pr, gboolean day_only)
+lookup_price(PriceReq *pr, PriceDate pd)
{
GNCPrice *prc = NULL;
g_return_val_if_fail (pr != NULL, FALSE);
@@ -249,26 +256,37 @@ lookup_price(PriceReq *pr, gboolean day_only)
g_return_val_if_fail (pr->to != NULL, FALSE);
pr->reverse = FALSE;
- if (day_only)
- {
- prc = gnc_pricedb_lookup_day (pr->pricedb, pr->from, pr->to, pr->ts);
- if (!prc)
- {
- prc = gnc_pricedb_lookup_day (pr->pricedb, pr->to,
- pr->from, pr->ts);
- pr->reverse = TRUE;
- }
- }
- else
+ switch (pd)
{
- prc = gnc_pricedb_lookup_nearest_in_time (pr->pricedb, pr->from,
- pr->to, pr->ts);
- if (!prc)
- {
- prc = gnc_pricedb_lookup_nearest_in_time (pr->pricedb, pr->to,
- pr->from, pr->ts);
- pr->reverse = TRUE;
- }
+ default:
+ case SAME_DAY:
+ prc = gnc_pricedb_lookup_day (pr->pricedb, pr->from,
+ pr->to, pr->ts);
+ if (!prc)
+ {
+ prc = gnc_pricedb_lookup_day (pr->pricedb, pr->to,
+ pr->from, pr->ts);
+ pr->reverse = TRUE;
+ }
+ break;
+ case NEAREST:
+ prc = gnc_pricedb_lookup_nearest_in_time (pr->pricedb, pr->from,
+ pr->to, pr->ts);
+ if (!prc)
+ {
+ prc = gnc_pricedb_lookup_nearest_in_time (pr->pricedb, pr->to,
+ pr->from, pr->ts);
+ pr->reverse = TRUE;
+ }
+ break;
+ case LATEST:
+ prc = gnc_pricedb_lookup_latest (pr->pricedb, pr->from, pr->to);
+ if (!prc)
+ {
+ prc = gnc_pricedb_lookup_latest (pr->pricedb, pr->to, pr->from);
+ pr->reverse = TRUE;
+ }
+ break;
}
if (pr->reverse)
{
@@ -305,8 +323,8 @@ gnc_xfer_dialog_update_price (XferDialog *xferData)
if (!xferData->pricedb) return;
price_request_from_xferData(&pr, xferData);
- if (!lookup_price(&pr, TRUE))
- if (!lookup_price(&pr, FALSE))
+ if (!lookup_price(&pr, SAME_DAY))
+ if (!lookup_price(&pr, NEAREST))
return;
/* grab the price from the pricedb */
@@ -1605,7 +1623,7 @@ create_price(XferDialog *xferData, Timespec ts)
* shifts to be < 1. */
price_request_from_xferData(&pr, xferData);
- if (lookup_price(&pr, TRUE))
+ if (lookup_price(&pr, SAME_DAY))
{
price_value = gnc_price_get_value(pr.price);
if (gnc_numeric_equal(pr.reverse ? gnc_numeric_invert(value) : value,
@@ -1810,14 +1828,11 @@ gnc_xfer_dialog_close_cb(GtkDialog *dialog, gpointer data)
void
gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData)
{
- gnc_numeric rate;
GNCPrice *prc;
- gnc_commodity *from = xferData->from_commodity;
- gnc_commodity *to = xferData->to_commodity;
+ PriceReq pr;
SCM quotes_func;
SCM book_scm;
SCM scm_window;
- gboolean have_price = FALSE;
g_return_if_fail (xferData);
@@ -1852,29 +1867,15 @@ gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData)
gnc_unset_busy_cursor (NULL);
/*the results should be in the price db now, but don't crash if not. */
-
- prc = gnc_pricedb_lookup_latest(xferData->pricedb, from, to);
- if (prc)
- {
- rate = gnc_price_get_value (prc);
- _gnc_xfer_dialog_set_price_edit(xferData, rate);
- gnc_price_unref (prc);
- have_price = TRUE;
- }
-
- /* Lets try reversing the commodities */
- if(!have_price)
+ price_request_from_xferData(&pr, xferData);
+ if (lookup_price(&pr, LATEST))
{
- prc = gnc_pricedb_lookup_latest (xferData->pricedb, to, from);
- if (prc)
- {
-/* FIXME: We probably want to swap the result price's to and from, not invert the price. */
- rate = gnc_numeric_invert(gnc_price_get_value (prc));
- rate = round_price(from, to, rate);
- _gnc_xfer_dialog_set_price_edit(xferData, rate);
- gnc_price_unref (prc);
- have_price = TRUE;
- }
+ gnc_numeric price_value = gnc_price_get_value(pr.price);
+ if (pr.reverse)
+ price_value = round_price(pr.from, pr.to,
+ gnc_numeric_invert(price_value));
+ _gnc_xfer_dialog_set_price_edit(xferData, price_value);
+ gnc_price_unref (pr.price);
}
LEAVE("quote retrieved");
commit 7db7e0cf7ab5b18de02df64992902f5d73bab7a3
Author: John Ralls <jralls at ceridwen.us>
Date: Wed Sep 9 11:02:41 2015 -0700
Recognize and handle reversed price quotes from gnc-fq-helper.
Gnc-fq-helper will flip currency price quotes if the one requested is < 1
or not available, which might mean that it's not representable in 4 digits
to the right of the decimal.
diff --git a/src/scm/price-quotes.scm b/src/scm/price-quotes.scm
index fc81139..e72fdae 100644
--- a/src/scm/price-quotes.scm
+++ b/src/scm/price-quotes.scm
@@ -375,7 +375,15 @@
(saved-price #f)
(commodity-str (gnc-commodity-get-printname commodity))
)
-
+ (if (equal? (gnc-commodity-get-printname currency) commodity-str)
+ (let* ((symbol (assq-ref quote-data 'symbol))
+ (other-curr
+ (and commodity-table
+ (string? symbol)
+ (gnc-commodity-table-lookup commodity-table "ISO4217"
+ (string-upcase symbol)))))
+ (set! commodity other-curr))
+ )
(or-map (lambda (price-sym)
(let ((p (assq-ref quote-data price-sym)))
(if p
commit 7d8b51e8db76608bd6a1b6b8de4fc92a8804b092
Author: John Ralls <jralls at ceridwen.us>
Date: Thu Sep 3 16:22:14 2015 -0700
Use an enum for internal representation of Price Sources.
Strings are still used for storage and display.
Purpose is to make multiple comparisons and conditional setting more
convenient.
diff --git a/src/backend/sql/gnc-price-sql.c b/src/backend/sql/gnc-price-sql.c
index 8729c91..92a5176 100644
--- a/src/backend/sql/gnc-price-sql.c
+++ b/src/backend/sql/gnc-price-sql.c
@@ -203,7 +203,7 @@ write_price( GNCPrice* p, gpointer data )
g_return_val_if_fail( p != NULL, FALSE );
g_return_val_if_fail( data != NULL, FALSE );
- if ( s->is_ok && strcmp(gnc_price_get_source(p), PRICE_SOURCE_INVOICE) != 0)
+ if ( s->is_ok && gnc_price_get_source(p) == PRICE_SOURCE_INVOICE)
{
s->is_ok = save_price( s->be, QOF_INSTANCE(p) );
}
diff --git a/src/backend/xml/gnc-pricedb-xml-v2.c b/src/backend/xml/gnc-pricedb-xml-v2.c
index fad3ff4..710fa01 100644
--- a/src/backend/xml/gnc-pricedb-xml-v2.c
+++ b/src/backend/xml/gnc-pricedb-xml-v2.c
@@ -120,7 +120,7 @@ price_parse_xml_sub_node(GNCPrice *p, xmlNodePtr sub_node, QofBook *book)
{
char *text = dom_tree_to_text(sub_node);
if (!text) return FALSE;
- gnc_price_set_source(p, text);
+ gnc_price_set_source_string(p, text);
g_free(text);
}
else if (g_strcmp0("price:type", (char*)sub_node->name) == 0)
@@ -440,7 +440,7 @@ gnc_price_to_dom_tree(const xmlChar *tag, GNCPrice *price)
tmpnode = timespec_to_dom_tree("price:time", ×p);
if (!add_child_or_kill_parent(price_xml, tmpnode)) return NULL;
- sourcestr = gnc_price_get_source(price);
+ sourcestr = gnc_price_get_source_string(price);
if (sourcestr && (strlen(sourcestr) != 0))
{
tmpnode = text_to_dom_tree("price:source", sourcestr);
diff --git a/src/backend/xml/io-gncxml-v1.c b/src/backend/xml/io-gncxml-v1.c
index 099ccd6..2dff2d0 100644
--- a/src/backend/xml/io-gncxml-v1.c
+++ b/src/backend/xml/io-gncxml-v1.c
@@ -3112,7 +3112,7 @@ price_parse_xml_sub_node(GNCPrice *p, xmlNodePtr sub_node, QofBook *book)
{
char *text = dom_tree_to_text(sub_node);
if (!text) return FALSE;
- gnc_price_set_source(p, text);
+ gnc_price_set_source_string(p, text);
g_free(text);
}
else if (g_strcmp0("price:type", (char*)sub_node->name) == 0)
diff --git a/src/engine/gnc-pricedb-p.h b/src/engine/gnc-pricedb-p.h
index d93747b..8d867da 100644
--- a/src/engine/gnc-pricedb-p.h
+++ b/src/engine/gnc-pricedb-p.h
@@ -39,7 +39,7 @@ struct gnc_price_s
gnc_commodity *commodity;
gnc_commodity *currency;
Timespec tmspec;
- char *source;
+ PriceSource source;
char *type;
gnc_numeric value;
diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c
index 81febf1..8cb841b 100644
--- a/src/engine/gnc-pricedb.c
+++ b/src/engine/gnc-pricedb.c
@@ -58,9 +58,28 @@ gnc_price_init(GNCPrice* price)
price->refcount = 1;
price->value = gnc_numeric_zero();
price->type = NULL;
- price->source = NULL;
+ price->source = PRICE_SOURCE_INVALID;
}
+/* Array of char constants for converting price-source enums. Be sure to keep in
+ * sync with the enum values in gnc-pricedb.h The string user:price-editor is
+ * explicitly used by price_to_gui() in dialog-price-editor.c and the string
+ * Finance::Quote is explicitly used by fq-results->commod-tz-quote-triples in
+ * price-quotes.scm. Take care to keep them in sync if you make changes. Beware
+ * that the strings are used to store the enum values in the backends so any
+ * changes will affect backward data compatibility.
+ */
+static const char* source_names[] =
+{
+ "user:price-editor", //sync with price_to_gui in dialog-price-editor.c
+ "Finance::Quote", //sync with
+ "user:xfer-dialog",
+ "user:split-register",
+ "user:stock-split",
+ "user:invoice-post",
+ "invalid"
+};
+
static void
gnc_price_dispose(GObject *pricep)
{
@@ -90,7 +109,7 @@ gnc_price_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec
switch (prop_id)
{
case PROP_SOURCE:
- g_value_set_string(value, price->source);
+ g_value_set_string(value, gnc_price_get_source_string(price));
break;
case PROP_TYPE:
g_value_set_string(value, price->type);
@@ -126,7 +145,7 @@ gnc_price_set_property(GObject* object, guint prop_id, const GValue* value, GPar
switch (prop_id)
{
case PROP_SOURCE:
- gnc_price_set_source(price, g_value_get_string(value));
+ gnc_price_set_source_string(price, g_value_get_string(value));
break;
case PROP_TYPE:
gnc_price_set_typestr(price, g_value_get_string(value));
@@ -188,10 +207,10 @@ gnc_price_class_init(GNCPriceClass *klass)
PROP_SOURCE,
g_param_spec_string ("source",
"Price source",
- "The price source is a string describing the "
- "source of a price quote. It will be something "
- "like this: 'Finance::Quote', 'user:misc', "
- "'user:foo', etc.",
+ "The price source is PriceSource enum describing how"
+ " the price was created. This property works on the"
+ " string values in source_names for SQL database"
+ " compatibility.",
NULL,
G_PARAM_READWRITE));
@@ -252,7 +271,6 @@ gnc_price_destroy (GNCPrice *p)
qof_event_gen (&p->inst, QOF_EVENT_DESTROY, NULL);
if (p->type) CACHE_REMOVE(p->type);
- if (p->source) CACHE_REMOVE(p->source);
/* qof_instance_release (&p->inst); */
g_object_unref(p);
@@ -439,23 +457,30 @@ gnc_price_set_time(GNCPrice *p, Timespec t)
}
void
-gnc_price_set_source(GNCPrice *p, const char *s)
+gnc_price_set_source(GNCPrice *p, PriceSource s)
{
if (!p) return;
- if (g_strcmp0(p->source, s) != 0)
- {
- char *tmp;
-
- gnc_price_begin_edit (p);
- tmp = CACHE_INSERT((gpointer) s);
- if (p->source) CACHE_REMOVE(p->source);
- p->source = tmp;
- gnc_price_set_dirty(p);
- gnc_price_commit_edit (p);
- }
+ gnc_price_begin_edit (p);
+ p->source = s;
+ gnc_price_set_dirty(p);
+ gnc_price_commit_edit(p);
}
void
+gnc_price_set_source_string(GNCPrice *p, const char* str)
+{
+ if (!p) return;
+ for (PriceSource s = PRICE_SOURCE_EDIT_DLG;
+ s < PRICE_SOURCE_INVALID; ++s)
+ if (strcmp(source_names[s], str) == 0)
+ {
+ gnc_price_set_source(p, s);
+ return;
+ }
+
+
+}
+void
gnc_price_set_typestr(GNCPrice *p, const char* type)
{
if (!p) return;
@@ -518,13 +543,20 @@ gnc_price_get_time(const GNCPrice *p)
return p->tmspec;
}
-const char *
+PriceSource
gnc_price_get_source(const GNCPrice *p)
{
- if (!p) return NULL;
+ if (!p) return PRICE_SOURCE_INVALID;
return p->source;
}
+const char*
+gnc_price_get_source_string(const GNCPrice *p)
+{
+ if (!p) return NULL;
+ return source_names[p->source];
+}
+
const char *
gnc_price_get_typestr(const GNCPrice *p)
{
@@ -573,8 +605,7 @@ gnc_price_equal (const GNCPrice *p1, const GNCPrice *p2)
if (!timespec_equal (&ts1, &ts2))
return FALSE;
- if (g_strcmp0 (gnc_price_get_source (p1),
- gnc_price_get_source (p2)) != 0)
+ if (gnc_price_get_source (p1) != gnc_price_get_source (p2))
return FALSE;
if (g_strcmp0 (gnc_price_get_typestr (p1),
@@ -973,11 +1004,11 @@ insert_or_replace_price(GNCPriceDB *db, GNCPrice *p)
p->currency, p->tmspec);
if (old_price == NULL)
return TRUE;
- if (strcmp(p->source, "PRICE_SOURCE_FQ"))
+ if (p->source != PRICE_SOURCE_FQ)
return TRUE;
return FALSE;
-}
+}
/* ==================================================================== */
/* The add_price() function is a utility that only manages the
* dual hash table instertion */
@@ -1210,7 +1241,7 @@ static gboolean
check_one_price_date (GNCPrice *price, gpointer user_data)
{
remove_info *data = user_data;
- const gchar *source;
+ PriceSource source;
Timespec pt;
ENTER("price %p (%s), data %p", price,
@@ -1219,7 +1250,7 @@ check_one_price_date (GNCPrice *price, gpointer user_data)
if (!data->delete_user)
{
source = gnc_price_get_source (price);
- if (g_strcmp0(source, "Finance::Quote") != 0)
+ if (source != PRICE_SOURCE_FQ)
{
LEAVE("Not an automatic quote");
return TRUE;
@@ -2472,8 +2503,8 @@ gnc_price_print(GNCPrice *p, FILE *f, int indent)
str = str ? str : "(null)";
fprintf(f, "%s <cmdty:ref-id>%s</cmdty:ref-id>\n", istr, str);
fprintf(f, "%s </pdb:currency>\n", istr);
- str = gnc_price_get_source(p);
- str = str ? str : "(null)";
+ str = source_names[gnc_price_get_source(p)];
+ str = str ? str : "invalid";
fprintf(f, "%s %s\n", istr, str);
str = gnc_price_get_typestr(p);
str = str ? str : "(null)";
diff --git a/src/engine/gnc-pricedb.h b/src/engine/gnc-pricedb.h
index ae65748..00a4126 100644
--- a/src/engine/gnc-pricedb.h
+++ b/src/engine/gnc-pricedb.h
@@ -156,6 +156,25 @@ GType gnc_pricedb_get_type(void);
typedef struct gnc_price_lookup_s GNCPriceLookup;
typedef GList PriceList;
+/** Price source enum. Be sure to keep in sync with the source_name array in
+ * gnc-pricedb.c. These are in preference order, so for example a quote with
+ * PRICE_SOURCE_EDIT_DLG will overwrite one with PRICE_SOURCE_FQ but not the
+ * other way around.
+ */
+typedef enum
+{
+ PRICE_SOURCE_EDIT_DLG, // "user:price-editor"
+ PRICE_SOURCE_FQ, // "Finance::Quote"
+ PRICE_SOURCE_XFER_DLG, // "user:xfer-dialog"
+ PRICE_SOURCE_SPLIT_REG, // "user:split-register"
+ PRICE_SOURCE_STOCK_SPLIT, // "user:stock-split"
+ PRICE_SOURCE_INVOICE, // "user:invoice-post"
+ PRICE_SOURCE_INVALID,
+} PriceSource;
+
+#define PRICE_TYPE_LAST "last"
+#define PRICE_TYPE_UNK "unknown"
+
/* ------------------ */
/** @name Constructors
@{ */
@@ -202,33 +221,26 @@ void gnc_price_commit_edit (GNCPrice *p);
void gnc_price_set_commodity(GNCPrice *p, gnc_commodity *c);
void gnc_price_set_currency(GNCPrice *p, gnc_commodity *c);
void gnc_price_set_time(GNCPrice *p, Timespec t);
-void gnc_price_set_source(GNCPrice *p, const char *source);
+void gnc_price_set_source(GNCPrice *p, PriceSource source);
+void gnc_price_set_source_string(GNCPrice *p, const char* s);
void gnc_price_set_typestr(GNCPrice *p, const char* type);
void gnc_price_set_value(GNCPrice *p, gnc_numeric value);
/** @} */
-#define PRICE_SOURCE_FQ "Finance::Quote"
-#define PRICE_SOURCE_INVOICE "user:invoice-post"
-#define PRICE_SOURCE_STOCK_SPLIT "user:stock-split"
-#define PRICE_SOURCE_XFER_DLG "user:xfer-dialog"
-#define PRICE_SOURCE_SPLIT_REG "user:split-register"
-#define PRICE_SOURCE_EDIT_DLG "user:price-editor"
-#define PRICE_TYPE_LAST "last"
-#define PRICE_TYPE_UNK "unknown"
-
/* ------------------ */
/** @name Getters
All of the getters return data that's internal
to the GNCPrice, not copies, so don't free these values.
@{ */
-GNCPrice * gnc_price_lookup (const GncGUID *guid, QofBook *book);
+ GNCPrice * gnc_price_lookup (const GncGUID *guid, QofBook *book);
/*@ dependent @*/
gnc_commodity * gnc_price_get_commodity(const GNCPrice *p);
/*@ dependent @*/
gnc_commodity * gnc_price_get_currency(const GNCPrice *p);
Timespec gnc_price_get_time(const GNCPrice *p);
-const char * gnc_price_get_source(const GNCPrice *p);
+PriceSource gnc_price_get_source(const GNCPrice *p);
+const char * gnc_price_get_source_string(const GNCPrice *p);
const char * gnc_price_get_typestr(const GNCPrice *p);
gnc_numeric gnc_price_get_value(const GNCPrice *p);
gboolean gnc_price_equal(const GNCPrice *p1, const GNCPrice *p2);
diff --git a/src/engine/test-core/test-engine-stuff.c b/src/engine/test-core/test-engine-stuff.c
index a9d9087..789a10b 100644
--- a/src/engine/test-core/test-engine-stuff.c
+++ b/src/engine/test-core/test-engine-stuff.c
@@ -656,6 +656,7 @@ void
make_random_changes_to_price (QofBook *book, GNCPrice *p)
{
Timespec *ts;
+ PriceSource ps;
char *string;
gnc_commodity *c;
@@ -673,9 +674,9 @@ make_random_changes_to_price (QofBook *book, GNCPrice *p)
gnc_price_set_time (p, *ts);
g_free (ts);
- string = get_random_string ();
- gnc_price_set_source (p, string);
- g_free (string);
+ ps = (PriceSource)get_random_int_in_range((int)PRICE_SOURCE_EDIT_DLG,
+ (int)PRICE_SOURCE_INVALID);
+ gnc_price_set_source (p, ps);
string = get_random_string ();
gnc_price_set_typestr (p, string);
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 502e4ac..2bb173f 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1617,7 +1617,7 @@ create_price(XferDialog *xferData, Timespec ts)
gnc_price_unref (pr.price);
return;
}
- if (strcmp (gnc_price_get_source(pr.price), PRICE_SOURCE_FQ) == 0)
+ if (gnc_price_get_source(pr.price) == PRICE_SOURCE_FQ)
{
PINFO("Existing price is from Finance::Quote, so won't supersede.");
gnc_price_unref (pr.price);
diff --git a/src/gnome-utils/gnc-tree-model-price.c b/src/gnome-utils/gnc-tree-model-price.c
index c62b749..20a4409 100644
--- a/src/gnome-utils/gnc-tree-model-price.c
+++ b/src/gnome-utils/gnc-tree-model-price.c
@@ -786,7 +786,7 @@ gnc_tree_model_price_get_value (GtkTreeModel *tree_model,
break;
case GNC_TREE_MODEL_PRICE_COL_SOURCE:
g_value_init (value, G_TYPE_STRING);
- g_value_set_string (value, gettext (gnc_price_get_source (price)));
+ g_value_set_string (value, gettext (gnc_price_get_source_string (price)));
break;
case GNC_TREE_MODEL_PRICE_COL_TYPE:
g_value_init (value, G_TYPE_STRING);
diff --git a/src/gnome-utils/gnc-tree-view-price.c b/src/gnome-utils/gnc-tree-view-price.c
index 7f3113d..b0dc599 100644
--- a/src/gnome-utils/gnc-tree-view-price.c
+++ b/src/gnome-utils/gnc-tree-view-price.c
@@ -300,8 +300,7 @@ sort_by_source (GtkTreeModel *f_model,
return sort_ns_or_cm (f_model, f_iter_a, f_iter_b);
/* sort by source first */
- result = safe_utf8_collate (gnc_price_get_source (price_a),
- gnc_price_get_source (price_b));
+ result = gnc_price_get_source (price_a) < gnc_price_get_source (price_b);
if (result != 0)
return result;
diff --git a/src/gnome/dialog-price-editor.c b/src/gnome/dialog-price-editor.c
index c7c5b9e..d395903 100644
--- a/src/gnome/dialog-price-editor.c
+++ b/src/gnome/dialog-price-editor.c
@@ -161,7 +161,7 @@ price_to_gui (PriceEditDialog *pedit_dialog)
currency = gnc_price_get_currency (pedit_dialog->price);
date = gnc_price_get_time (pedit_dialog->price);
- source = gnc_price_get_source (pedit_dialog->price);
+ source = gnc_price_get_source_string (pedit_dialog->price);
type = gnc_price_get_typestr (pedit_dialog->price);
value = gnc_price_get_value (pedit_dialog->price);
}
@@ -170,7 +170,7 @@ price_to_gui (PriceEditDialog *pedit_dialog)
currency = gnc_default_currency ();
date.tv_sec = gnc_time (NULL);
date.tv_nsec = 0;
- source = PRICE_SOURCE_EDIT_DLG;
+ source = "user:price-editor"; //Sync with source_names in gnc-pricedb.c
type = "";
value = gnc_numeric_zero ();
}
@@ -237,7 +237,7 @@ gui_to_price (PriceEditDialog *pedit_dialog)
gnc_price_set_commodity (pedit_dialog->price, commodity);
gnc_price_set_currency (pedit_dialog->price, currency);
gnc_price_set_time (pedit_dialog->price, date);
- gnc_price_set_source (pedit_dialog->price, source);
+ gnc_price_set_source_string (pedit_dialog->price, source);
gnc_price_set_typestr (pedit_dialog->price, type);
gnc_price_set_value (pedit_dialog->price, value);
gnc_price_commit_edit (pedit_dialog->price);
diff --git a/src/register/ledger-core/split-register.c b/src/register/ledger-core/split-register.c
index 1b5dd47..1332bf1 100644
--- a/src/register/ledger-core/split-register.c
+++ b/src/register/ledger-core/split-register.c
@@ -2084,7 +2084,7 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
gnc_price_unref (price);
return;
}
- if (strcmp (gnc_price_get_source(price), PRICE_SOURCE_FQ) == 0)
+ if (gnc_price_get_source(price) == PRICE_SOURCE_FQ)
{
gnc_price_unref(price);
return;
diff --git a/src/scm/price-quotes.scm b/src/scm/price-quotes.scm
index ecea984..fc81139 100644
--- a/src/scm/price-quotes.scm
+++ b/src/scm/price-quotes.scm
@@ -421,7 +421,7 @@
(begin
(gnc-price-begin-edit saved-price)
(gnc-price-set-time saved-price gnc-time)
- (gnc-price-set-source saved-price "Finance::Quote")
+ (gnc-price-set-source-string saved-price "Finance::Quote")
(gnc-price-set-typestr saved-price price-type)
(gnc-price-set-value saved-price price)
(gnc-price-commit-edit saved-price)
@@ -435,7 +435,7 @@
(gnc-price-set-commodity gnc-price commodity)
(gnc-price-set-currency gnc-price currency)
(gnc-price-set-time gnc-price gnc-time)
- (gnc-price-set-source gnc-price "Finance::Quote")
+ (gnc-price-set-source-string gnc-price "Finance::Quote")
(gnc-price-set-typestr gnc-price price-type)
(gnc-price-set-value gnc-price price)
(gnc-price-commit-edit gnc-price)
commit d52a0b602c0af20faa40f344f2c5de1e99c1eaff
Author: John Ralls <jralls at ceridwen.us>
Date: Thu Sep 3 16:16:33 2015 -0700
Fix whitespace error.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 715245e..502e4ac 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1460,7 +1460,8 @@ check_accounts (XferDialog* xferData, Account* from_account,
static gboolean
check_edit(XferDialog *xferData)
-{ if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->price_edit)))
+{
+ if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->price_edit)))
{
if (gtk_toggle_button_get_active
(GTK_TOGGLE_BUTTON(xferData->price_radio)))
commit d4968d3bb40129c4e26a5f7b3b6de001b60dfc7b
Author: John Ralls <jralls at ceridwen.us>
Date: Thu Sep 3 11:22:51 2015 -0700
Extract function lookup_price in dialog_transfer.c
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index f0c2ff9..715245e 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -216,73 +216,107 @@ round_price(gnc_commodity *from, gnc_commodity *to, gnc_numeric value)
return value;
}
-/* (maybe) update the price from the pricedb. */
-static void
-gnc_xfer_dialog_update_price (XferDialog *xferData)
+typedef struct
{
- GNCPrice *prc;
- gnc_numeric price_value;
- Timespec date;
- gnc_commodity *from = xferData->from_commodity;
- gnc_commodity *to = xferData->to_commodity;
+ GNCPrice *price;
+ GNCPriceDB *pricedb;
+ gnc_commodity *from;
+ gnc_commodity *to;
+ Timespec ts;
gboolean reverse;
+} PriceReq;
- if (!xferData) return;
- if (!xferData->from_commodity || ! xferData->to_commodity) return;
- if (gnc_commodity_equal (xferData->from_commodity, xferData->to_commodity))
- return;
- if (!xferData->pricedb) return;
-
- /* when do we update, and when do we NOT update? */
-
- /* XXX: I'm ALWAYS going to update whenever we get called */
-
- /* grab the price on the same day or nearest to the DATE out of the pricedb */
- date = gnc_date_edit_get_date_ts (GNC_DATE_EDIT (xferData->date_entry));
+static void
+price_request_from_xferData(PriceReq *pr, XferDialog *xd)
+{
+ g_return_if_fail (pr != NULL);
+ g_return_if_fail (xd != NULL);
+ pr->price = NULL;
+ pr->pricedb = xd->pricedb;
+ pr->from = xd->from_commodity;
+ pr->to = xd->to_commodity;
+ pr->ts = gnc_date_edit_get_date_ts (GNC_DATE_EDIT (xd->date_entry));
+ pr->reverse = FALSE;
+}
- /* Look for a price on the same day or, failing that, closest in time. */
- prc = gnc_pricedb_lookup_day (xferData->pricedb, from, to, date);
- reverse = FALSE;
+static gboolean
+lookup_price(PriceReq *pr, gboolean day_only)
+{
+ GNCPrice *prc = NULL;
+ g_return_val_if_fail (pr != NULL, FALSE);
+ g_return_val_if_fail (pr->pricedb != NULL, FALSE);
+ g_return_val_if_fail (pr->from != NULL, FALSE);
+ g_return_val_if_fail (pr->to != NULL, FALSE);
+ pr->reverse = FALSE;
+ if (day_only)
+ {
+ prc = gnc_pricedb_lookup_day (pr->pricedb, pr->from, pr->to, pr->ts);
if (!prc)
{
- /* Look for reverse price on same day */
- prc = gnc_pricedb_lookup_day (xferData->pricedb, to, from, date);
- reverse = TRUE;
+ prc = gnc_pricedb_lookup_day (pr->pricedb, pr->to,
+ pr->from, pr->ts);
+ pr->reverse = TRUE;
}
-
+ }
+ else
+ {
+ prc = gnc_pricedb_lookup_nearest_in_time (pr->pricedb, pr->from,
+ pr->to, pr->ts);
if (!prc)
{
- /* Didn't find one on the same day, look for nearest in time */
- prc = gnc_pricedb_lookup_nearest_in_time (xferData->pricedb, from,
- to, date);
- reverse = FALSE;
+ prc = gnc_pricedb_lookup_nearest_in_time (pr->pricedb, pr->to,
+ pr->from, pr->ts);
+ pr->reverse = TRUE;
}
+ }
+ if (pr->reverse)
+ {
+ PINFO("Found reverse price: 1 %s = %f %s",
+ gnc_commodity_get_mnemonic(pr->to),
+ gnc_numeric_to_double(gnc_price_get_value(prc)),
+ gnc_commodity_get_mnemonic(pr->from));
- if (!prc)
+ }
+ else
{
- prc = gnc_pricedb_lookup_nearest_in_time (xferData->pricedb, to,
- from, date);
- reverse = TRUE;
+ PINFO("Found price: 1 %s = %f %s",
+ gnc_commodity_get_mnemonic(pr->from),
+ gnc_numeric_to_double(gnc_price_get_value(prc)),
+ gnc_commodity_get_mnemonic(pr->to));
}
-
if (!prc)
+ return FALSE;
+ pr->price = prc;
+ return TRUE;
+}
+
+/* (maybe) update the price from the pricedb. */
+static void
+gnc_xfer_dialog_update_price (XferDialog *xferData)
+{
+ PriceReq pr;
+ gnc_numeric price_value;
+
+ if (!xferData) return;
+ if (!xferData->from_commodity || ! xferData->to_commodity) return;
+ if (gnc_commodity_equal (xferData->from_commodity, xferData->to_commodity))
+ return;
+ if (!xferData->pricedb) return;
+
+ price_request_from_xferData(&pr, xferData);
+ if (!lookup_price(&pr, TRUE))
+ if (!lookup_price(&pr, FALSE))
return;
/* grab the price from the pricedb */
- price_value = gnc_price_get_value (prc);
- if (reverse)
+ price_value = gnc_price_get_value (pr.price);
+ if (pr.reverse)
{
- PINFO("Found reverse price: 1 %s = %f %s", gnc_commodity_get_mnemonic(to),
- gnc_numeric_to_double(price_value), gnc_commodity_get_mnemonic(from));
price_value = gnc_numeric_invert (price_value);
- price_value = round_price(from, to, price_value);
- }
- else
- {
- PINFO("Found price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
- gnc_numeric_to_double(price_value), gnc_commodity_get_mnemonic(to));
+ price_value = round_price(pr.from, pr.to, price_value);
}
+ gnc_price_unref(pr.price);
/* and set the price entry */
_gnc_xfer_dialog_set_price_edit(xferData, price_value);
@@ -1542,9 +1576,10 @@ swap_commodities(gnc_commodity **from, gnc_commodity **to, gnc_numeric value)
static void
create_price(XferDialog *xferData, Timespec ts)
{
+ PriceReq pr;
+ GNCPrice *price = NULL;
gnc_commodity *from = xferData->from_commodity;
gnc_commodity *to = xferData->to_commodity;
- GNCPrice *price;
gnc_numeric price_value;
gnc_numeric value;
gnc_numeric from_amt, to_amt;
@@ -1561,52 +1596,49 @@ create_price(XferDialog *xferData, Timespec ts)
(strcmp (gnc_commodity_get_mnemonic(from),
gnc_commodity_get_mnemonic(to)) < 0)))
swap_amount (&from, &to, &value, &from_amt, &to_amt);
- /* First see if the closest entry on the same day has an equivalent rate */
- price = gnc_pricedb_lookup_day (xferData->pricedb, from, to, ts);
- if (!price)
- {
- price = gnc_pricedb_lookup_day (xferData->pricedb, to, from, ts);
- if (price)
- swap = TRUE;
- }
+
/* Normally we want to store currency rates such that the rate > 1 and commodity
* prices in terms of a currency regardless of value. However, if we already
* have a price in either direction we want to continue using that direction for
* the rest of the day so that we don't wind up with two prices if the rate
* shifts to be < 1. */
- if (price)
+ price_request_from_xferData(&pr, xferData);
+ if (lookup_price(&pr, TRUE))
{
- price_value = gnc_price_get_value(price);
- if (gnc_numeric_equal(swap ? gnc_numeric_invert(value) : value,
+ price_value = gnc_price_get_value(pr.price);
+ if (gnc_numeric_equal(pr.reverse ? gnc_numeric_invert(value) : value,
price_value))
{
- PINFO("Found price for %s in %s", gnc_commodity_get_mnemonic(from),
- gnc_commodity_get_mnemonic(to));
- gnc_price_unref (price);
+ PINFO("Found price for %s in %s",
+ gnc_commodity_get_mnemonic(pr.from),
+ gnc_commodity_get_mnemonic(pr.to));
+ gnc_price_unref (pr.price);
return;
}
- if (strcmp (gnc_price_get_source(price), PRICE_SOURCE_FQ) == 0)
+ if (strcmp (gnc_price_get_source(pr.price), PRICE_SOURCE_FQ) == 0)
{
PINFO("Existing price is from Finance::Quote, so won't supersede.");
- gnc_price_unref (price);
+ gnc_price_unref (pr.price);
return;
}
- if (swap)
+ if (pr.reverse)
{
value = swap_commodities(&from, &to, value);
xferData->from_commodity = from;
xferData->to_commodity = to;
}
- value = round_price(from, to, value);
- gnc_price_begin_edit (price);
- gnc_price_set_time (price, ts);
- gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
- gnc_price_set_value (price, value);
- gnc_price_commit_edit (price);
- PINFO("Modified price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
- gnc_numeric_to_double(value), gnc_commodity_get_mnemonic(to));
- gnc_price_unref (price);
+ value = round_price(pr.from, pr.to, value);
+ gnc_price_begin_edit (pr.price);
+ gnc_price_set_time (pr.price, ts);
+ gnc_price_set_source (pr.price, PRICE_SOURCE_XFER_DLG);
+ gnc_price_set_value (pr.price, value);
+ gnc_price_commit_edit (pr.price);
+ PINFO("Modified price: 1 %s = %f %s",
+ gnc_commodity_get_mnemonic(from),
+ gnc_numeric_to_double(value),
+ gnc_commodity_get_mnemonic(to));
+ gnc_price_unref (pr.price);
return;
}
if (gnc_commodity_is_currency(from) && gnc_commodity_is_currency(to))
commit 157c7e30a53abe2e8f74ea61e02c497a306bf6ac
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 1 14:56:19 2015 -0700
Invert the F::Q price if there's already one in the other direction.
We don't want to create prices in both directions on the same day.
diff --git a/src/scm/price-quotes.scm b/src/scm/price-quotes.scm
index c6a2405..ecea984 100644
--- a/src/scm/price-quotes.scm
+++ b/src/scm/price-quotes.scm
@@ -1,17 +1,17 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; price-quotes.scm - manage sub-processes.
;;; Copyright 2001 Rob Browning <rlb at cs.utexas.edu>
-;;;
-;;; This program is free software; you can redistribute it and/or
-;;; modify it under the terms of the GNU General Public License as
-;;; published by the Free Software Foundation; either version 2 of
-;;; the License, or (at your option) any later version.
-;;;
-;;; This program is distributed in the hope that it will be useful,
-;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;;; GNU General Public License for more details.
-;;;
+;;;
+;;; This program is free software; you can redistribute it and/or
+;;; modify it under the terms of the GNU General Public License as
+;;; published by the Free Software Foundation; either version 2 of
+;;; the License, or (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program; if not, contact:
;;;
@@ -35,7 +35,7 @@
(define (item-list->hash! lst hash
getkey getval
- hashref hashset
+ hashref hashset
list-duplicates?)
;; Takes a list of the form (item item item item) and returns a hash
;; formed by traversing the list, and getting the key and val from
@@ -58,7 +58,7 @@
(if existing-val
(hashset hash key (cons val existing-val))
(hashset hash key (list val))))))
-
+
(for-each handle-item lst)
hash)
@@ -205,7 +205,7 @@
;; a list of the corresponding commodities. Also perform a bit of
;; optimization, merging calls for symbols to the same
;; Finance::Quote method.
- ;;
+ ;;
;; Returns a list of the info needed for a set of calls to
;; gnc-fq-helper. Each item will of the list will be of the
;; form:
@@ -223,7 +223,7 @@
(commodity-list #f)
(currency-list (filter
(lambda (a) (not (gnc-commodity-equiv (cadr a) (caddr a))))
- (call-with-values
+ (call-with-values
(lambda () (partition!
(lambda (cmd)
(not (string=? (car cmd) "currency")))
@@ -257,7 +257,7 @@
;;
;; ("yahoo" (commodity-1 currency-1 tz-1)
;; (commodity-2 currency-2 tz-2) ...)
- ;;
+ ;;
;; ("yahoo" "IBM" "AMD" ...)
;;
@@ -411,6 +411,12 @@
(set! saved-price (gnc-pricedb-lookup-day pricedb
commodity currency
gnc-time))
+ (if (null? saved-price)
+ (begin
+ (set! saved-price (gnc-pricedb-lookup-day pricedb currency
+ commodity gnc-time))
+ (if (not (null? saved-price))
+ (set! price (gnc-numeric-invert(price))))))
(if (not (null? saved-price))
(begin
(gnc-price-begin-edit saved-price)
commit 890cfe2186a452969cd2eeadaf065c04ef054d68
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 1 14:47:40 2015 -0700
Handle currencies with one-directional quotes and quotes < 1 in F::Q.
Some currencies quotes are one-directional, so check both directions if
necessary. Quotes with values < 1 often have too few significant digits,
so in that case use the other direction if available.
diff --git a/src/quotes/gnc-fq-dump b/src/quotes/gnc-fq-dump
index 2b1ab1e..771e2ae 100755
--- a/src/quotes/gnc-fq-dump
+++ b/src/quotes/gnc-fq-dump
@@ -166,6 +166,15 @@ if ($exchange eq "currency") {
while ($#ARGV >= 0) {
my $to = shift;
my $result = $q->currency($from, $to);
+ unless (defined($result) && $result >= 1) {
+ my $inv_res = $q->currency($to, $from);
+ if (defined($inv_res)) {
+ my $tmp = $to;
+ $to = $from;
+ $from = $tmp;
+ $result = $inv_res;
+ }
+ }
if (defined($result)) {
printf "1 $from = $result $to\n";
} else {
diff --git a/src/quotes/gnc-fq-helper.in b/src/quotes/gnc-fq-helper.in
index edb6220..6af1dee 100755
--- a/src/quotes/gnc-fq-helper.in
+++ b/src/quotes/gnc-fq-helper.in
@@ -350,6 +350,19 @@ while(<>) {
last unless $to_currency;
my $price = $quoter->currency($from_currency, $to_currency);
+ my $inv_price = undef;
+ #Sometimes price quotes are available in only one direction, and if the
+ #direction we asked for results in a quote < 1 we want the other direction
+ #if it's available to get more significant digits.
+ unless (defined($price) && $price > 1) {
+ $inv_price = $quoter->currency($to_currency, $from_currency);
+ if (defined($inv_price)) {
+ my $tmp = $to_currency;
+ $to_currency = $from_currency;
+ $from_currency = $tmp;
+ $price = $inv_price;
+ }
+ }
$quote_data{$from_currency, "success"} = defined($price);
$quote_data{$from_currency, "symbol"} = $from_currency;
commit 96471379f0d0f1fd8b5e6050a5f8e7d26fd7964c
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 1 12:44:25 2015 -0700
Adjust split_register to match transfer dialog checking inverted prices.
diff --git a/src/register/ledger-core/split-register.c b/src/register/ledger-core/split-register.c
index 3cf90cc..1b5dd47 100644
--- a/src/register/ledger-core/split-register.c
+++ b/src/register/ledger-core/split-register.c
@@ -2056,6 +2056,7 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
int scu = gnc_commodity_get_fraction(curr);
Timespec ts;
BasicCell *cell = gnc_table_layout_get_cell (reg->table->layout, DATE_CELL);
+ gboolean swap = FALSE;
/* Only record the price for account types that don't have a
* "rate" cell. They'll get handled later by
@@ -2065,24 +2066,20 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
return;
gnc_date_cell_get_date ((DateCell*)cell, &ts);
price = gnc_pricedb_lookup_day (pricedb, comm, curr, ts);
- if (price)
- {
- price_value = gnc_price_get_value(price);
- }
- else
+ if (!price)
{
price = gnc_pricedb_lookup_day (pricedb, curr, comm, ts);
if (price)
- {
/* It might be better to raise an error here: We shouldn't be creating
* currency->commodity prices.
*/
- price_value = gnc_numeric_invert(gnc_price_get_value(price));
- }
+ swap = TRUE;
}
if (price)
{
- if (gnc_numeric_equal(value, price_value))
+ price_value = gnc_price_get_value(price);
+ if (gnc_numeric_equal(swap ? gnc_numeric_invert(value) : value,
+ price_value))
{
gnc_price_unref (price);
return;
@@ -2092,16 +2089,13 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
gnc_price_unref(price);
return;
}
- if (!gnc_numeric_eq(price_value, gnc_price_get_value(price)))
+ if (swap)
{
value = gnc_numeric_invert(value);
scu = gnc_commodity_get_fraction(comm);
- value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
- GNC_HOW_RND_ROUND_HALF_UP);
}
- else
- value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
- GNC_HOW_RND_ROUND_HALF_UP);
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
gnc_price_begin_edit (price);
gnc_price_set_time (price, ts);
gnc_price_set_source (price, PRICE_SOURCE_SPLIT_REG);
commit d7fb92d03f9b043bb3f5259d4ff9d8a13bc4161e
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 1 12:39:12 2015 -0700
Fix missing initialization of price_value.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index a7ecf9d..f0c2ff9 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1577,6 +1577,7 @@ create_price(XferDialog *xferData, Timespec ts)
if (price)
{
+ price_value = gnc_price_get_value(price);
if (gnc_numeric_equal(swap ? gnc_numeric_invert(value) : value,
price_value))
{
commit 93bb5c0fdd3c9ea1df7801228ea05bd0b989fd4c
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 1 12:17:12 2015 -0700
Change CURRENCY_DENOM to 10000, matching what F::Q returns.
diff --git a/src/engine/gnc-pricedb.h b/src/engine/gnc-pricedb.h
index c7fe6d0..ae65748 100644
--- a/src/engine/gnc-pricedb.h
+++ b/src/engine/gnc-pricedb.h
@@ -250,7 +250,7 @@ void gnc_price_print(GNCPrice *db, FILE *f, int indent);
* of the commodity with a fixed denominator of the pricing currency's
* SCU * 10000.
*/
-#define CURRENCY_DENOM 1000
+#define CURRENCY_DENOM 10000
#define COMMODITY_DENOM_MULT 10000
/* ================================================================ */
commit ffe96b304412aa059c075b66812d3bcbf0712839
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 1 12:16:09 2015 -0700
Extract function round_price(), consistently apply it.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index dd90e8b..a7ecf9d 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -190,6 +190,32 @@ gnc_xfer_dialog_compute_price_value (XferDialog *xferData)
return(gnc_numeric_div(to_amt, from_amt, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE));
}
+/* Round a price value according to this policy:
+ * If both commodities are currencies, round to a fixed denominator.
+ * If only one is a currency, round to the currency's scu * a fixed factor.
+ * The fixed values are defined in gnc-pricedb.h
+ */
+static gnc_numeric
+round_price(gnc_commodity *from, gnc_commodity *to, gnc_numeric value)
+{
+ if (gnc_commodity_is_currency(from) && gnc_commodity_is_currency(to))
+ value = gnc_numeric_convert(value, CURRENCY_DENOM,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ else if (gnc_commodity_is_currency(to))
+ {
+ int scu = gnc_commodity_get_fraction (to);
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ }
+ else if (gnc_commodity_is_currency(from))
+ {
+ int scu = gnc_commodity_get_fraction (from);
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ }
+ return value;
+}
+
/* (maybe) update the price from the pricedb. */
static void
gnc_xfer_dialog_update_price (XferDialog *xferData)
@@ -249,7 +275,8 @@ gnc_xfer_dialog_update_price (XferDialog *xferData)
{
PINFO("Found reverse price: 1 %s = %f %s", gnc_commodity_get_mnemonic(to),
gnc_numeric_to_double(price_value), gnc_commodity_get_mnemonic(from));
- price_value = gnc_numeric_invert(price_value);
+ price_value = gnc_numeric_invert (price_value);
+ price_value = round_price(from, to, price_value);
}
else
{
@@ -1001,17 +1028,11 @@ gnc_xfer_to_amount_update_cb(GtkWidget *widget, GdkEventFocus *event,
XferDialog *xferData = data;
gnc_numeric price_value;
Account *account;
- int scu;
- account = gnc_transfer_dialog_get_selected_account (xferData, XFER_DIALOG_TO);
- if (account == NULL)
- account = gnc_transfer_dialog_get_selected_account (xferData, XFER_DIALOG_FROM);
- scu = xaccAccountGetCommoditySCU(account);
gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->to_amount_edit));
-
price_value = gnc_xfer_dialog_compute_price_value(xferData);
- price_value = gnc_numeric_convert (price_value, scu * COMMODITY_DENOM_MULT,
- GNC_HOW_RND_ROUND_HALF_UP);
+ price_value = round_price(xferData->from_commodity, xferData->to_commodity,
+ price_value);
gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit),
price_value);
gnc_xfer_dialog_update_conv_info(xferData);
@@ -1496,24 +1517,26 @@ static void
swap_amount (gnc_commodity **from, gnc_commodity **to, gnc_numeric *value,
gnc_numeric *from_amt, gnc_numeric *to_amt)
{
- gnc_commodity *tmp;
- gnc_numeric *tmp_amt;
- tmp = *from;
+ gnc_commodity *tmp = *from;
+ gnc_numeric *tmp_amt = from_amt;
*from = *to;
*to = tmp;
- tmp_amt = from_amt;
from_amt = to_amt;
to_amt = tmp_amt;
*value = gnc_numeric_invert (*value);
+ *value = round_price(*from, *to, *value);
}
static gnc_numeric
swap_commodities(gnc_commodity **from, gnc_commodity **to, gnc_numeric value)
{
gnc_commodity *tmp = *to;
+
*to = *from;
*from = tmp;
- return gnc_numeric_invert(value);
+ value = gnc_numeric_invert(value);
+ value = round_price(*from, *to, value);
+ return value;
}
static void
@@ -1546,6 +1569,11 @@ create_price(XferDialog *xferData, Timespec ts)
if (price)
swap = TRUE;
}
+/* Normally we want to store currency rates such that the rate > 1 and commodity
+ * prices in terms of a currency regardless of value. However, if we already
+ * have a price in either direction we want to continue using that direction for
+ * the rest of the day so that we don't wind up with two prices if the rate
+ * shifts to be < 1. */
if (price)
{
@@ -1566,16 +1594,10 @@ create_price(XferDialog *xferData, Timespec ts)
if (swap)
{
value = swap_commodities(&from, &to, value);
+ xferData->from_commodity = from;
+ xferData->to_commodity = to;
}
- if (gnc_commodity_is_currency(from) && gnc_commodity_is_currency(to))
- value = gnc_numeric_convert(value, CURRENCY_DENOM,
- GNC_HOW_RND_ROUND_HALF_UP);
- else if (gnc_commodity_is_currency(to))
- {
- int scu = gnc_commodity_get_fraction (to);
- value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
- GNC_HOW_RND_ROUND_HALF_UP);
- }
+ value = round_price(from, to, value);
gnc_price_begin_edit (price);
gnc_price_set_time (price, ts);
gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
@@ -1814,6 +1836,7 @@ gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData)
{
/* FIXME: We probably want to swap the result price's to and from, not invert the price. */
rate = gnc_numeric_invert(gnc_price_get_value (prc));
+ rate = round_price(from, to, rate);
_gnc_xfer_dialog_set_price_edit(xferData, rate);
gnc_price_unref (prc);
have_price = TRUE;
@@ -2370,6 +2393,7 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
gboolean swap_amounts = FALSE;
gnc_commodity *txn_cur = xaccTransGetCurrency(txn);
gnc_commodity *reg_com = xaccAccountGetCommodity(reg_acc);
+ gnc_numeric dialog_rate = *exch_rate;
g_return_val_if_fail(txn_cur, TRUE);
@@ -2431,7 +2455,10 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
gnc_xfer_dialog_select_to_currency(xfer, txn_cur);
gnc_xfer_dialog_select_from_currency(xfer, xfer_com);
if (!gnc_numeric_zero_p(*exch_rate))
- *exch_rate = gnc_numeric_invert(*exch_rate);
+ {
+ dialog_rate = gnc_numeric_invert(*exch_rate);
+ dialog_rate = round_price(xfer_com, txn_cur, *exch_rate);
+ }
amount = gnc_numeric_neg(amount);
}
else
@@ -2455,16 +2482,11 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
*/
/* Set the exchange rate */
- _gnc_xfer_dialog_set_price_edit(xfer, *exch_rate);
+ _gnc_xfer_dialog_set_price_edit(xfer, dialog_rate);
/* and run it... */
if (gnc_xfer_dialog_run_until_done(xfer) == FALSE)
return TRUE;
- /* If we swapped the amounts for the dialog, then make sure we swap
- * it back now...
- */
- if (swap_amounts)
- *exch_rate = gnc_numeric_invert(*exch_rate);
return FALSE;
}
commit bfbb50879901ac4f0ecde4065d5b662afa69568f
Author: John Ralls <jralls at ceridwen.us>
Date: Mon Aug 31 13:40:21 2015 -0700
Fix swap_amount so that it swaps the account pointers.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 2f4950c..dd90e8b 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1493,14 +1493,14 @@ create_transaction(XferDialog *xferData, Timespec *ts,
}
static void
-swap_amount (gnc_commodity *from, gnc_commodity *to, gnc_numeric *value,
+swap_amount (gnc_commodity **from, gnc_commodity **to, gnc_numeric *value,
gnc_numeric *from_amt, gnc_numeric *to_amt)
{
gnc_commodity *tmp;
gnc_numeric *tmp_amt;
- tmp = from;
- from = to;
- to = tmp;
+ tmp = *from;
+ *from = *to;
+ *to = tmp;
tmp_amt = from_amt;
from_amt = to_amt;
to_amt = tmp_amt;
@@ -1537,7 +1537,7 @@ create_price(XferDialog *xferData, Timespec ts)
((to != gnc_default_currency()) &&
(strcmp (gnc_commodity_get_mnemonic(from),
gnc_commodity_get_mnemonic(to)) < 0)))
- swap_amount (from, to, &value, &from_amt, &to_amt);
+ swap_amount (&from, &to, &value, &from_amt, &to_amt);
/* First see if the closest entry on the same day has an equivalent rate */
price = gnc_pricedb_lookup_day (xferData->pricedb, from, to, ts);
if (!price)
commit 86320a4d11188bbc0b251060440dc693d502053c
Author: John Ralls <jralls at ceridwen.us>
Date: Mon Aug 31 13:39:37 2015 -0700
Fix gnc_numeric_invert to correctly handle negative values.
diff --git a/src/libqof/qof/gnc-numeric.c b/src/libqof/qof/gnc-numeric.c
index 97e416f..44c6400 100644
--- a/src/libqof/qof/gnc-numeric.c
+++ b/src/libqof/qof/gnc-numeric.c
@@ -1154,9 +1154,21 @@ gnc_numeric_invert(gnc_numeric num)
{
if (num.num == 0)
return gnc_numeric_zero();
- return gnc_numeric_create (num.denom, num.num);
+ if (num.denom > 0)
+ {
+ if (num.num < 0)
+ return gnc_numeric_create (-num.denom, -num.num);
+ return gnc_numeric_create (num.denom, num.num);
+ }
+ else /* Negative denominator means multiply instead of divide. */
+ {
+ int64_t mult = (num.num < 0 ? INT64_C(-1) : INT64_C(1));
+ qofint128 denom = mult128(-num.denom, mult * num.num);
+ if (denom.hi)
+ return gnc_numeric_error(GNC_ERROR_OVERFLOW);
+ return gnc_numeric_create (mult, denom.lo);
+ }
}
-
/* *******************************************************************
* double_to_gnc_numeric
********************************************************************/
commit c068397633569699b00cd3f4062f779f84f16faf
Author: John Ralls <jralls at ceridwen.us>
Date: Sun Aug 30 11:36:54 2015 -0700
Flip return values of check_edit() and check_accounts().
It's easier to understand if they return FALSE on fail.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 79f6ba2..2f4950c 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1361,7 +1361,7 @@ check_accounts (XferDialog* xferData, Account* from_account,
"Otherwise, it will not be recorded.");
gnc_error_dialog(xferData->dialog, "%s", message);
LEAVE("bad account");
- return TRUE;
+ return FALSE;
}
if (from_account == to_account)
@@ -1370,7 +1370,7 @@ check_accounts (XferDialog* xferData, Account* from_account,
"account!");
gnc_error_dialog(xferData->dialog, "%s", message);
LEAVE("same account");
- return TRUE;
+ return FALSE;
}
if (xaccAccountGetPlaceholder(from_account) ||
@@ -1398,9 +1398,9 @@ check_accounts (XferDialog* xferData, Account* from_account,
"and making the \"amount\" negative.");
gnc_error_dialog(xferData->dialog, "%s", message);
LEAVE("non-currency");
- return TRUE;
+ return FALSE;
}
- return FALSE;
+ return TRUE;
}
static gboolean
@@ -1412,7 +1412,7 @@ check_edit(XferDialog *xferData)
{
gnc_parse_error_dialog (xferData, _("You must enter a valid price."));
LEAVE("invalid price");
- return TRUE;
+ return FALSE;
}
}
@@ -1424,10 +1424,10 @@ check_edit(XferDialog *xferData)
gnc_parse_error_dialog (xferData,
_("You must enter a valid `to' amount."));
LEAVE("invalid to amount");
- return TRUE;
+ return FALSE;
}
}
- return FALSE;
+ return TRUE;
}
static void
@@ -1647,7 +1647,7 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
to_account = gnc_transfer_dialog_get_selected_account (xferData, XFER_DIALOG_TO);
if (xferData->exch_rate == NULL &&
- check_accounts(xferData, from_account, to_account))
+ !check_accounts(xferData, from_account, to_account))
return;
if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->amount_edit)))
@@ -1671,7 +1671,7 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
if (!gnc_commodity_equiv(xferData->from_commodity, xferData->to_commodity))
{
- if (check_edit(xferData))
+ if (!check_edit(xferData))
return;
to_amount = gnc_amount_edit_get_amount
(GNC_AMOUNT_EDIT(xferData->to_amount_edit));
commit e12c89b5cac50364e7234ce9be94cb0bf0819c59
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Aug 29 07:50:20 2015 -0700
Move gnc_numeric_invert to be not-inline.
The inline version crashed.
diff --git a/src/libqof/qof/gnc-numeric.c b/src/libqof/qof/gnc-numeric.c
index 693fdf9..97e416f 100644
--- a/src/libqof/qof/gnc-numeric.c
+++ b/src/libqof/qof/gnc-numeric.c
@@ -1149,6 +1149,13 @@ gnc_numeric_to_decimal(gnc_numeric *a, guint8 *max_decimal_places)
return TRUE;
}
+gnc_numeric
+gnc_numeric_invert(gnc_numeric num)
+{
+ if (num.num == 0)
+ return gnc_numeric_zero();
+ return gnc_numeric_create (num.denom, num.num);
+}
/* *******************************************************************
* double_to_gnc_numeric
diff --git a/src/libqof/qof/gnc-numeric.h b/src/libqof/qof/gnc-numeric.h
index b833753..89933c8 100644
--- a/src/libqof/qof/gnc-numeric.h
+++ b/src/libqof/qof/gnc-numeric.h
@@ -510,10 +510,7 @@ gboolean gnc_numeric_to_decimal(gnc_numeric * a,
* @param num The number to be inverted
* @return a gnc_numeric that is the inverse of num
*/
-inline gnc_numeric gnc_numeric_invert (gnc_numeric num)
-{
- return gnc_numeric_create (num.num, num.denom);
-}
+gnc_numeric gnc_numeric_invert (gnc_numeric num);
/** @} */
/** @name GValue
commit 6b5207785a28c24ee887bc58a0af64318ba26640
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Aug 28 21:20:51 2015 +0100
Create a rounding policy for prices in the pricedb.
Currency-currency prices will be priced in the smaller currency so that
the price > 1 and will be rounded to 3 digits after the decimal.
Commodity-currency prices will be priced in the currency and rounded to
the currency's scu * 10000.
This affects only prices stored in the pricedb. Prices in splits will
continue to be computed from value/amount.
diff --git a/src/engine/gnc-pricedb.h b/src/engine/gnc-pricedb.h
index befff2d..c7fe6d0 100644
--- a/src/engine/gnc-pricedb.h
+++ b/src/engine/gnc-pricedb.h
@@ -243,6 +243,15 @@ gboolean gnc_price_equal(const GNCPrice *p1, const GNCPrice *p2);
/** This simple function can be useful for debugging the price code */
void gnc_price_print(GNCPrice *db, FILE *f, int indent);
/** @} */
+/** @name Denominator Constants Price policy: In order to avoid rounding
+ * problems, currency prices (often called exchange rates) are saved in terms of
+ * the smaller currency, so that price > 1, with a fixed denominator of
+ * 1/1000. Commodity prices in currency are always expressed as value per unit
+ * of the commodity with a fixed denominator of the pricing currency's
+ * SCU * 10000.
+ */
+#define CURRENCY_DENOM 1000
+#define COMMODITY_DENOM_MULT 10000
/* ================================================================ */
/** @name GNCPrice lists
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 0bfa185..79f6ba2 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -55,8 +55,6 @@
#define DIALOG_TRANSFER_CM_CLASS "dialog-transfer"
#define GNC_PREFS_GROUP "dialogs.transfer"
-#define PRECISION 1000000
-
typedef enum
{
XFER_DIALOG_FROM,
@@ -1003,15 +1001,16 @@ gnc_xfer_to_amount_update_cb(GtkWidget *widget, GdkEventFocus *event,
XferDialog *xferData = data;
gnc_numeric price_value;
Account *account;
+ int scu;
account = gnc_transfer_dialog_get_selected_account (xferData, XFER_DIALOG_TO);
if (account == NULL)
account = gnc_transfer_dialog_get_selected_account (xferData, XFER_DIALOG_FROM);
-
+ scu = xaccAccountGetCommoditySCU(account);
gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->to_amount_edit));
price_value = gnc_xfer_dialog_compute_price_value(xferData);
- price_value = gnc_numeric_convert (price_value, PRECISION,
+ price_value = gnc_numeric_convert (price_value, scu * COMMODITY_DENOM_MULT,
GNC_HOW_RND_ROUND_HALF_UP);
gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit),
price_value);
@@ -1507,6 +1506,16 @@ swap_amount (gnc_commodity *from, gnc_commodity *to, gnc_numeric *value,
to_amt = tmp_amt;
*value = gnc_numeric_invert (*value);
}
+
+static gnc_numeric
+swap_commodities(gnc_commodity **from, gnc_commodity **to, gnc_numeric value)
+{
+ gnc_commodity *tmp = *to;
+ *to = *from;
+ *from = tmp;
+ return gnc_numeric_invert(value);
+}
+
static void
create_price(XferDialog *xferData, Timespec ts)
{
@@ -1516,6 +1525,7 @@ create_price(XferDialog *xferData, Timespec ts)
gnc_numeric price_value;
gnc_numeric value;
gnc_numeric from_amt, to_amt;
+ gboolean swap = FALSE;
/* Bail in the unlikely event that both currencies have joined the Euro. */
if (gnc_is_euro_currency (from) && gnc_is_euro_currency (to))
@@ -1530,21 +1540,17 @@ create_price(XferDialog *xferData, Timespec ts)
swap_amount (from, to, &value, &from_amt, &to_amt);
/* First see if the closest entry on the same day has an equivalent rate */
price = gnc_pricedb_lookup_day (xferData->pricedb, from, to, ts);
- if (price)
- {
- price_value = gnc_price_get_value(price);
- }
- else
+ if (!price)
{
price = gnc_pricedb_lookup_day (xferData->pricedb, to, from, ts);
if (price)
-
- price_value = gnc_numeric_invert(gnc_price_get_value(price));
+ swap = TRUE;
}
if (price)
{
- if (gnc_numeric_equal(value, price_value))
+ if (gnc_numeric_equal(swap ? gnc_numeric_invert(value) : value,
+ price_value))
{
PINFO("Found price for %s in %s", gnc_commodity_get_mnemonic(from),
gnc_commodity_get_mnemonic(to));
@@ -1557,10 +1563,18 @@ create_price(XferDialog *xferData, Timespec ts)
gnc_price_unref (price);
return;
}
- if (!gnc_numeric_eq(price_value, gnc_price_get_value(price)))
+ if (swap)
{
- value = gnc_numeric_invert(value);
- value = gnc_numeric_convert(value, PRECISION, GNC_HOW_DENOM_REDUCE);
+ value = swap_commodities(&from, &to, value);
+ }
+ if (gnc_commodity_is_currency(from) && gnc_commodity_is_currency(to))
+ value = gnc_numeric_convert(value, CURRENCY_DENOM,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ else if (gnc_commodity_is_currency(to))
+ {
+ int scu = gnc_commodity_get_fraction (to);
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
}
gnc_price_begin_edit (price);
gnc_price_set_time (price, ts);
@@ -1572,6 +1586,24 @@ create_price(XferDialog *xferData, Timespec ts)
gnc_price_unref (price);
return;
}
+ if (gnc_commodity_is_currency(from) && gnc_commodity_is_currency(to))
+ {
+ if (value.num < value.denom)
+ {
+ value = swap_commodities(&from, &to, value);
+ }
+ value = gnc_numeric_convert(value, CURRENCY_DENOM,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ }
+ else if (gnc_commodity_is_currency(from) || gnc_commodity_is_currency(to))
+ {
+ int scu;
+ if (gnc_commodity_is_currency(from))
+ value = swap_commodities(&from, &to, value);
+ scu = gnc_commodity_get_fraction (to);
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ }
price = gnc_price_create (xferData->book);
gnc_price_begin_edit (price);
gnc_price_set_commodity (price, from);
diff --git a/src/register/ledger-core/split-register.c b/src/register/ledger-core/split-register.c
index aef5c6f..3cf90cc 100644
--- a/src/register/ledger-core/split-register.c
+++ b/src/register/ledger-core/split-register.c
@@ -64,9 +64,9 @@ static QofLogModule log_module = GNC_MOD_LEDGER;
static CursorClass copied_class = CURSOR_CLASS_NONE;
static SCM copied_item = SCM_UNDEFINED;
static GncGUID copied_leader_guid;
-static const int PRECISION = 1000000;
-
-
+/* A denominator representing number of digits to the right of the decimal point
+ * displayed in a price cell. */
+static int PRICE_CELL_DENOM = 1000000;
/** static prototypes *****************************************************/
static gboolean gnc_split_register_save_to_scm (SplitRegister *reg,
@@ -2053,6 +2053,7 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
gnc_commodity *curr = xaccTransGetCurrency (trans);
GNCPrice *price;
gnc_numeric price_value;
+ int scu = gnc_commodity_get_fraction(curr);
Timespec ts;
BasicCell *cell = gnc_table_layout_get_cell (reg->table->layout, DATE_CELL);
@@ -2073,10 +2074,10 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
price = gnc_pricedb_lookup_day (pricedb, curr, comm, ts);
if (price)
{
- price_value = gnc_numeric_div (gnc_numeric_create(1, 1),
- gnc_price_get_value(price),
- GNC_DENOM_AUTO,
- GNC_HOW_DENOM_REDUCE);
+/* It might be better to raise an error here: We shouldn't be creating
+ * currency->commodity prices.
+ */
+ price_value = gnc_numeric_invert(gnc_price_get_value(price));
}
}
if (price)
@@ -2092,9 +2093,15 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
return;
}
if (!gnc_numeric_eq(price_value, gnc_price_get_value(price)))
- value = gnc_numeric_div (gnc_numeric_create(1, 1), value,
- PRECISION, GNC_HOW_DENOM_REDUCE);
-
+ {
+ value = gnc_numeric_invert(value);
+ scu = gnc_commodity_get_fraction(comm);
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ }
+ else
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
gnc_price_begin_edit (price);
gnc_price_set_time (price, ts);
gnc_price_set_source (price, PRICE_SOURCE_SPLIT_REG);
@@ -2104,6 +2111,8 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
return;
}
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
price = gnc_price_create (book);
gnc_price_begin_edit (price);
gnc_price_set_commodity (price, comm);
@@ -2589,7 +2598,8 @@ gnc_split_register_config_cells (SplitRegister *reg)
/* Use 6 decimal places for prices and "exchange rates" */
gnc_price_cell_set_fraction
((PriceCell *)
- gnc_table_layout_get_cell (reg->table->layout, PRIC_CELL), PRECISION);
+ gnc_table_layout_get_cell (reg->table->layout, PRIC_CELL),
+ PRICE_CELL_DENOM);
/* Initialize shares and share balance cells */
gnc_price_cell_set_print_info
commit c7c97be684186bc4cfe90c9759cf838b4b6aaa74
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Aug 28 19:25:35 2015 +0100
Rename _gnc_xfer_dialog_set_exchange_rate and use it consistently.
_gnc_xfer_dialog_set_price_edit says what we're actually setting.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 30c0dc8..0bfa185 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -160,6 +160,7 @@ static Account *gnc_transfer_dialog_get_selected_account (XferDialog *dialog,
static void gnc_transfer_dialog_set_selected_account (XferDialog *dialog,
Account *account,
XferDirection direction);
+static void _gnc_xfer_dialog_set_price_edit(XferDialog*, gnc_numeric);
void gnc_xfer_description_insert_cb(GtkEditable *editable,
const gchar *insert_text,
@@ -259,7 +260,7 @@ gnc_xfer_dialog_update_price (XferDialog *xferData)
}
/* and set the price entry */
- gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (xferData->price_edit), price_value);
+ _gnc_xfer_dialog_set_price_edit(xferData, price_value);
/* And then update the to_amount */
gnc_xfer_update_to_amount (xferData);
@@ -313,9 +314,7 @@ gnc_xfer_dialog_set_price_auto (XferDialog *xferData,
if (!currency_active)
{
GtkEntry *entry;
-
- gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit),
- gnc_numeric_zero ());
+ _gnc_xfer_dialog_set_price_edit(xferData, gnc_numeric_zero());
entry = GTK_ENTRY(gnc_amount_edit_gtk_entry
(GNC_AMOUNT_EDIT(xferData->price_edit)));
gtk_entry_set_text(entry, "");
@@ -1338,16 +1337,16 @@ void gnc_xfer_dialog_set_date_sensitive(XferDialog *xferData,
}
void
-gnc_xfer_dialog_set_exchange_rate(XferDialog *xferData, gnc_numeric exchange_rate)
+_gnc_xfer_dialog_set_price_edit(XferDialog *xferData, gnc_numeric price_value)
{
if (xferData == NULL)
return;
- if (gnc_numeric_zero_p (exchange_rate))
+ if (gnc_numeric_zero_p (price_value))
return;
gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (xferData->price_edit),
- exchange_rate);
+ price_value);
gnc_xfer_update_to_amount (xferData);
}
@@ -1770,7 +1769,7 @@ gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData)
if (prc)
{
rate = gnc_price_get_value (prc);
- gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit), rate);
+ _gnc_xfer_dialog_set_price_edit(xferData, rate);
gnc_price_unref (prc);
have_price = TRUE;
}
@@ -1781,9 +1780,9 @@ gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData)
prc = gnc_pricedb_lookup_latest (xferData->pricedb, to, from);
if (prc)
{
- gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit), rate);
/* FIXME: We probably want to swap the result price's to and from, not invert the price. */
rate = gnc_numeric_invert(gnc_price_get_value (prc));
+ _gnc_xfer_dialog_set_price_edit(xferData, rate);
gnc_price_unref (prc);
have_price = TRUE;
}
@@ -2424,7 +2423,7 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
*/
/* Set the exchange rate */
- gnc_xfer_dialog_set_exchange_rate(xfer, *exch_rate);
+ _gnc_xfer_dialog_set_price_edit(xfer, *exch_rate);
/* and run it... */
if (gnc_xfer_dialog_run_until_done(xfer) == FALSE)
@@ -2434,7 +2433,6 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
* it back now...
*/
if (swap_amounts)
- *exch_rate = gnc_numeric_div(gnc_numeric_create(1, 1), *exch_rate,
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+ *exch_rate = gnc_numeric_invert(*exch_rate);
return FALSE;
}
commit 73233a5e2e93f96f73ae60c314e58e1280bb9641
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Aug 28 19:21:37 2015 +0100
Provide gnc_numeric_invert() convenience function.
Clearer and faster than dividing into 1/1.
diff --git a/src/app-utils/gnc-sx-instance-model.c b/src/app-utils/gnc-sx-instance-model.c
index 560fe79..cc7dbbf 100644
--- a/src/app-utils/gnc-sx-instance-model.c
+++ b/src/app-utils/gnc-sx-instance-model.c
@@ -1170,9 +1170,9 @@ create_each_transaction_helper(Transaction *template_txn, void *user_data)
}
else
{
- exchange = gnc_numeric_div(gnc_numeric_create(1,1),
- gnc_price_get_value(price),
- 1000, GNC_HOW_RND_ROUND_HALF_UP);
+ exchange = gnc_numeric_invert(gnc_price_get_value(price));
+ exchange = gnc_numeric_convert(exchange, 1000,
+ GNC_HOW_RND_ROUND_HALF_UP);
}
}
else
@@ -1779,4 +1779,3 @@ GHashTable* gnc_sx_all_instantiate_cashflow_all(GDate range_start, GDate range_e
result_map, NULL);
return result_map;
}
-
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index aed2b3f..30c0dc8 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -250,8 +250,7 @@ gnc_xfer_dialog_update_price (XferDialog *xferData)
{
PINFO("Found reverse price: 1 %s = %f %s", gnc_commodity_get_mnemonic(to),
gnc_numeric_to_double(price_value), gnc_commodity_get_mnemonic(from));
- price_value = gnc_numeric_div (gnc_numeric_create (1, 1), price_value,
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+ price_value = gnc_numeric_invert(price_value);
}
else
{
@@ -910,8 +909,7 @@ gnc_xfer_dialog_update_conv_info (XferDialog *xferData)
gtk_label_set_text(GTK_LABEL(xferData->conv_forward), string);
g_free(string);
- rate = gnc_numeric_div(gnc_numeric_create (1, 1), rate,
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+ rate = gnc_numeric_invert(rate);
string = g_strdup_printf("1 %s = %f %s", to_mnemonic,
gnc_numeric_to_double(rate), from_mnemonic);
gtk_label_set_text(GTK_LABEL(xferData->conv_reverse), string);
@@ -1508,8 +1506,7 @@ swap_amount (gnc_commodity *from, gnc_commodity *to, gnc_numeric *value,
tmp_amt = from_amt;
from_amt = to_amt;
to_amt = tmp_amt;
- *value = gnc_numeric_div (gnc_numeric_create(1, 1), *value,
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+ *value = gnc_numeric_invert (*value);
}
static void
create_price(XferDialog *xferData, Timespec ts)
@@ -1542,12 +1539,8 @@ create_price(XferDialog *xferData, Timespec ts)
{
price = gnc_pricedb_lookup_day (xferData->pricedb, to, from, ts);
if (price)
- {
- price_value = gnc_numeric_div (gnc_numeric_create(1, 1),
- gnc_price_get_value(price),
- GNC_DENOM_AUTO,
- GNC_HOW_DENOM_REDUCE);
- }
+
+ price_value = gnc_numeric_invert(gnc_price_get_value(price));
}
if (price)
@@ -1566,9 +1559,10 @@ create_price(XferDialog *xferData, Timespec ts)
return;
}
if (!gnc_numeric_eq(price_value, gnc_price_get_value(price)))
- value = gnc_numeric_div (gnc_numeric_create(1, 1), value,
- PRECISION, GNC_HOW_DENOM_REDUCE);
-
+ {
+ value = gnc_numeric_invert(value);
+ value = gnc_numeric_convert(value, PRECISION, GNC_HOW_DENOM_REDUCE);
+ }
gnc_price_begin_edit (price);
gnc_price_set_time (price, ts);
gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
@@ -1787,10 +1781,9 @@ gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData)
prc = gnc_pricedb_lookup_latest (xferData->pricedb, to, from);
if (prc)
{
- rate = gnc_numeric_div (gnc_numeric_create (1, 1), gnc_price_get_value (prc),
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
-
gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit), rate);
+/* FIXME: We probably want to swap the result price's to and from, not invert the price. */
+ rate = gnc_numeric_invert(gnc_price_get_value (prc));
gnc_price_unref (prc);
have_price = TRUE;
}
@@ -2396,9 +2389,9 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
gnc_numeric rate = xaccTransGetAccountConvRate(txn, reg_acc);
/* XXX: should we tell the user we've done the conversion? */
- amount = gnc_numeric_div(
- amount, rate,
- gnc_commodity_get_fraction(txn_cur), GNC_HOW_DENOM_REDUCE);
+ amount = gnc_numeric_div(amount, rate,
+ gnc_commodity_get_fraction(txn_cur),
+ GNC_HOW_DENOM_REDUCE);
}
/* enter the accounts */
@@ -2407,8 +2400,7 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
gnc_xfer_dialog_select_to_currency(xfer, txn_cur);
gnc_xfer_dialog_select_from_currency(xfer, xfer_com);
if (!gnc_numeric_zero_p(*exch_rate))
- *exch_rate = gnc_numeric_div(gnc_numeric_create(1, 1), *exch_rate,
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+ *exch_rate = gnc_numeric_invert(*exch_rate);
amount = gnc_numeric_neg(amount);
}
else
diff --git a/src/libqof/qof/gnc-numeric.h b/src/libqof/qof/gnc-numeric.h
index bcb70f1..b833753 100644
--- a/src/libqof/qof/gnc-numeric.h
+++ b/src/libqof/qof/gnc-numeric.h
@@ -504,6 +504,16 @@ gnc_numeric gnc_numeric_reduce(gnc_numeric n);
********************************************************************/
gboolean gnc_numeric_to_decimal(gnc_numeric * a,
guint8 * max_decimal_places);
+
+/** Invert a gnc_numeric.
+ * Much faster than dividing 1 by it.
+ * @param num The number to be inverted
+ * @return a gnc_numeric that is the inverse of num
+ */
+inline gnc_numeric gnc_numeric_invert (gnc_numeric num)
+{
+ return gnc_numeric_create (num.num, num.denom);
+}
/** @} */
/** @name GValue
commit 3a51c0d5c1ce654cf07a3eba22783411dfc5d128
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Aug 28 18:40:01 2015 +0100
Use price_value when referring to a gnc_numeric.
Price and prc are for gnc_price*.
For clarity.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index c180283..aed2b3f 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -180,7 +180,7 @@ void gnc_xfer_dialog_close_cb(GtkDialog *dialog, gpointer data);
/** Implementations **********************************************/
static gnc_numeric
-gnc_xfer_dialog_compute_price (XferDialog *xferData)
+gnc_xfer_dialog_compute_price_value (XferDialog *xferData)
{
gnc_numeric from_amt, to_amt;
g_return_val_if_fail (xferData != NULL, gnc_numeric_error (GNC_ERROR_ARG));
@@ -196,7 +196,7 @@ static void
gnc_xfer_dialog_update_price (XferDialog *xferData)
{
GNCPrice *prc;
- gnc_numeric price;
+ gnc_numeric price_value;
Timespec date;
gnc_commodity *from = xferData->from_commodity;
gnc_commodity *to = xferData->to_commodity;
@@ -245,22 +245,22 @@ gnc_xfer_dialog_update_price (XferDialog *xferData)
return;
/* grab the price from the pricedb */
- price = gnc_price_get_value (prc);
+ price_value = gnc_price_get_value (prc);
if (reverse)
{
PINFO("Found reverse price: 1 %s = %f %s", gnc_commodity_get_mnemonic(to),
- gnc_numeric_to_double(price), gnc_commodity_get_mnemonic(from));
- price = gnc_numeric_div (gnc_numeric_create (1, 1), price,
+ gnc_numeric_to_double(price_value), gnc_commodity_get_mnemonic(from));
+ price_value = gnc_numeric_div (gnc_numeric_create (1, 1), price_value,
GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
}
else
{
PINFO("Found price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
- gnc_numeric_to_double(price), gnc_commodity_get_mnemonic(to));
+ gnc_numeric_to_double(price_value), gnc_commodity_get_mnemonic(to));
}
/* and set the price entry */
- gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (xferData->price_edit), price);
+ gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (xferData->price_edit), price_value);
/* And then update the to_amount */
gnc_xfer_update_to_amount (xferData);
@@ -309,7 +309,7 @@ gnc_xfer_dialog_set_price_auto (XferDialog *xferData,
{
gnc_numeric from_rate;
gnc_numeric to_rate;
- gnc_numeric price;
+ gnc_numeric price_value;
if (!currency_active)
{
@@ -339,9 +339,9 @@ gnc_xfer_dialog_set_price_auto (XferDialog *xferData,
if (gnc_numeric_zero_p (from_rate) || gnc_numeric_zero_p (to_rate))
gnc_xfer_dialog_update_price (xferData);
- price = gnc_numeric_div (to_rate, from_rate, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+ price_value = gnc_numeric_div (to_rate, from_rate, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
- gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(xferData->price_edit), price);
+ gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(xferData->price_edit), price_value);
gnc_xfer_update_to_amount (xferData);
}
@@ -938,7 +938,7 @@ static void
gnc_xfer_update_to_amount (XferDialog *xferData)
{
GNCAmountEdit *amount_edit, *price_edit, *to_amount_edit;
- gnc_numeric price, to_amount;
+ gnc_numeric price_value, to_amount;
Account *account;
int scu = 0;
@@ -961,11 +961,11 @@ gnc_xfer_update_to_amount (XferDialog *xferData)
/* Determine the amount to transfer. */
if (!gnc_amount_edit_evaluate(price_edit) ||
- gnc_numeric_zero_p(price = gnc_amount_edit_get_amount(price_edit)))
+ gnc_numeric_zero_p(price_value = gnc_amount_edit_get_amount(price_edit)))
to_amount = gnc_numeric_zero();
else
to_amount = gnc_numeric_mul(gnc_amount_edit_get_amount(amount_edit),
- price, scu, GNC_HOW_RND_ROUND_HALF_UP);
+ price_value, scu, GNC_HOW_RND_ROUND_HALF_UP);
/* Update the dialog. */
gnc_amount_edit_set_amount(to_amount_edit, to_amount);
@@ -1004,7 +1004,7 @@ gnc_xfer_to_amount_update_cb(GtkWidget *widget, GdkEventFocus *event,
gpointer data)
{
XferDialog *xferData = data;
- gnc_numeric price;
+ gnc_numeric price_value;
Account *account;
account = gnc_transfer_dialog_get_selected_account (xferData, XFER_DIALOG_TO);
@@ -1013,9 +1013,11 @@ gnc_xfer_to_amount_update_cb(GtkWidget *widget, GdkEventFocus *event,
gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->to_amount_edit));
- price = gnc_xfer_dialog_compute_price(xferData);
- price = gnc_numeric_convert (price, PRECISION, GNC_HOW_RND_ROUND_HALF_UP);
- gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit), price);
+ price_value = gnc_xfer_dialog_compute_price_value(xferData);
+ price_value = gnc_numeric_convert (price_value, PRECISION,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit),
+ price_value);
gnc_xfer_dialog_update_conv_info(xferData);
return FALSE;
@@ -1656,7 +1658,7 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
if (xferData->exch_rate)
{
- gnc_numeric price;
+ gnc_numeric price_value;
/* If we've got the price-button set, then make sure we update the
* to-amount before we use it.
@@ -1664,8 +1666,8 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(xferData->price_radio)))
gnc_xfer_update_to_amount(xferData);
- price = gnc_xfer_dialog_compute_price(xferData);
- *(xferData->exch_rate) = gnc_numeric_abs(price);
+ price_value = gnc_xfer_dialog_compute_price_value(xferData);
+ *(xferData->exch_rate) = gnc_numeric_abs(price_value);
}
else
create_transaction (xferData, &ts, from_account, to_account,
commit 06f70bad61ea7205128b7aeb2ff49550b9139a60
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Aug 25 11:17:07 2015 +0100
Price-quotes: Modify quotes on same day instead of creating new ones.
We can use only one per day so no point in keeping a bunch of them.
Finance::Quote prices always overwrite user prices.
diff --git a/src/scm/price-quotes.scm b/src/scm/price-quotes.scm
index 7daacd0..c6a2405 100644
--- a/src/scm/price-quotes.scm
+++ b/src/scm/price-quotes.scm
@@ -370,7 +370,11 @@
(string? currency-str)
(gnc-commodity-table-lookup commodity-table
"ISO4217"
- (string-upcase currency-str)))))
+ (string-upcase currency-str))))
+ (pricedb (gnc-pricedb-get-db book))
+ (saved-price #f)
+ (commodity-str (gnc-commodity-get-printname commodity))
+ )
(or-map (lambda (price-sym)
(let ((p (assq-ref quote-data price-sym)))
@@ -403,27 +407,44 @@
(if (not (and commodity currency gnc-time price price-type))
(string-append
currency-str ":" (gnc-commodity-get-mnemonic commodity))
- (let ((gnc-price (gnc-price-create book)))
- (if (not gnc-price)
- (string-append
- currency-str ":" (gnc-commodity-get-mnemonic commodity))
- (begin
- (gnc-price-begin-edit gnc-price)
- (gnc-price-set-commodity gnc-price commodity)
- (gnc-price-set-currency gnc-price currency)
- (gnc-price-set-time gnc-price gnc-time)
- (gnc-price-set-source gnc-price "Finance::Quote")
- (gnc-price-set-typestr gnc-price price-type)
- (gnc-price-set-value gnc-price price)
- (gnc-price-commit-edit gnc-price)
- gnc-price))))))
+ (begin
+ (set! saved-price (gnc-pricedb-lookup-day pricedb
+ commodity currency
+ gnc-time))
+ (if (not (null? saved-price))
+ (begin
+ (gnc-price-begin-edit saved-price)
+ (gnc-price-set-time saved-price gnc-time)
+ (gnc-price-set-source saved-price "Finance::Quote")
+ (gnc-price-set-typestr saved-price price-type)
+ (gnc-price-set-value saved-price price)
+ (gnc-price-commit-edit saved-price)
+ #f)
+ (let ((gnc-price (gnc-price-create book)))
+ (if (not gnc-price)
+ (string-append
+ currency-str ":" (gnc-commodity-get-mnemonic commodity))
+ (begin
+ (gnc-price-begin-edit gnc-price)
+ (gnc-price-set-commodity gnc-price commodity)
+ (gnc-price-set-currency gnc-price currency)
+ (gnc-price-set-time gnc-price gnc-time)
+ (gnc-price-set-source gnc-price "Finance::Quote")
+ (gnc-price-set-typestr gnc-price price-type)
+ (gnc-price-set-value gnc-price price)
+ (gnc-price-commit-edit gnc-price)
+ gnc-price)))))
+ )))
(define (book-add-prices! book prices)
(let ((pricedb (gnc-pricedb-get-db book)))
(for-each
(lambda (price)
- (gnc-pricedb-add-price pricedb price)
- (gnc-price-unref price))
+ (if price
+ (begin
+ (gnc-pricedb-add-price pricedb price)
+ (gnc-price-unref price)
+ #f)))
prices)))
;; FIXME: uses of gnc:warn in here need to be cleaned up. Right
commit ea48ed882b35f94aa716e91a8a82418a91fb687e
Author: John Ralls <jralls at ceridwen.us>
Date: Sun Aug 23 12:17:23 2015 +0100
Edit split-based prices instead of adding.
For split-register and xfer-dialog generated prices if there's an existing
non-FQ price for the day, change it. If there's an F::Q quote for the day,
do nothing. Only add a price if there isn't one for the from/to
combination.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index ebc0097..c180283 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -86,7 +86,7 @@ struct _xferDialog
gnc_commodity *to_commodity;
QuickFill *qf; /* Quickfill on transfer descriptions,
- defaults to matching on the "From" account. */
+ defaults to matching on the "From" account. */
XferDirection quickfill; /* direction match on the account instead. */
@@ -1548,26 +1548,46 @@ create_price(XferDialog *xferData, Timespec ts)
}
}
- if (price && gnc_numeric_equal(value, price_value))
- {
- PINFO("Found price for %s in %s", gnc_commodity_get_mnemonic(from),
- gnc_commodity_get_mnemonic(to));
- }
- else
+ if (price)
{
- price = gnc_price_create (xferData->book);
+ if (gnc_numeric_equal(value, price_value))
+ {
+ PINFO("Found price for %s in %s", gnc_commodity_get_mnemonic(from),
+ gnc_commodity_get_mnemonic(to));
+ gnc_price_unref (price);
+ return;
+ }
+ if (strcmp (gnc_price_get_source(price), PRICE_SOURCE_FQ) == 0)
+ {
+ PINFO("Existing price is from Finance::Quote, so won't supersede.");
+ gnc_price_unref (price);
+ return;
+ }
+ if (!gnc_numeric_eq(price_value, gnc_price_get_value(price)))
+ value = gnc_numeric_div (gnc_numeric_create(1, 1), value,
+ PRECISION, GNC_HOW_DENOM_REDUCE);
+
gnc_price_begin_edit (price);
- gnc_price_set_commodity (price, from);
- gnc_price_set_currency (price, to);
gnc_price_set_time (price, ts);
gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
gnc_price_set_value (price, value);
- gnc_pricedb_add_price (xferData->pricedb, price);
gnc_price_commit_edit (price);
- PINFO("Created price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
+ PINFO("Modified price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
gnc_numeric_to_double(value), gnc_commodity_get_mnemonic(to));
+ gnc_price_unref (price);
+ return;
}
-
+ price = gnc_price_create (xferData->book);
+ gnc_price_begin_edit (price);
+ gnc_price_set_commodity (price, from);
+ gnc_price_set_currency (price, to);
+ gnc_price_set_time (price, ts);
+ gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
+ gnc_price_set_value (price, value);
+ gnc_pricedb_add_price (xferData->pricedb, price);
+ gnc_price_commit_edit (price);
+ PINFO("Created price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
+ gnc_numeric_to_double(value), gnc_commodity_get_mnemonic(to));
gnc_price_unref (price);
}
diff --git a/src/register/ledger-core/split-register.c b/src/register/ledger-core/split-register.c
index 119a459..aef5c6f 100644
--- a/src/register/ledger-core/split-register.c
+++ b/src/register/ledger-core/split-register.c
@@ -64,6 +64,7 @@ static QofLogModule log_module = GNC_MOD_LEDGER;
static CursorClass copied_class = CURSOR_CLASS_NONE;
static SCM copied_item = SCM_UNDEFINED;
static GncGUID copied_leader_guid;
+static const int PRECISION = 1000000;
/** static prototypes *****************************************************/
@@ -2078,9 +2079,31 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
GNC_HOW_DENOM_REDUCE);
}
}
-
- if (price && gnc_numeric_equal(value, price_value))
+ if (price)
+ {
+ if (gnc_numeric_equal(value, price_value))
+ {
+ gnc_price_unref (price);
+ return;
+ }
+ if (strcmp (gnc_price_get_source(price), PRICE_SOURCE_FQ) == 0)
+ {
+ gnc_price_unref(price);
+ return;
+ }
+ if (!gnc_numeric_eq(price_value, gnc_price_get_value(price)))
+ value = gnc_numeric_div (gnc_numeric_create(1, 1), value,
+ PRECISION, GNC_HOW_DENOM_REDUCE);
+
+ gnc_price_begin_edit (price);
+ gnc_price_set_time (price, ts);
+ gnc_price_set_source (price, PRICE_SOURCE_SPLIT_REG);
+ gnc_price_set_value (price, value);
+ gnc_price_commit_edit (price);
+ gnc_price_unref (price);
return;
+ }
+
price = gnc_price_create (book);
gnc_price_begin_edit (price);
gnc_price_set_commodity (price, comm);
@@ -2566,7 +2589,7 @@ gnc_split_register_config_cells (SplitRegister *reg)
/* Use 6 decimal places for prices and "exchange rates" */
gnc_price_cell_set_fraction
((PriceCell *)
- gnc_table_layout_get_cell (reg->table->layout, PRIC_CELL), 1000000);
+ gnc_table_layout_get_cell (reg->table->layout, PRIC_CELL), PRECISION);
/* Initialize shares and share balance cells */
gnc_price_cell_set_print_info
commit 0b03328143b030871dfeaa034d151c3667878753
Author: John Ralls <jralls at ceridwen.us>
Date: Sun Aug 23 11:44:24 2015 +0100
Check for an existing price before adding one in split_reg.
To make the behavior the same as in xfer_dialog.
diff --git a/src/register/ledger-core/split-register.c b/src/register/ledger-core/split-register.c
index fc4f587..119a459 100644
--- a/src/register/ledger-core/split-register.c
+++ b/src/register/ledger-core/split-register.c
@@ -2051,8 +2051,9 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
gnc_commodity *comm = xaccAccountGetCommodity (account);
gnc_commodity *curr = xaccTransGetCurrency (trans);
GNCPrice *price;
+ gnc_numeric price_value;
Timespec ts;
- BasicCell *cell;
+ BasicCell *cell = gnc_table_layout_get_cell (reg->table->layout, DATE_CELL);
/* Only record the price for account types that don't have a
* "rate" cell. They'll get handled later by
@@ -2060,8 +2061,26 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
*/
if (gnc_split_reg_has_rate_cell (reg->type))
return;
- cell = gnc_table_layout_get_cell (reg->table->layout, DATE_CELL);
gnc_date_cell_get_date ((DateCell*)cell, &ts);
+ price = gnc_pricedb_lookup_day (pricedb, comm, curr, ts);
+ if (price)
+ {
+ price_value = gnc_price_get_value(price);
+ }
+ else
+ {
+ price = gnc_pricedb_lookup_day (pricedb, curr, comm, ts);
+ if (price)
+ {
+ price_value = gnc_numeric_div (gnc_numeric_create(1, 1),
+ gnc_price_get_value(price),
+ GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_REDUCE);
+ }
+ }
+
+ if (price && gnc_numeric_equal(value, price_value))
+ return;
price = gnc_price_create (book);
gnc_price_begin_edit (price);
gnc_price_set_commodity (price, comm);
commit c6a67f4eac5f7e95b9637c2c163260fff3f7cc53
Author: John Ralls <jralls at ceridwen.us>
Date: Sun Aug 23 11:06:14 2015 +0100
In the transfer dialog use the price_edit value for the saved price.
Instead of computing it separately and differently from to_amt and from_amt.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 08e6ab0..ebc0097 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1523,16 +1523,7 @@ create_price(XferDialog *xferData, Timespec ts)
if (gnc_is_euro_currency (from) && gnc_is_euro_currency (to))
return;
- from_amt =
- gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->amount_edit));
- to_amt =
- gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->to_amount_edit));
-
- /* compute the price -- maybe we need to swap? */
- value = gnc_numeric_div(to_amt, from_amt, GNC_DENOM_AUTO,
- GNC_HOW_DENOM_REDUCE);
- value = gnc_numeric_abs (value);
-
+ value = gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->price_edit));
/* Try to be consistent about how quotes are installed. */
if (from == gnc_default_currency() ||
((to != gnc_default_currency()) &&
@@ -1557,20 +1548,7 @@ create_price(XferDialog *xferData, Timespec ts)
}
}
- /* See if we found a good enough price */
- if (price)
- {
- int scu = gnc_commodity_get_fraction (to);
- if (!gnc_numeric_equal (gnc_numeric_mul (from_amt, price_value,
- scu, GNC_HOW_RND_ROUND_HALF_UP),
- to_amt))
- {
- gnc_price_unref (price);
- price = NULL;
- }
- }
-
- if (price)
+ if (price && gnc_numeric_equal(value, price_value))
{
PINFO("Found price for %s in %s", gnc_commodity_get_mnemonic(from),
gnc_commodity_get_mnemonic(to));
commit 407d61cbb64d3232bc56e74dbb1e95eff9cf5ef8
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Aug 22 10:48:24 2015 +0100
Fix up whitespace in dialog-transfer.c.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 3715c7b..08e6ab0 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -69,61 +69,60 @@ static QofLogModule log_module = GNC_MOD_GUI;
struct _xferDialog
{
- GtkWidget * dialog;
-
- GtkWidget * amount_edit;
- GtkWidget * date_entry;
- GtkWidget * num_entry;
- GtkWidget * description_entry;
- GtkWidget * memo_entry;
- GtkWidget * conv_forward;
- GtkWidget * conv_reverse;
-
- GtkWidget * from_window;
+ GtkWidget *dialog;
+ GtkWidget *amount_edit;
+ GtkWidget *date_entry;
+ GtkWidget *num_entry;
+ GtkWidget *description_entry;
+ GtkWidget *memo_entry;
+ GtkWidget *conv_forward;
+ GtkWidget *conv_reverse;
+
+ GtkWidget *from_window;
GtkTreeView * from_tree_view;
- gnc_commodity * from_commodity;
- GtkWidget * to_window;
- GtkTreeView * to_tree_view;
- gnc_commodity * to_commodity;
+ gnc_commodity *from_commodity;
+ GtkWidget *to_window;
+ GtkTreeView *to_tree_view;
+ gnc_commodity *to_commodity;
- QuickFill * qf; /* Quickfill on transfer descriptions,
- defaults to matching on the "From" account. */
+ QuickFill *qf; /* Quickfill on transfer descriptions,
+ defaults to matching on the "From" account. */
- XferDirection quickfill; /* direction match on the account instead. */
+ XferDirection quickfill; /* direction match on the account instead. */
/* stored data for the description quickfill selection function */
gint desc_start_selection;
gint desc_end_selection;
guint desc_selection_source_id;
- GtkWidget * transferinfo_label;
+ GtkWidget *transferinfo_label;
- GtkWidget * from_transfer_label;
- GtkWidget * to_transfer_label;
+ GtkWidget *from_transfer_label;
+ GtkWidget *to_transfer_label;
- GtkWidget * from_currency_label;
- GtkWidget * to_currency_label;
+ GtkWidget *from_currency_label;
+ GtkWidget *to_currency_label;
- GtkWidget * from_show_button;
- GtkWidget * to_show_button;
+ GtkWidget *from_show_button;
+ GtkWidget *to_show_button;
- GtkWidget * curr_xfer_table;
+ GtkWidget *curr_xfer_table;
- GtkWidget * price_edit;
- GtkWidget * to_amount_edit;
+ GtkWidget *price_edit;
+ GtkWidget *to_amount_edit;
- GtkWidget * price_radio;
- GtkWidget * amount_radio;
+ GtkWidget *price_radio;
+ GtkWidget *amount_radio;
- GtkWidget * fetch_button;
+ GtkWidget *fetch_button;
- QofBook * book;
- GNCPriceDB * pricedb;
+ QofBook *book;
+ GNCPriceDB *pricedb;
/* Where to store the "exchange_rate" at exit (in lieu of
* creating a transaction)
*/
- gnc_numeric * exch_rate;
+ gnc_numeric *exch_rate;
/* Callback function to notify of the newly created Transaction */
gnc_xfer_dialog_cb transaction_cb;
@@ -157,10 +156,10 @@ static void gnc_xfer_update_to_amount (XferDialog *xferData);
static void gnc_xfer_dialog_update_conv_info(XferDialog *xferData);
static Account *gnc_transfer_dialog_get_selected_account (XferDialog *dialog,
- XferDirection direction);
+ XferDirection direction);
static void gnc_transfer_dialog_set_selected_account (XferDialog *dialog,
- Account *account,
- XferDirection direction);
+ Account *account,
+ XferDirection direction);
void gnc_xfer_description_insert_cb(GtkEditable *editable,
const gchar *insert_text,
@@ -168,11 +167,11 @@ void gnc_xfer_description_insert_cb(GtkEditable *editable,
gint *start_pos,
XferDialog *xferData);
gboolean gnc_xfer_description_key_press_cb( GtkEntry *entry,
- GdkEventKey *event,
- XferDialog *xferData );
+ GdkEventKey *event,
+ XferDialog *xferData );
void gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData);
gboolean gnc_xfer_dialog_inc_exp_filter_func (Account *account,
- gpointer data);
+ gpointer data);
void price_amount_radio_toggled_cb(GtkToggleButton *togglebutton, gpointer data);
void gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data);
@@ -231,14 +230,14 @@ gnc_xfer_dialog_update_price (XferDialog *xferData)
{
/* Didn't find one on the same day, look for nearest in time */
prc = gnc_pricedb_lookup_nearest_in_time (xferData->pricedb, from,
- to, date);
+ to, date);
reverse = FALSE;
}
if (!prc)
{
prc = gnc_pricedb_lookup_nearest_in_time (xferData->pricedb, to,
- from, date);
+ from, date);
reverse = TRUE;
}
@@ -328,7 +327,7 @@ gnc_xfer_dialog_set_price_auto (XferDialog *xferData,
}
if (!gnc_is_euro_currency (from_currency) ||
- !gnc_is_euro_currency (to_currency))
+ !gnc_is_euro_currency (to_currency))
{
gnc_xfer_dialog_update_price (xferData);
return;
@@ -363,8 +362,8 @@ gnc_xfer_dialog_curr_acct_activate(XferDialog *xferData)
curr_active = (xferData->exch_rate ||
((from_account != NULL) && (to_account != NULL)))
- && !gnc_commodity_equiv(xferData->from_commodity,
- xferData->to_commodity);
+ && !gnc_commodity_equiv(xferData->from_commodity,
+ xferData->to_commodity);
gtk_widget_set_sensitive(xferData->curr_xfer_table, curr_active);
gtk_widget_set_sensitive(xferData->price_edit,
@@ -441,7 +440,7 @@ gnc_xfer_dialog_reload_quickfill( XferDialog *xferData )
static void
gnc_xfer_dialog_from_tree_selection_changed_cb (GtkTreeSelection *selection,
- gpointer data)
+ gpointer data)
{
XferDialog *xferData = data;
GNCPrintAmountInfo print_info;
@@ -541,7 +540,7 @@ gnc_xfer_dialog_fill_tree_view(XferDialog *xferData,
g_return_if_fail (xferData != NULL);
use_accounting_labels = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL,
- GNC_PREF_ACCOUNTING_LABELS);
+ GNC_PREF_ACCOUNTING_LABELS);
/* In "normal" mode (non accounting terms) the account where the
* money comes from is displayed on the left side and the account
@@ -557,20 +556,20 @@ gnc_xfer_dialog_fill_tree_view(XferDialog *xferData,
if (use_accounting_labels)
{
button = GTK_WIDGET(gtk_builder_get_object (builder,
- (direction == XFER_DIALOG_TO) ?
- "left_show_button" : "right_show_button"));
+ (direction == XFER_DIALOG_TO) ?
+ "left_show_button" : "right_show_button"));
scroll_win = GTK_WIDGET(gtk_builder_get_object (builder,
- (direction == XFER_DIALOG_TO) ?
- "left_trans_window" : "right_trans_window"));
+ (direction == XFER_DIALOG_TO) ?
+ "left_trans_window" : "right_trans_window"));
}
else
{
button = GTK_WIDGET(gtk_builder_get_object (builder,
- (direction == XFER_DIALOG_TO) ?
- "right_show_button" : "left_show_button"));
+ (direction == XFER_DIALOG_TO) ?
+ "right_show_button" : "left_show_button"));
scroll_win = GTK_WIDGET(gtk_builder_get_object (builder,
- (direction == XFER_DIALOG_TO) ?
- "right_trans_window" : "left_trans_window"));
+ (direction == XFER_DIALOG_TO) ?
+ "right_trans_window" : "left_trans_window"));
}
@@ -686,7 +685,7 @@ gnc_xfer_dialog_quickfill( XferDialog *xferData )
*/
if ( gnc_numeric_zero_p(
- gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->amount_edit))))
+ gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->amount_edit))))
{
gnc_numeric amt;
DEBUG("updating amount");
@@ -718,7 +717,7 @@ gnc_xfer_dialog_quickfill( XferDialog *xferData )
* and select that account in the appropriate account tree.
*/
if ( ( other = xaccSplitGetOtherSplit( split ) ) &&
- ( other_acct = xaccSplitGetAccount( other ) ) )
+ ( other_acct = xaccSplitGetAccount( other ) ) )
{
GNCAccountType other_type;
GtkWidget *other_button;
@@ -804,8 +803,8 @@ gnc_xfer_description_insert_cb(GtkEditable *editable,
g_free(prefix);
if ((match = gnc_quickfill_get_string_match(xferData->qf, new_text))
- && (match_str = gnc_quickfill_string(match))
- && ((match_str_len = strlen(match_str)) > new_text_len))
+ && (match_str = gnc_quickfill_string(match))
+ && ((match_str_len = strlen(match_str)) > new_text_len))
{
g_signal_handlers_block_matched (G_OBJECT (editable),
G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, xferData);
@@ -829,7 +828,7 @@ gnc_xfer_description_insert_cb(GtkEditable *editable,
xferData->desc_start_selection = *start_pos;
xferData->desc_end_selection = -1;
xferData->desc_selection_source_id = g_idle_add(idle_select_region,
- xferData);
+ xferData);
}
g_free(new_text);
}
@@ -848,25 +847,25 @@ gnc_xfer_description_key_press_cb( GtkEntry *entry,
ENTER(" ");
switch ( event->keyval )
{
- case GDK_Return:
- case GDK_KP_Enter:
- gnc_xfer_dialog_quickfill( xferData );
- /* NOT done with input, activate the default button of the dialog. */
- break;
-
- case GDK_Tab:
- case GDK_ISO_Left_Tab:
- if ( !( event->state & GDK_SHIFT_MASK) ) /* Complete on Tab,
- * but not Shift-Tab */
- {
+ case GDK_Return:
+ case GDK_KP_Enter:
gnc_xfer_dialog_quickfill( xferData );
- /* NOT done with input, though, since we need to focus to the next
- * field. Unselect the current field, though.
- */
- gtk_editable_select_region( GTK_EDITABLE(xferData->description_entry),
- 0, 0 );
- }
- break;
+ /* NOT done with input, activate the default button of the dialog. */
+ break;
+
+ case GDK_Tab:
+ case GDK_ISO_Left_Tab:
+ if ( !( event->state & GDK_SHIFT_MASK) ) /* Complete on Tab,
+ * but not Shift-Tab */
+ {
+ gnc_xfer_dialog_quickfill( xferData );
+ /* NOT done with input, though, since we need to focus to the next
+ * field. Unselect the current field, though.
+ */
+ gtk_editable_select_region( GTK_EDITABLE(xferData->description_entry),
+ 0, 0 );
+ }
+ break;
}
LEAVE("done=%d", done_with_input);
@@ -954,7 +953,7 @@ gnc_xfer_update_to_amount (XferDialog *xferData)
account = gnc_transfer_dialog_get_selected_account(xferData, XFER_DIALOG_TO);
if (account == NULL)
account = gnc_transfer_dialog_get_selected_account(xferData,
- XFER_DIALOG_FROM);
+ XFER_DIALOG_FROM);
if (account != NULL)
scu = xaccAccountGetCommoditySCU(account);
else if (xferData->to_commodity != NULL)
@@ -962,7 +961,7 @@ gnc_xfer_update_to_amount (XferDialog *xferData)
/* Determine the amount to transfer. */
if (!gnc_amount_edit_evaluate(price_edit) ||
- gnc_numeric_zero_p(price = gnc_amount_edit_get_amount(price_edit)))
+ gnc_numeric_zero_p(price = gnc_amount_edit_get_amount(price_edit)))
to_amount = gnc_numeric_zero();
else
to_amount = gnc_numeric_mul(gnc_amount_edit_get_amount(amount_edit),
@@ -1099,18 +1098,18 @@ gnc_xfer_dialog_lock_account_tree(XferDialog *xferData,
switch (direction)
{
- case XFER_DIALOG_FROM:
- tree_view = xferData->from_tree_view;
- scroll_win = xferData->from_window;
- show_button = xferData->from_show_button;
- break;
- case XFER_DIALOG_TO:
- tree_view = xferData->to_tree_view;
- scroll_win = xferData->to_window;
- show_button = xferData->to_show_button;
- break;
- default:
- return;
+ case XFER_DIALOG_FROM:
+ tree_view = xferData->from_tree_view;
+ scroll_win = xferData->from_window;
+ show_button = xferData->from_show_button;
+ break;
+ case XFER_DIALOG_TO:
+ tree_view = xferData->to_tree_view;
+ scroll_win = xferData->to_window;
+ show_button = xferData->to_show_button;
+ break;
+ default:
+ return;
}
gtk_widget_set_sensitive( GTK_WIDGET(tree_view), FALSE );
@@ -1199,7 +1198,7 @@ gnc_xfer_dialog_is_exchange_dialog (XferDialog *xferData,
g_return_if_fail(xferData);
ENTER("xferData=%p, exch_rate=%p (%s)", xferData, exch_rate,
exch_rate == NULL ? "NULL" : xaccPrintAmount(*exch_rate,
- gnc_default_print_info(FALSE)));
+ gnc_default_print_info(FALSE)));
gtk_widget_set_sensitive (xferData->amount_edit, FALSE);
gtk_widget_set_sensitive (xferData->date_entry, FALSE);
@@ -1233,15 +1232,15 @@ gnc_xfer_dialog_set_amount(XferDialog *xferData, gnc_numeric amount)
return;
account = gnc_transfer_dialog_get_selected_account (xferData,
- XFER_DIALOG_FROM);
+ XFER_DIALOG_FROM);
if (account == NULL)
account = gnc_transfer_dialog_get_selected_account (xferData,
- XFER_DIALOG_TO);
+ XFER_DIALOG_TO);
gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (xferData->amount_edit), amount);
}
void gnc_xfer_dialog_set_amount_sensitive(XferDialog *xferData,
- gboolean is_sensitive)
+ gboolean is_sensitive)
{
g_assert(xferData);
gtk_widget_set_sensitive(gnc_amount_edit_gtk_entry(GNC_AMOUNT_EDIT (xferData->amount_edit)), is_sensitive);
@@ -1252,9 +1251,9 @@ gnc_xfer_dialog_set_fetch_sensitive (GtkWidget *fetch)
{
if (gnc_quote_source_fq_installed ())
{
- gtk_widget_set_sensitive (fetch, TRUE);
- gtk_widget_set_tooltip_text (fetch, _("Retrieve the current online quote"));
- return;
+ gtk_widget_set_sensitive (fetch, TRUE);
+ gtk_widget_set_tooltip_text (fetch, _("Retrieve the current online quote"));
+ return;
}
gtk_widget_set_sensitive (fetch, FALSE);
gtk_widget_set_tooltip_text (fetch, _("Finance::Quote must be installed to enable this button."));
@@ -1508,7 +1507,7 @@ swap_amount (gnc_commodity *from, gnc_commodity *to, gnc_numeric *value,
from_amt = to_amt;
to_amt = tmp_amt;
*value = gnc_numeric_div (gnc_numeric_create(1, 1), *value,
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+ GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
}
static void
create_price(XferDialog *xferData, Timespec ts)
@@ -1808,7 +1807,7 @@ gnc_xfer_dialog_create(GtkWidget *parent, XferDialog *xferData)
gboolean use_accounting_labels;
use_accounting_labels = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL,
- GNC_PREF_ACCOUNTING_LABELS);
+ GNC_PREF_ACCOUNTING_LABELS);
ENTER(" ");
builder = gtk_builder_new();
@@ -2129,7 +2128,7 @@ gnc_xfer_dialog_set_to_account_label( XferDialog *xferData,
void
gnc_xfer_dialog_set_from_show_button_active( XferDialog *xferData,
- gboolean set_value )
+ gboolean set_value )
{
if ( xferData && xferData->from_show_button )
{
@@ -2140,7 +2139,7 @@ gnc_xfer_dialog_set_from_show_button_active( XferDialog *xferData,
void
gnc_xfer_dialog_set_to_show_button_active( XferDialog *xferData,
- gboolean set_value )
+ gboolean set_value )
{
if ( xferData && xferData->to_show_button )
{
@@ -2151,16 +2150,16 @@ gnc_xfer_dialog_set_to_show_button_active( XferDialog *xferData,
/* Add a button with a user-specified label and "clicked" callback */
void gnc_xfer_dialog_add_user_specified_button( XferDialog *xferData,
- const gchar *label,
- GCallback callback,
- gpointer user_data )
+ const gchar *label,
+ GCallback callback,
+ gpointer user_data )
{
if ( xferData && label && callback )
{
GtkBuilder *builder = g_object_get_data (G_OBJECT (xferData->dialog), "builder");
GtkWidget *button = gtk_button_new_with_label( label );
GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder,
- "transfermain-vbox" ));
+ "transfermain-vbox" ));
gtk_box_pack_end( GTK_BOX(box), button, FALSE, FALSE, 0 );
g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (callback), user_data);
gtk_widget_show( button );
@@ -2168,7 +2167,7 @@ void gnc_xfer_dialog_add_user_specified_button( XferDialog *xferData,
}
void gnc_xfer_dialog_toggle_currency_table( XferDialog *xferData,
- gboolean show_table )
+ gboolean show_table )
{
if (xferData && xferData->curr_xfer_table)
{
@@ -2211,8 +2210,8 @@ gboolean gnc_xfer_dialog_run_until_done( XferDialog *xferData )
* that's bad mojo whole gtk_dialog_run is still in control.
*/
count = g_signal_handlers_disconnect_by_func(dialog,
- gnc_xfer_dialog_response_cb,
- xferData);
+ gnc_xfer_dialog_response_cb,
+ xferData);
g_assert(count == 1);
while ( TRUE )
@@ -2269,22 +2268,22 @@ gnc_xfer_dialog_quickfill_to_account(XferDialog *xferData,
static Account *
gnc_transfer_dialog_get_selected_account (XferDialog *dialog,
- XferDirection direction)
+ XferDirection direction)
{
GtkTreeView *tree_view;
Account *account;
switch (direction)
{
- case XFER_DIALOG_FROM:
- tree_view = dialog->from_tree_view;
- break;
- case XFER_DIALOG_TO:
- tree_view = dialog->to_tree_view;
- break;
- default:
- g_assert_not_reached ();
- return NULL;
+ case XFER_DIALOG_FROM:
+ tree_view = dialog->from_tree_view;
+ break;
+ case XFER_DIALOG_TO:
+ tree_view = dialog->to_tree_view;
+ break;
+ default:
+ g_assert_not_reached ();
+ return NULL;
}
account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (tree_view));
@@ -2293,8 +2292,8 @@ gnc_transfer_dialog_get_selected_account (XferDialog *dialog,
static void
gnc_transfer_dialog_set_selected_account (XferDialog *dialog,
- Account *account,
- XferDirection direction)
+ Account *account,
+ XferDirection direction)
{
GtkTreeView *tree_view;
GtkCheckButton *show_button;
@@ -2305,17 +2304,17 @@ gnc_transfer_dialog_set_selected_account (XferDialog *dialog,
switch (direction)
{
- case XFER_DIALOG_FROM:
- tree_view = dialog->from_tree_view;
- show_button = GTK_CHECK_BUTTON (dialog->from_show_button);
- break;
- case XFER_DIALOG_TO:
- tree_view = dialog->to_tree_view;
- show_button = GTK_CHECK_BUTTON (dialog->to_show_button);
- break;
- default:
- g_assert_not_reached ();
- return;
+ case XFER_DIALOG_FROM:
+ tree_view = dialog->from_tree_view;
+ show_button = GTK_CHECK_BUTTON (dialog->from_show_button);
+ break;
+ case XFER_DIALOG_TO:
+ tree_view = dialog->to_tree_view;
+ show_button = GTK_CHECK_BUTTON (dialog->to_show_button);
+ break;
+ default:
+ g_assert_not_reached ();
+ return;
}
type = xaccAccountGetType (account);
@@ -2324,7 +2323,7 @@ gnc_transfer_dialog_set_selected_account (XferDialog *dialog,
(type == ACCT_TYPE_INCOME));
gnc_tree_view_account_set_selected_account (GNC_TREE_VIEW_ACCOUNT (tree_view),
- account);
+ account);
}
@@ -2398,8 +2397,8 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
/* XXX: should we tell the user we've done the conversion? */
amount = gnc_numeric_div(
- amount, rate,
- gnc_commodity_get_fraction(txn_cur), GNC_HOW_DENOM_REDUCE);
+ amount, rate,
+ gnc_commodity_get_fraction(txn_cur), GNC_HOW_DENOM_REDUCE);
}
/* enter the accounts */
commit 47f91c022761a0f2d7c27caed0d3ab0cf81263d9
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Aug 22 10:44:00 2015 +0100
Refactor gnc_xfer_dialog_response_cb with several extract-functions.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 9a6215f..3715c7b 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1353,24 +1353,256 @@ gnc_xfer_dialog_set_exchange_rate(XferDialog *xferData, gnc_numeric exchange_rat
gnc_xfer_update_to_amount (xferData);
}
+static gboolean
+check_accounts (XferDialog* xferData, Account* from_account,
+ Account* to_account)
+{
+ if ((from_account == NULL) || (to_account == NULL))
+ {
+ const char *message = _("You must specify an account to transfer from, "
+ "or to, or both, for this transaction. "
+ "Otherwise, it will not be recorded.");
+ gnc_error_dialog(xferData->dialog, "%s", message);
+ LEAVE("bad account");
+ return TRUE;
+ }
+
+ if (from_account == to_account)
+ {
+ const char *message = _("You can't transfer from and to the same "
+ "account!");
+ gnc_error_dialog(xferData->dialog, "%s", message);
+ LEAVE("same account");
+ return TRUE;
+ }
+
+ if (xaccAccountGetPlaceholder(from_account) ||
+ xaccAccountGetPlaceholder(to_account))
+ {
+ const char *placeholder_format =
+ _("The account %s does not allow transactions.");
+ char *name;
+
+ if (xaccAccountGetPlaceholder(from_account))
+ name = gnc_account_get_full_name(from_account);
+ else
+ name = gnc_account_get_full_name(to_account);
+ gnc_error_dialog(xferData->dialog, placeholder_format, name);
+ g_free(name);
+ LEAVE("placeholder");
+ return TRUE;
+ }
+
+ if (!gnc_commodity_is_iso (xferData->from_commodity))
+ {
+ const char *message =
+ _("You can't transfer from a non-currency account. "
+ "Try reversing the \"from\" and \"to\" accounts "
+ "and making the \"amount\" negative.");
+ gnc_error_dialog(xferData->dialog, "%s", message);
+ LEAVE("non-currency");
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+check_edit(XferDialog *xferData)
+{ if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->price_edit)))
+ {
+ if (gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON(xferData->price_radio)))
+ {
+ gnc_parse_error_dialog (xferData, _("You must enter a valid price."));
+ LEAVE("invalid price");
+ return TRUE;
+ }
+ }
+
+ if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->to_amount_edit)))
+ {
+ if (gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON(xferData->amount_radio)))
+ {
+ gnc_parse_error_dialog (xferData,
+ _("You must enter a valid `to' amount."));
+ LEAVE("invalid to amount");
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void
+create_transaction(XferDialog *xferData, Timespec *ts,
+ Account *from_account, Account* to_account,
+ gnc_numeric amount, gnc_numeric to_amount)
+{
+ Transaction *trans;
+ Split *from_split;
+ Split *to_split;
+ const char *string;
+ /* Create the transaction */
+ trans = xaccMallocTransaction(xferData->book);
+
+ xaccTransBeginEdit(trans);
+
+ xaccTransSetCurrency(trans, xferData->from_commodity);
+ xaccTransSetDatePostedTS(trans, ts);
+
+ /* Trans-Num or Split-Action set with gnc_set_num_action below per book
+ * option */
+
+ string = gtk_entry_get_text(GTK_ENTRY(xferData->description_entry));
+ xaccTransSetDescription(trans, string);
+
+ /* create from split */
+ from_split = xaccMallocSplit(xferData->book);
+ xaccTransAppendSplit(trans, from_split);
+
+ /* create to split */
+ to_split = xaccMallocSplit(xferData->book);
+ xaccTransAppendSplit(trans, to_split);
+
+ xaccAccountBeginEdit(from_account);
+ xaccAccountInsertSplit(from_account, from_split);
+
+ xaccAccountBeginEdit(to_account);
+ xaccAccountInsertSplit(to_account, to_split);
+
+ xaccSplitSetBaseValue(from_split, gnc_numeric_neg (amount),
+ xferData->from_commodity);
+ xaccSplitSetBaseValue(to_split, amount, xferData->from_commodity);
+ xaccSplitSetBaseValue(to_split, to_amount, xferData->to_commodity);
+
+ /* Set the transaction number or split action field based on book option*/
+ string = gtk_entry_get_text(GTK_ENTRY(xferData->num_entry));
+ gnc_set_num_action (trans, from_split, string, NULL);
+
+ /* Set the memo fields */
+ string = gtk_entry_get_text(GTK_ENTRY(xferData->memo_entry));
+ xaccSplitSetMemo(from_split, string);
+ xaccSplitSetMemo(to_split, string);
+
+ /* finish transaction */
+ xaccTransCommitEdit(trans);
+ xaccAccountCommitEdit(from_account);
+ xaccAccountCommitEdit(to_account);
+
+ /* If there is a registered callback handler that should be
+ notified of the newly created Transaction, call it now. */
+ if (xferData->transaction_cb)
+ xferData->transaction_cb(trans, xferData->transaction_user_data);
+}
+
+static void
+swap_amount (gnc_commodity *from, gnc_commodity *to, gnc_numeric *value,
+ gnc_numeric *from_amt, gnc_numeric *to_amt)
+{
+ gnc_commodity *tmp;
+ gnc_numeric *tmp_amt;
+ tmp = from;
+ from = to;
+ to = tmp;
+ tmp_amt = from_amt;
+ from_amt = to_amt;
+ to_amt = tmp_amt;
+ *value = gnc_numeric_div (gnc_numeric_create(1, 1), *value,
+ GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+}
+static void
+create_price(XferDialog *xferData, Timespec ts)
+{
+ gnc_commodity *from = xferData->from_commodity;
+ gnc_commodity *to = xferData->to_commodity;
+ GNCPrice *price;
+ gnc_numeric price_value;
+ gnc_numeric value;
+ gnc_numeric from_amt, to_amt;
+
+/* Bail in the unlikely event that both currencies have joined the Euro. */
+ if (gnc_is_euro_currency (from) && gnc_is_euro_currency (to))
+ return;
+
+ from_amt =
+ gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->amount_edit));
+ to_amt =
+ gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->to_amount_edit));
+
+ /* compute the price -- maybe we need to swap? */
+ value = gnc_numeric_div(to_amt, from_amt, GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_REDUCE);
+ value = gnc_numeric_abs (value);
+
+ /* Try to be consistent about how quotes are installed. */
+ if (from == gnc_default_currency() ||
+ ((to != gnc_default_currency()) &&
+ (strcmp (gnc_commodity_get_mnemonic(from),
+ gnc_commodity_get_mnemonic(to)) < 0)))
+ swap_amount (from, to, &value, &from_amt, &to_amt);
+ /* First see if the closest entry on the same day has an equivalent rate */
+ price = gnc_pricedb_lookup_day (xferData->pricedb, from, to, ts);
+ if (price)
+ {
+ price_value = gnc_price_get_value(price);
+ }
+ else
+ {
+ price = gnc_pricedb_lookup_day (xferData->pricedb, to, from, ts);
+ if (price)
+ {
+ price_value = gnc_numeric_div (gnc_numeric_create(1, 1),
+ gnc_price_get_value(price),
+ GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_REDUCE);
+ }
+ }
+
+ /* See if we found a good enough price */
+ if (price)
+ {
+ int scu = gnc_commodity_get_fraction (to);
+ if (!gnc_numeric_equal (gnc_numeric_mul (from_amt, price_value,
+ scu, GNC_HOW_RND_ROUND_HALF_UP),
+ to_amt))
+ {
+ gnc_price_unref (price);
+ price = NULL;
+ }
+ }
+
+ if (price)
+ {
+ PINFO("Found price for %s in %s", gnc_commodity_get_mnemonic(from),
+ gnc_commodity_get_mnemonic(to));
+ }
+ else
+ {
+ price = gnc_price_create (xferData->book);
+ gnc_price_begin_edit (price);
+ gnc_price_set_commodity (price, from);
+ gnc_price_set_currency (price, to);
+ gnc_price_set_time (price, ts);
+ gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
+ gnc_price_set_value (price, value);
+ gnc_pricedb_add_price (xferData->pricedb, price);
+ gnc_price_commit_edit (price);
+ PINFO("Created price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
+ gnc_numeric_to_double(value), gnc_commodity_get_mnemonic(to));
+ }
+
+ gnc_price_unref (price);
+}
+
void
gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
{
XferDialog *xferData = data;
Account *to_account;
Account *from_account;
- gnc_commodity *from_commodity;
- gnc_commodity *to_commodity;
gnc_numeric amount, to_amount;
- const char *string;
Timespec ts;
- gboolean curr_trans;
-
- Transaction *trans;
- Split *from_split;
- Split *to_split;
-
g_return_if_fail (xferData != NULL);
ENTER(" ");
@@ -1390,54 +1622,9 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
from_account = gnc_transfer_dialog_get_selected_account (xferData, XFER_DIALOG_FROM);
to_account = gnc_transfer_dialog_get_selected_account (xferData, XFER_DIALOG_TO);
- if (xferData->exch_rate == NULL)
- {
- if ((from_account == NULL) || (to_account == NULL))
- {
- const char *message = _("You must specify an account to transfer from, "
- "or to, or both, for this transaction. "
- "Otherwise, it will not be recorded.");
- gnc_error_dialog(xferData->dialog, "%s", message);
- LEAVE("bad account");
- return;
- }
-
- if (from_account == to_account)
- {
- const char *message = _("You can't transfer from and to the same "
- "account!");
- gnc_error_dialog(xferData->dialog, "%s", message);
- LEAVE("same account");
- return;
- }
-
- if (xaccAccountGetPlaceholder(from_account) ||
- xaccAccountGetPlaceholder(to_account))
- {
- const char *placeholder_format =
- _("The account %s does not allow transactions.");
- char *name;
-
- if (xaccAccountGetPlaceholder(from_account))
- name = gnc_account_get_full_name(from_account);
- else
- name = gnc_account_get_full_name(to_account);
- gnc_error_dialog(xferData->dialog, placeholder_format, name);
- g_free(name);
- LEAVE("placeholder");
- return;
- }
-
- if (!gnc_commodity_is_iso (xferData->from_commodity))
- {
- const char *message = _("You can't transfer from a non-currency account. "
- "Try reversing the \"from\" and \"to\" accounts "
- "and making the \"amount\" negative.");
- gnc_error_dialog(xferData->dialog, "%s", message);
- LEAVE("non-currency");
- return;
- }
- }
+ if (xferData->exch_rate == NULL &&
+ check_accounts(xferData, from_account, to_account))
+ return;
if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->amount_edit)))
{
@@ -1446,11 +1633,6 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
return;
}
- from_commodity = xferData->from_commodity;
- to_commodity = xferData->to_commodity;
-
- curr_trans = !gnc_commodity_equiv(from_commodity, to_commodity);
-
amount = gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->amount_edit));
if (gnc_numeric_zero_p (amount))
@@ -1463,33 +1645,12 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
ts = gnc_date_edit_get_date_ts(GNC_DATE_EDIT(xferData->date_entry));
- if (curr_trans)
+ if (!gnc_commodity_equiv(xferData->from_commodity, xferData->to_commodity))
{
- if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->price_edit)))
- {
- if (gtk_toggle_button_get_active
- (GTK_TOGGLE_BUTTON(xferData->price_radio)))
- {
- gnc_parse_error_dialog (xferData, _("You must enter a valid price."));
- LEAVE("invalid price");
- return;
- }
- }
-
- if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->to_amount_edit)))
- {
- if (gtk_toggle_button_get_active
- (GTK_TOGGLE_BUTTON(xferData->amount_radio)))
- {
- gnc_parse_error_dialog (xferData,
- _("You must enter a valid `to' amount."));
- LEAVE("invalid to amount");
- return;
- }
- }
-
+ if (check_edit(xferData))
+ return;
to_amount = gnc_amount_edit_get_amount
- (GNC_AMOUNT_EDIT(xferData->to_amount_edit));
+ (GNC_AMOUNT_EDIT(xferData->to_amount_edit));
}
else
to_amount = amount;
@@ -1510,156 +1671,12 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
*(xferData->exch_rate) = gnc_numeric_abs(price);
}
else
- {
- /* Create the transaction */
- trans = xaccMallocTransaction(xferData->book);
-
- xaccTransBeginEdit(trans);
-
- xaccTransSetCurrency(trans, from_commodity);
- xaccTransSetDatePostedTS(trans, &ts);
-
- /* Trans-Num or Split-Action set with gnc_set_num_action below per book
- * option */
-
- string = gtk_entry_get_text(GTK_ENTRY(xferData->description_entry));
- xaccTransSetDescription(trans, string);
-
- /* create from split */
- from_split = xaccMallocSplit(xferData->book);
- xaccTransAppendSplit(trans, from_split);
-
- /* create to split */
- to_split = xaccMallocSplit(xferData->book);
- xaccTransAppendSplit(trans, to_split);
-
- xaccAccountBeginEdit(from_account);
- xaccAccountInsertSplit(from_account, from_split);
-
- xaccAccountBeginEdit(to_account);
- xaccAccountInsertSplit(to_account, to_split);
-
- xaccSplitSetBaseValue(from_split, gnc_numeric_neg (amount), from_commodity);
- xaccSplitSetBaseValue(to_split, amount, from_commodity);
- xaccSplitSetBaseValue(to_split, to_amount, to_commodity);
-
- /* Set the transaction number or split action field based on book option*/
- string = gtk_entry_get_text(GTK_ENTRY(xferData->num_entry));
- gnc_set_num_action (trans, from_split, string, NULL);
-
- /* Set the memo fields */
- string = gtk_entry_get_text(GTK_ENTRY(xferData->memo_entry));
- xaccSplitSetMemo(from_split, string);
- xaccSplitSetMemo(to_split, string);
-
- /* finish transaction */
- xaccTransCommitEdit(trans);
- xaccAccountCommitEdit(from_account);
- xaccAccountCommitEdit(to_account);
-
- /* If there is a registered callback handler that should be
- notified of the newly created Transaction, call it now. */
- if (xferData->transaction_cb)
- xferData->transaction_cb(trans, xferData->transaction_user_data);
- }
-
+ create_transaction (xferData, &ts, from_account, to_account,
+ amount, to_amount);
/* try to save this to the pricedb */
- if (xferData->pricedb)
- {
- gnc_commodity *from = xferData->from_commodity;
- gnc_commodity *to = xferData->to_commodity;
-
- /* only continue if the currencies are DIFFERENT and are
- * not both euroland currencies
- */
- if (!gnc_commodity_equal (from, to) &&
- !(gnc_is_euro_currency (from) && gnc_is_euro_currency (to)))
- {
- GNCPrice *price;
- gnc_numeric price_value;
- gnc_numeric value;
- gnc_commodity *tmp;
- gnc_numeric from_amt, to_amt;
- gnc_numeric tmp_amt;
-
- from_amt = gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->amount_edit));
- to_amt = gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->to_amount_edit));
-
- /* compute the price -- maybe we need to swap? */
-
- value = gnc_numeric_div(to_amt, from_amt, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
- value = gnc_numeric_abs (value);
-
- /* Try to be consistent about how quotes are installed. */
- if (from == gnc_default_currency() ||
- ((to != gnc_default_currency()) &&
- (strcmp (gnc_commodity_get_mnemonic(from),
- gnc_commodity_get_mnemonic(to)) < 0)))
- {
- tmp = from;
- from = to;
- to = tmp;
- tmp_amt = from_amt;
- from_amt = to_amt;
- to_amt = tmp_amt;
- value = gnc_numeric_div (gnc_numeric_create(1, 1), value,
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
- }
-
- /* First see if the closest entry on the same day has an equivalent rate */
- price = gnc_pricedb_lookup_day (xferData->pricedb, from, to, ts);
- if (price)
- {
- price_value = gnc_price_get_value(price);
- }
- else
- {
- price = gnc_pricedb_lookup_day (xferData->pricedb, to, from, ts);
- if (price)
- {
- price_value = gnc_numeric_div (gnc_numeric_create(1, 1),
- gnc_price_get_value(price),
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
- }
- }
-
- /* See if we found a good enough price */
- if (price)
- {
- int scu = gnc_commodity_get_fraction (to);
- if (!gnc_numeric_equal (gnc_numeric_mul (from_amt, price_value,
- scu, GNC_HOW_RND_ROUND_HALF_UP),
- to_amt))
- {
- gnc_price_unref (price);
- price = NULL;
- }
- }
-
- if (price)
- {
- PINFO("Found price for %s in %s", gnc_commodity_get_mnemonic(from),
- gnc_commodity_get_mnemonic(to));
- }
- else
- {
- price = gnc_price_create (xferData->book);
- gnc_price_begin_edit (price);
- gnc_price_set_commodity (price, from);
- gnc_price_set_currency (price, to);
- gnc_price_set_time (price, ts);
- gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
- gnc_price_set_value (price, value);
- gnc_pricedb_add_price (xferData->pricedb, price);
- gnc_price_commit_edit (price);
- PINFO("Created price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
- gnc_numeric_to_double(value), gnc_commodity_get_mnemonic(to));
- }
-
- gnc_price_unref (price);
- }
- }
-
+ if (xferData->pricedb && !gnc_commodity_equal (xferData->from_commodity,
+ xferData->to_commodity))
+ create_price(xferData, ts);
/* Refresh everything */
gnc_resume_gui_refresh ();
commit e1b4e45de5f3ab357b17c135ee1881d99dbc8373
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Aug 22 09:17:49 2015 +0100
Don't store prices of source invoice.
They're intended to be temporary, for creating splits. They're also already
stored from the transfer dialog.
diff --git a/src/backend/sql/gnc-price-sql.c b/src/backend/sql/gnc-price-sql.c
index d7e6b70..8729c91 100644
--- a/src/backend/sql/gnc-price-sql.c
+++ b/src/backend/sql/gnc-price-sql.c
@@ -203,7 +203,7 @@ write_price( GNCPrice* p, gpointer data )
g_return_val_if_fail( p != NULL, FALSE );
g_return_val_if_fail( data != NULL, FALSE );
- if ( s->is_ok )
+ if ( s->is_ok && strcmp(gnc_price_get_source(p), PRICE_SOURCE_INVOICE) != 0)
{
s->is_ok = save_price( s->be, QOF_INSTANCE(p) );
}
commit 9a611a2aca597be3aa95812f105e4d9b5d13e6ec
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Aug 21 15:54:58 2015 +0100
Replace the price source and type strings with defines.
diff --git a/src/business/business-gnome/dialog-invoice.c b/src/business/business-gnome/dialog-invoice.c
index e840742..10c4d75 100644
--- a/src/business/business-gnome/dialog-invoice.c
+++ b/src/business/business-gnome/dialog-invoice.c
@@ -901,11 +901,8 @@ gnc_invoice_post(InvoiceWindow *iw, struct post_invoice_params *post_params)
gnc_price_set_commodity (convprice, account_currency);
gnc_price_set_currency (convprice, gncInvoiceGetCurrency (invoice));
gnc_price_set_time (convprice, postdate);
- gnc_price_set_source (convprice, "user:invoice-post");
-
- /* Yes, magic strings are evil but I can't find any defined constants
- for this..*/
- gnc_price_set_typestr (convprice, "last");
+ gnc_price_set_source (convprice, PRICE_SOURCE_INVOICE);
+ gnc_price_set_typestr (convprice, PRICE_TYPE_LAST);
gnc_price_set_value (convprice, exch_rate);
gncInvoiceAddPrice(invoice, convprice);
gnc_price_commit_edit (convprice);
@@ -1702,7 +1699,7 @@ gnc_invoice_update_window (InvoiceWindow *iw, GtkWidget *widget)
}
/* Set the type label */
- gtk_label_set_text (GTK_LABEL(iw->type_label), iw->is_credit_note ? _("Credit Note")
+ gtk_label_set_text (GTK_LABEL(iw->type_label), iw->is_credit_note ? _("Credit Note")
: gtk_label_get_text (GTK_LABEL(iw->type_label)));
if (iw->owner_choice)
@@ -1820,14 +1817,14 @@ gnc_invoice_update_window (InvoiceWindow *iw, GtkWidget *widget)
gtk_widget_hide (hide);
hide = GTK_WIDGET (gtk_builder_get_object (iw->builder, "hide4"));
gtk_widget_hide (hide);
-
+
show = GTK_WIDGET (gtk_builder_get_object (iw->builder, "posted_label"));
gtk_widget_show (show);
gtk_widget_show (iw->posted_date_hbox);
show = GTK_WIDGET (gtk_builder_get_object (iw->builder, "acct_label"));
gtk_widget_show (show);
gtk_widget_show (acct_entry);
-
+
show = GTK_WIDGET (gtk_builder_get_object (iw->builder, "hide1"));
gtk_widget_show (show);
show = GTK_WIDGET (gtk_builder_get_object (iw->builder, "hide2"));
@@ -2347,17 +2344,17 @@ gnc_invoice_create_page (InvoiceWindow *iw, gpointer page)
{
case GNC_OWNER_VENDOR:
gtk_label_set_text (GTK_LABEL(iw->info_label), _("Bill Information"));
- gtk_label_set_text (GTK_LABEL(iw->type_label), _("Bill"));
- gtk_label_set_text (GTK_LABEL(iw->id_label), _("Bill ID"));
+ gtk_label_set_text (GTK_LABEL(iw->type_label), _("Bill"));
+ gtk_label_set_text (GTK_LABEL(iw->id_label), _("Bill ID"));
break;
case GNC_OWNER_EMPLOYEE:
gtk_label_set_text (GTK_LABEL(iw->info_label), _("Voucher Information"));
gtk_label_set_text (GTK_LABEL(iw->type_label), _("Voucher"));
- gtk_label_set_text (GTK_LABEL(iw->id_label), _("Voucher ID"));
+ gtk_label_set_text (GTK_LABEL(iw->id_label), _("Voucher ID"));
default:
break;
}
-
+
entry_ledger = gnc_entry_ledger_new (iw->book, ledger_type);
/* Save the ledger... */
@@ -2430,7 +2427,7 @@ gnc_invoice_window_new_invoice (InvoiceDialogType dialog_type, QofBook *bookp,
const GncOwner *start_owner;
GncBillTerm *owner_terms = NULL;
GncOwnerType owner_type;
-
+
g_assert (dialog_type == NEW_INVOICE || dialog_type == MOD_INVOICE || dialog_type == DUP_INVOICE);
if (invoice)
@@ -2513,20 +2510,20 @@ gnc_invoice_window_new_invoice (InvoiceDialogType dialog_type, QofBook *bookp,
iw->id_label = GTK_WIDGET (gtk_builder_get_object (builder, "label14"));
iw->info_label = GTK_WIDGET (gtk_builder_get_object (builder, "label1"));
invoice_radio = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_invoice_type"));
-
+
iw->type_hbox = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_type_choice_hbox"));
iw->type_choice = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_type_invoice"));
-
+
/* The default GUI lables are for invoices, so change them if it isn't. */
owner_type = gncOwnerGetType (&iw->owner);
switch(owner_type)
{
case GNC_OWNER_VENDOR:
gtk_label_set_text (GTK_LABEL(iw->info_label), _("Bill Information"));
- gtk_label_set_text (GTK_LABEL(iw->type_label), _("Bill"));
+ gtk_label_set_text (GTK_LABEL(iw->type_label), _("Bill"));
gtk_button_set_label (GTK_BUTTON(invoice_radio), _("Bill"));
gtk_label_set_text (GTK_LABEL(iw->id_label), _("Bill ID"));
-
+
break;
case GNC_OWNER_EMPLOYEE:
gtk_label_set_text (GTK_LABEL(iw->info_label), _("Voucher Information"));
@@ -2536,7 +2533,7 @@ gnc_invoice_window_new_invoice (InvoiceDialogType dialog_type, QofBook *bookp,
default:
break;
}
-
+
/* configure the type related widgets based on dialog type and invoice type */
switch (dialog_type)
{
@@ -3306,4 +3303,3 @@ gnc_invoice_remind_bills_due_cb (void)
gnc_invoice_remind_bills_due();
}
-
diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c
index 54b7385..81febf1 100644
--- a/src/engine/gnc-pricedb.c
+++ b/src/engine/gnc-pricedb.c
@@ -966,6 +966,18 @@ gnc_pricedb_equal (GNCPriceDB *db1, GNCPriceDB *db2)
return equal_data.equal;
}
+static gboolean
+insert_or_replace_price(GNCPriceDB *db, GNCPrice *p)
+{
+ GNCPrice *old_price = gnc_pricedb_lookup_day (db, p->commodity,
+ p->currency, p->tmspec);
+ if (old_price == NULL)
+ return TRUE;
+ if (strcmp(p->source, "PRICE_SOURCE_FQ"))
+ return TRUE;
+ return FALSE;
+}
+
/* ==================================================================== */
/* The add_price() function is a utility that only manages the
* dual hash table instertion */
@@ -1030,6 +1042,12 @@ add_price(GNCPriceDB *db, GNCPrice *p)
LEAVE (" no price list");
return FALSE;
}
+
+ if (!insert_or_replace_price(db, p))
+ {
+ LEAVE("A better price already exists");
+ return FALSE;
+ }
g_hash_table_insert(currency_hash, currency, price_list);
p->db = db;
qof_event_gen (&p->inst, QOF_EVENT_ADD, NULL);
diff --git a/src/engine/gnc-pricedb.h b/src/engine/gnc-pricedb.h
index ce077a5..befff2d 100644
--- a/src/engine/gnc-pricedb.h
+++ b/src/engine/gnc-pricedb.h
@@ -207,6 +207,15 @@ void gnc_price_set_typestr(GNCPrice *p, const char* type);
void gnc_price_set_value(GNCPrice *p, gnc_numeric value);
/** @} */
+#define PRICE_SOURCE_FQ "Finance::Quote"
+#define PRICE_SOURCE_INVOICE "user:invoice-post"
+#define PRICE_SOURCE_STOCK_SPLIT "user:stock-split"
+#define PRICE_SOURCE_XFER_DLG "user:xfer-dialog"
+#define PRICE_SOURCE_SPLIT_REG "user:split-register"
+#define PRICE_SOURCE_EDIT_DLG "user:price-editor"
+#define PRICE_TYPE_LAST "last"
+#define PRICE_TYPE_UNK "unknown"
+
/* ------------------ */
/** @name Getters
All of the getters return data that's internal
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index bd1cda6..9a6215f 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1648,7 +1648,7 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
gnc_price_set_commodity (price, from);
gnc_price_set_currency (price, to);
gnc_price_set_time (price, ts);
- gnc_price_set_source (price, "user:xfer-dialog");
+ gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
gnc_price_set_value (price, value);
gnc_pricedb_add_price (xferData->pricedb, price);
gnc_price_commit_edit (price);
diff --git a/src/gnome/assistant-stock-split.c b/src/gnome/assistant-stock-split.c
index 8426ce1..f4b9cff 100644
--- a/src/gnome/assistant-stock-split.c
+++ b/src/gnome/assistant-stock-split.c
@@ -399,8 +399,8 @@ gnc_stock_split_assistant_finish (GtkAssistant *assistant,
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, "user:stock-split");
- gnc_price_set_typestr (price, "unknown");
+ 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);
diff --git a/src/gnome/dialog-price-editor.c b/src/gnome/dialog-price-editor.c
index ac980dc..c7c5b9e 100644
--- a/src/gnome/dialog-price-editor.c
+++ b/src/gnome/dialog-price-editor.c
@@ -50,8 +50,6 @@
#define DIALOG_PRICE_EDIT_CM_CLASS "dialog-price-edit"
#define GNC_PREFS_GROUP "dialogs.price-editor"
-#define DIALOG_PRICE_EDIT_SOURCE "user:price-editor"
-
/* This static indicates the debugging module that this .o belongs to. */
G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_GUI;
@@ -172,7 +170,7 @@ price_to_gui (PriceEditDialog *pedit_dialog)
currency = gnc_default_currency ();
date.tv_sec = gnc_time (NULL);
date.tv_nsec = 0;
- source = DIALOG_PRICE_EDIT_SOURCE;
+ source = PRICE_SOURCE_EDIT_DLG;
type = "";
value = gnc_numeric_zero ();
}
@@ -553,7 +551,7 @@ gnc_price_edit_dialog (GtkWidget * parent,
price = gnc_price_clone(price, pedit_dialog->book);
// } else {
// price = gnc_price_create (pedit_dialog->book);
- gnc_price_set_source (price, DIALOG_PRICE_EDIT_SOURCE);
+ gnc_price_set_source (price, PRICE_SOURCE_EDIT_DLG);
}
pedit_dialog->is_new = TRUE;
diff --git a/src/register/ledger-core/split-register.c b/src/register/ledger-core/split-register.c
index 3531633..fc4f587 100644
--- a/src/register/ledger-core/split-register.c
+++ b/src/register/ledger-core/split-register.c
@@ -2067,7 +2067,7 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
gnc_price_set_commodity (price, comm);
gnc_price_set_currency (price, curr);
gnc_price_set_time (price, ts);
- gnc_price_set_source (price, "user:split-register");
+ gnc_price_set_source (price, PRICE_SOURCE_SPLIT_REG);
gnc_price_set_value (price, value);
gnc_pricedb_add_price (pricedb, price);
gnc_price_commit_edit (price);
Summary of changes:
src/app-utils/gnc-sx-instance-model.c | 7 +-
src/backend/sql/gnc-price-sql.c | 2 +-
src/backend/xml/gnc-pricedb-xml-v2.c | 4 +-
src/backend/xml/io-gncxml-v1.c | 2 +-
src/business/business-gnome/dialog-invoice.c | 34 +-
src/engine/engine.i | 11 +-
src/engine/gnc-pricedb-p.h | 2 +-
src/engine/gnc-pricedb.c | 109 ++-
src/engine/gnc-pricedb.h | 37 +-
src/engine/test-core/test-engine-stuff.c | 7 +-
src/gnome-utils/dialog-transfer.c | 1048 ++++++++++++++------------
src/gnome-utils/gnc-tree-model-price.c | 2 +-
src/gnome-utils/gnc-tree-view-price.c | 3 +-
src/gnome/assistant-stock-split.c | 4 +-
src/gnome/dialog-price-editor.c | 10 +-
src/libqof/qof/gnc-numeric.c | 21 +-
src/libqof/qof/gnc-numeric.h | 7 +
src/quotes/gnc-fq-dump | 9 +
src/quotes/gnc-fq-helper.in | 13 +
src/register/ledger-core/split-register.c | 68 +-
src/scm/price-quotes.scm | 103 ++-
21 files changed, 900 insertions(+), 603 deletions(-)
More information about the gnucash-changes
mailing list