mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Update price database for imported transactions
When a transaction is added from the ledger, price database is updated properly. But if the transaction is imported, there is no price db update. This change adds the proper pricedb update in the import path (qfx/ofx/qif). Tested with make check
This commit is contained in:
parent
228f145bba
commit
75209c024f
@ -421,6 +421,7 @@ void qof_book_set_string_option(QofBook* book, const char* opt_name, const char*
|
|||||||
SET_ENUM("PRICE-SOURCE-USER-PRICE");
|
SET_ENUM("PRICE-SOURCE-USER-PRICE");
|
||||||
SET_ENUM("PRICE-SOURCE-XFER-DLG-VAL");
|
SET_ENUM("PRICE-SOURCE-XFER-DLG-VAL");
|
||||||
SET_ENUM("PRICE-SOURCE-SPLIT-REG");
|
SET_ENUM("PRICE-SOURCE-SPLIT-REG");
|
||||||
|
SET_ENUM("PRICE-SOURCE-SPLIT-IMPORT");
|
||||||
SET_ENUM("PRICE-SOURCE-STOCK-SPLIT");
|
SET_ENUM("PRICE-SOURCE-STOCK-SPLIT");
|
||||||
SET_ENUM("PRICE-SOURCE-TEMP");
|
SET_ENUM("PRICE-SOURCE-TEMP");
|
||||||
SET_ENUM("PRICE-SOURCE-INVALID");
|
SET_ENUM("PRICE-SOURCE-INVALID");
|
||||||
|
@ -840,6 +840,7 @@ gnc_import_process_trans_item (GncImportMatchMap *matchmap,
|
|||||||
{
|
{
|
||||||
Split * other_split;
|
Split * other_split;
|
||||||
gnc_numeric imbalance_value;
|
gnc_numeric imbalance_value;
|
||||||
|
Transaction *trans;
|
||||||
|
|
||||||
/* DEBUG("Begin"); */
|
/* DEBUG("Begin"); */
|
||||||
|
|
||||||
@ -894,7 +895,9 @@ gnc_import_process_trans_item (GncImportMatchMap *matchmap,
|
|||||||
xaccSplitSetDateReconciledSecs(gnc_import_TransInfo_get_fsplit (trans_info),
|
xaccSplitSetDateReconciledSecs(gnc_import_TransInfo_get_fsplit (trans_info),
|
||||||
gnc_time (NULL));
|
gnc_time (NULL));
|
||||||
/* Done editing. */
|
/* Done editing. */
|
||||||
xaccTransCommitEdit(gnc_import_TransInfo_get_trans (trans_info));
|
trans = gnc_import_TransInfo_get_trans (trans_info);
|
||||||
|
xaccTransCommitEdit(trans);
|
||||||
|
xaccTransRecordPrice(trans, PRICE_SOURCE_SPLIT_IMPORT);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case GNCImport_UPDATE:
|
case GNCImport_UPDATE:
|
||||||
{
|
{
|
||||||
|
@ -444,7 +444,8 @@
|
|||||||
progress-dialog)
|
progress-dialog)
|
||||||
|
|
||||||
;; rebalance and commit everything
|
;; rebalance and commit everything
|
||||||
(xaccTransCommitEdit gnc-xtn))))
|
(xaccTransCommitEdit gnc-xtn)
|
||||||
|
(xaccTransRecordPrice gnc-xtn PRICE-SOURCE-SPLIT-IMPORT))))
|
||||||
(qif-file:xtns qif-file)))
|
(qif-file:xtns qif-file)))
|
||||||
sorted-qif-files-list)
|
sorted-qif-files-list)
|
||||||
|
|
||||||
|
@ -1958,6 +1958,7 @@ gnc_split_register_save (SplitRegister* reg, gboolean do_commit)
|
|||||||
}
|
}
|
||||||
unreconcile_splits (reg);
|
unreconcile_splits (reg);
|
||||||
xaccTransCommitEdit (trans);
|
xaccTransCommitEdit (trans);
|
||||||
|
xaccTransRecordPrice (trans, PRICE_SOURCE_SPLIT_REG);
|
||||||
}
|
}
|
||||||
|
|
||||||
gnc_table_clear_current_cursor_changes (reg->table);
|
gnc_table_clear_current_cursor_changes (reg->table);
|
||||||
@ -2203,79 +2204,6 @@ recalculate_value (Split* split, SplitRegister* reg,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
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));
|
|
||||||
GNCPriceDB* pricedb = gnc_pricedb_get_db (book);
|
|
||||||
gnc_commodity* comm = xaccAccountGetCommodity (account);
|
|
||||||
gnc_commodity* curr = xaccTransGetCurrency (trans);
|
|
||||||
GNCPrice* price;
|
|
||||||
gnc_numeric price_value;
|
|
||||||
int scu = gnc_commodity_get_fraction (curr);
|
|
||||||
time64 time;
|
|
||||||
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
|
|
||||||
* gnc_split_register_handle_exchange.
|
|
||||||
*/
|
|
||||||
if (gnc_split_reg_has_rate_cell (reg->type))
|
|
||||||
return;
|
|
||||||
gnc_date_cell_get_date ((DateCell*)cell, &time, TRUE);
|
|
||||||
price = gnc_pricedb_lookup_day_t64 (pricedb, comm, curr, time);
|
|
||||||
if (gnc_commodity_equiv (comm, gnc_price_get_currency (price)))
|
|
||||||
swap = TRUE;
|
|
||||||
|
|
||||||
if (price)
|
|
||||||
{
|
|
||||||
price_value = gnc_price_get_value (price);
|
|
||||||
if (gnc_numeric_equal (swap ? gnc_numeric_invert (value) : value,
|
|
||||||
price_value))
|
|
||||||
{
|
|
||||||
gnc_price_unref (price);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (gnc_price_get_source (price) < PRICE_SOURCE_XFER_DLG_VAL)
|
|
||||||
{
|
|
||||||
/* Existing price is preferred over this one. */
|
|
||||||
gnc_price_unref (price);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
gnc_price_begin_edit (price);
|
|
||||||
gnc_price_set_time64 (price, time);
|
|
||||||
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);
|
|
||||||
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);
|
|
||||||
gnc_price_set_currency (price, curr);
|
|
||||||
gnc_price_set_time64 (price, time);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gnc_split_register_auto_calc (SplitRegister* reg, Split* split)
|
gnc_split_register_auto_calc (SplitRegister* reg, Split* split)
|
||||||
{
|
{
|
||||||
@ -2447,14 +2375,6 @@ gnc_split_register_auto_calc (SplitRegister* reg, Split* split)
|
|||||||
if (recalc_value)
|
if (recalc_value)
|
||||||
recalculate_value (split, reg, price, amount, shares_changed);
|
recalculate_value (split, reg, price, amount, shares_changed);
|
||||||
|
|
||||||
if (price_changed)
|
|
||||||
{
|
|
||||||
cell = (PriceCell*) gnc_table_layout_get_cell (reg->table->layout,
|
|
||||||
PRIC_CELL);
|
|
||||||
price = gnc_price_cell_get_value (cell);
|
|
||||||
if (gnc_numeric_positive_p (price))
|
|
||||||
record_price (reg, account, price, source);
|
|
||||||
}
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2938,6 +2938,100 @@ xaccTransFindSplitByAccount(const Transaction *trans, const Account *acc)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
record_price (Split *split,
|
||||||
|
PriceSource source)
|
||||||
|
{
|
||||||
|
Transaction *trans;
|
||||||
|
Account *account;
|
||||||
|
QofBook* book;
|
||||||
|
GNCPriceDB* pricedb;
|
||||||
|
gnc_commodity* comm;
|
||||||
|
gnc_commodity* curr;
|
||||||
|
GNCPrice* price;
|
||||||
|
gnc_numeric price_value, value, amount;
|
||||||
|
int scu;
|
||||||
|
time64 time;
|
||||||
|
gboolean swap;
|
||||||
|
|
||||||
|
account = xaccSplitGetAccount (split);
|
||||||
|
if (!xaccAccountIsPriced (account))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
amount = xaccSplitGetAmount (split);
|
||||||
|
if (gnc_numeric_zero_p (amount))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
trans = xaccSplitGetParent (split);
|
||||||
|
value = gnc_numeric_div (xaccSplitGetValue (split), amount,
|
||||||
|
GNC_DENOM_AUTO,
|
||||||
|
GNC_HOW_DENOM_EXACT);
|
||||||
|
book = qof_instance_get_book (QOF_INSTANCE (account));
|
||||||
|
pricedb = gnc_pricedb_get_db (book);
|
||||||
|
comm = xaccAccountGetCommodity (account);
|
||||||
|
curr = xaccTransGetCurrency (trans);
|
||||||
|
scu = gnc_commodity_get_fraction (curr);
|
||||||
|
swap = FALSE;
|
||||||
|
time = xaccTransGetDate (trans);
|
||||||
|
price = gnc_pricedb_lookup_day_t64 (pricedb, comm, curr, time);
|
||||||
|
if (gnc_commodity_equiv (comm, gnc_price_get_currency (price)))
|
||||||
|
swap = TRUE;
|
||||||
|
|
||||||
|
if (price)
|
||||||
|
{
|
||||||
|
price_value = gnc_price_get_value (price);
|
||||||
|
if (gnc_numeric_equal (swap ? gnc_numeric_invert (value) : value,
|
||||||
|
price_value))
|
||||||
|
{
|
||||||
|
gnc_price_unref (price);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (gnc_price_get_source (price) < source)
|
||||||
|
{
|
||||||
|
/* Existing price is preferred over this one. */
|
||||||
|
gnc_price_unref (price);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
gnc_price_begin_edit (price);
|
||||||
|
gnc_price_set_time64 (price, time);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
gnc_price_set_currency (price, curr);
|
||||||
|
gnc_price_set_time64 (price, time);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccTransRecordPrice (Transaction *trans, PriceSource source)
|
||||||
|
{
|
||||||
|
/* XXX: This should have been part of xaccSplitCommitEdit. */
|
||||||
|
for (GList *n = xaccTransGetSplitList (trans); n; n = n->next)
|
||||||
|
record_price (n->data, source);
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
\********************************************************************/
|
\********************************************************************/
|
||||||
|
@ -92,6 +92,7 @@ typedef struct _TransactionClass TransactionClass;
|
|||||||
|
|
||||||
#include "gnc-commodity.h"
|
#include "gnc-commodity.h"
|
||||||
#include "gnc-engine.h"
|
#include "gnc-engine.h"
|
||||||
|
#include "gnc-pricedb.h"
|
||||||
#include "Split.h"
|
#include "Split.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -767,6 +768,15 @@ time64 xaccTransGetVoidTime(const Transaction *tr);
|
|||||||
void xaccTransDump (const Transaction *trans, const char *tag);
|
void xaccTransDump (const Transaction *trans, const char *tag);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** The xaccTransRecordPrice() method iterates through the splits and
|
||||||
|
* and record the non-currency equivalent prices in the price database.
|
||||||
|
*
|
||||||
|
* @param trans The transaction whose price is recorded
|
||||||
|
* @param source The price priority level
|
||||||
|
*/
|
||||||
|
void xaccTransRecordPrice (Transaction *trans, PriceSource source);
|
||||||
|
|
||||||
|
|
||||||
#define RECONCILED_MATCH_TYPE "reconciled-match"
|
#define RECONCILED_MATCH_TYPE "reconciled-match"
|
||||||
|
|
||||||
/** \deprecated */
|
/** \deprecated */
|
||||||
|
@ -124,6 +124,7 @@ static const char* source_names[(size_t)PRICE_SOURCE_INVALID + 1] =
|
|||||||
/* String retained for backwards compatibility. */
|
/* String retained for backwards compatibility. */
|
||||||
"user:xfer-dialog",
|
"user:xfer-dialog",
|
||||||
"user:split-register",
|
"user:split-register",
|
||||||
|
"user:split-import",
|
||||||
"user:stock-split",
|
"user:stock-split",
|
||||||
"user:invoice-post", /* Retained for backwards compatibility */
|
"user:invoice-post", /* Retained for backwards compatibility */
|
||||||
"temporary",
|
"temporary",
|
||||||
|
@ -173,6 +173,7 @@ typedef enum
|
|||||||
PRICE_SOURCE_USER_PRICE, // "user:price"
|
PRICE_SOURCE_USER_PRICE, // "user:price"
|
||||||
PRICE_SOURCE_XFER_DLG_VAL, // "user:xfer-dialog"
|
PRICE_SOURCE_XFER_DLG_VAL, // "user:xfer-dialog"
|
||||||
PRICE_SOURCE_SPLIT_REG, // "user:split-register"
|
PRICE_SOURCE_SPLIT_REG, // "user:split-register"
|
||||||
|
PRICE_SOURCE_SPLIT_IMPORT, // "user:split-import"
|
||||||
PRICE_SOURCE_STOCK_SPLIT, // "user:stock-split"
|
PRICE_SOURCE_STOCK_SPLIT, // "user:stock-split"
|
||||||
PRICE_SOURCE_INVOICE, // "user:invoice-post"
|
PRICE_SOURCE_INVOICE, // "user:invoice-post"
|
||||||
PRICE_SOURCE_TEMP, // "temporary"
|
PRICE_SOURCE_TEMP, // "temporary"
|
||||||
|
@ -144,3 +144,10 @@ xaccTransDestroy (Transaction *trans)
|
|||||||
ASSERT_TRUE(GNC_IS_MOCKTRANSACTION(trans));
|
ASSERT_TRUE(GNC_IS_MOCKTRANSACTION(trans));
|
||||||
gnc_mocktransaction(trans)->destroy();
|
gnc_mocktransaction(trans)->destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccTransRecordPrice (Transaction *trans, PriceSource source)
|
||||||
|
{
|
||||||
|
g_return_if_fail(GNC_IS_MOCKTRANSACTION(trans));
|
||||||
|
((MockTransaction*)trans)->recordPrice();
|
||||||
|
}
|
||||||
|
@ -66,6 +66,7 @@ public:
|
|||||||
MOCK_CONST_METHOD0(get_num, const char *());
|
MOCK_CONST_METHOD0(get_num, const char *());
|
||||||
MOCK_CONST_METHOD0(is_open, gboolean());
|
MOCK_CONST_METHOD0(is_open, gboolean());
|
||||||
MOCK_METHOD0(destroy, void());
|
MOCK_METHOD0(destroy, void());
|
||||||
|
MOCK_METHOD0(recordPrice, void());
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Protect destructor to avoid MockTransaction objects to be created on stack. MockTransaction
|
// Protect destructor to avoid MockTransaction objects to be created on stack. MockTransaction
|
||||||
|
Loading…
Reference in New Issue
Block a user