1 /********************************************************************
2  * gnc-pricedb.h -- a simple price database for gnucash.            *
3  *                                                                  *
4  * This program is free software; you can redistribute it and/or    *
5  * modify it under the terms of the GNU General Public License as   *
6  * published by the Free Software Foundation; either version 2 of   *
7  * the License, or (at your option) any later version.              *
8  *                                                                  *
9  * This program is distributed in the hope that it will be useful,  *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
12  * GNU General Public License for more details.                     *
13  *                                                                  *
14  * You should have received a copy of the GNU General Public License*
15  * along with this program; if not, contact:                        *
16  *                                                                  *
17  * Free Software Foundation           Voice:  +1-617-542-5942       *
18  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
19  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
20  *                                                                  *
21  *******************************************************************/
22 
23 #ifndef GNC_PRICEDB_H
24 #define GNC_PRICEDB_H
25 
26 typedef struct _GncPriceClass GNCPriceClass;
27 typedef struct _GncPriceDBClass GNCPriceDBClass;
28 
29 #include <stdio.h>
30 #include "qof.h"
31 #include "gnc-commodity.h"
32 #include "gnc-engine.h"
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 /* --- type macros --- */
39 #define GNC_TYPE_PRICE            (gnc_price_get_type ())
40 #define GNC_PRICE(o)              \
41      (G_TYPE_CHECK_INSTANCE_CAST ((o), GNC_TYPE_PRICE, GNCPrice))
42 #define GNC_PRICE_CLASS(k)        \
43      (G_TYPE_CHECK_CLASS_CAST((k), GNC_TYPE_PRICE, GNCPriceClass))
44 #define GNC_IS_PRICE(o)           \
45      (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_PRICE))
46 #define GNC_IS_PRICE_CLASS(k)     \
47      (G_TYPE_CHECK_CLASS_TYPE ((k), GNC_TYPE_PRICE))
48 #define GNC_PRICE_GET_CLASS(o)    \
49      (G_TYPE_INSTANCE_GET_CLASS ((o), GNC_TYPE_PRICE, GNCPriceClass))
50 GType gnc_price_get_type(void);
51 
52 /* --- type macros --- */
53 #define GNC_TYPE_PRICEDB            (gnc_pricedb_get_type ())
54 #define GNC_PRICEDB(o)              \
55      (G_TYPE_CHECK_INSTANCE_CAST ((o), GNC_TYPE_PRICEDB, GNCPriceDB))
56 #define GNC_PRICEDB_CLASS(k)        \
57      (G_TYPE_CHECK_CLASS_CAST((k), GNC_TYPE_PRICEDB, GNCPriceDBClass))
58 #define GNC_IS_PRICEDB(o)           \
59      (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_PRICEDB))
60 #define GNC_IS_PRICEDB_CLASS(k)     \
61      (G_TYPE_CHECK_CLASS_TYPE ((k), GNC_TYPE_PRICEDB))
62 #define GNC_PRICEDB_GET_CLASS(o)    \
63      (G_TYPE_INSTANCE_GET_CLASS ((o), GNC_TYPE_PRICEDB, GNCPriceDBClass))
64 GType gnc_pricedb_get_type(void);
65 
66 
67 /** @addtogroup PriceDB
68     @{ */
69 /** @file gnc-pricedb.h
70     @author Copyright (C) 2001 Rob Browning
71     @author Copyright (C) 2001,2003 Linas Vepstas <linas@linas.org>
72     @brief a simple price database for gnucash
73 */
74 /** @} */
75 
76 
77 /** @addtogroup Engine
78     @{ */
79 /** @addtogroup PriceDB  Price Database
80     @ingroup Engine
81     The PriceDB is intended to be a database of price quotes, or more
82     specifically, a database of GNCPrices.  For the time being, it is
83     still a fairly simple database supporting only fairly simple
84     queries.  It is expected that new queries will be added as needed,
85     and that there is some advantage to delaying complex queries for
86     now in the hope that we get a real DB implementation before
87     they're really needed.
88 
89     Every QofBook contains a GNCPriceDB, accessible via
90     gnc_pricedb_get_db.
91 
92     \warning The PriceDB does not currently use the object
93     system used elsewhere in the GnuCash Engine, i.e. it does
94     not use GUISD's, Entities and Collections.  It should.
95     In particular, this means that currently prices cannot
96     be queried with the same mechanism as everything else.
97 */
98 
99 /** @addtogroup Price  Prices
100     @ingroup Engine
101     Each price in the database represents an "instantaneous" quote for
102     a given commodity with respect to another commodity.  For example,
103     a given price might represent the value of LNUX in USD on
104     2001-02-03.
105 
106     \par Fields:
107 
108     - commodity: the item being priced.
109     - currency: the denomination of the value of the item being priced.
110     - value: the value of the item being priced.
111     - time: the time the price was valid.
112     - source: a string describing the source of the quote.  These
113       strings will be something like this: "Finance::Quote",
114       "user:misc", "user:foo", etc.  If the quote came from a user,
115       as a matter of policy, you *must* prefix the string you give
116       with "user:".  For now, the only other reserved values are
117       "Finance::Quote" and "old-file-import".  Any string used must
118       be added to the source_list array in dialog-price-edit-db.c so
119       that it can be properly translated. (There are unfortunately
120       many strings in users' databases, so this string must be
121       translated on output instead of always being used in untranslated
122       form).
123     - type: the type of quote - types possible right now are bid, ask, last,
124       nav, transaction, and unknown. 'Transaction' is set when the price is
125       created from an amount and value in a Split and is not available for users
126       to set via the GUI.
127 
128     \par Implementation Details:
129 
130     \note
131     For source and type, NULL and the empty string are
132     considered the same, so if one of these is "", then after a file
133     save/restore, it might be NULL.  Behave accordingly.
134 
135     GNCPrices are reference counted.  When you gnc_price_create one
136     or clone it, the new price's count is set to 1.  When you are
137     finished with a price, call gnc_price_unref.  If you hand the
138     price pointer to some other code that needs to keep it, make
139     sure it calls gnc_price_ref to indicate its interest in that
140     price, and calls gnc_price_unref when it's finished with the
141     price.  For those unfamiliar with reference counting, basically
142     each price stores an integer count which starts at 1 and is
143     incremented every time someone calls gnc_price_ref.  Conversely,
144     the count is decremented every time someone calls
145     gnc_price_unref.  If the count ever reaches 0, the price is
146     destroyed.
147 
148       All of the getters return data that's internal to the GNCPrice,
149       not copies, so don't free these values.
150 
151       All of the setters store copies of the data given, with the
152       exception of the commodity field which just stores the pointer
153       given.  It is assumed that commodities are a global resource and
154       are pointer unique.
155    */
156 /* ================================================================ */
157 
158 /** @addtogroup Price
159  @{ */
160 
161 /** */
162 typedef GList PriceList;
163 
164 /** Price source enum. Be sure to keep in sync with the source_name array in
165  * gnc-pricedb.c. These are in preference order, so for example a quote with
166  * PRICE_SOURCE_EDIT_DLG will overwrite one with PRICE_SOURCE_FQ but not the
167  * other way around.
168  */
169 typedef enum
170 {
171     PRICE_SOURCE_EDIT_DLG,         // "user:price-editor"
172     PRICE_SOURCE_FQ,               // "Finance::Quote"
173     PRICE_SOURCE_USER_PRICE,       // "user:price"
174     PRICE_SOURCE_XFER_DLG_VAL,     // "user:xfer-dialog"
175     PRICE_SOURCE_SPLIT_REG,        // "user:split-register"
176     PRICE_SOURCE_SPLIT_IMPORT,     // "user:split-import"
177     PRICE_SOURCE_STOCK_SPLIT,      // "user:stock-split"
178     PRICE_SOURCE_INVOICE,          // "user:invoice-post"
179     PRICE_SOURCE_TEMP,             // "temporary"
180     PRICE_SOURCE_INVALID,          // "invalid"
181 } PriceSource;
182 
183 #define PRICE_TYPE_LAST "last"
184 #define PRICE_TYPE_UNK "unknown"
185 #define PRICE_TYPE_TRN "transaction"
186 /* ------------------ */
187 /** @name Constructors
188     @{ */
189 
190 /** gnc_price_create - returns a newly allocated and initialized price
191    with a reference count of 1. */
192 /*@ dependent @*/
193 GNCPrice *gnc_price_create(QofBook *book);
194 
195 /** gnc_price_clone - returns a newly allocated price that's a
196    content-wise duplicate of the given price, p.  The returned clone
197    will have a reference count of 1. */
198 GNCPrice *gnc_price_clone(GNCPrice* p, QofBook *book);
199 
200 /** Return a newly-allocated price that's the inverse of the given price, p.
201  *
202  * Inverse means that the commodity and currency are swapped and the value is
203  * the numeric inverse of the original's. The source is set to PRICE_SOURCE_TEMP
204  * to prevent it being saved in the pricedb.
205  * @param p The price to invert
206  * @return a new price, with a ref-count of 1. Don't forget to unref it!
207  */
208 GNCPrice *gnc_price_invert(GNCPrice *p);
209 
210 /**  @} */
211 
212 /* ------------------ */
213 /** @name  Memory Management
214     @{ */
215 
216 /** gnc_price_ref - indicate your need for a given price to stick
217    around (i.e. increase its reference count by 1). */
218 void      gnc_price_ref(GNCPrice *p);
219 
220 /** gnc_price_unref - indicate you're finished with a price
221    (i.e. decrease its reference count by 1). */
222 void      gnc_price_unref(GNCPrice *p);
223 /** @} */
224 
225 /* ------------------ */
226 /** @name  Setters
227  * All of the setters store copies of the data
228  * given, with the exception of the commodity field which just stores
229  * the pointer given.  It is assumed that commodities are a global
230  * resource and are pointer unique.
231  *
232  * Invocations of the setters should be wrapped with calls to
233  * gnc_price_begin_edit() and commit_edit().  The begin/commit
234  * calls help ensure that the local price db is synchronized with
235  * the backend.
236    @{ */
237 void gnc_price_begin_edit (GNCPrice *p);
238 void gnc_price_commit_edit (GNCPrice *p);
239 
240 void gnc_price_set_commodity(GNCPrice *p, gnc_commodity *c);
241 void gnc_price_set_currency(GNCPrice *p, gnc_commodity *c);
242 void gnc_price_set_time64(GNCPrice *p, time64 t);
243 void gnc_price_set_source(GNCPrice *p, PriceSource source);
244 void gnc_price_set_source_string(GNCPrice *p, const char* s);
245 void gnc_price_set_typestr(GNCPrice *p, const char* type);
246 void gnc_price_set_value(GNCPrice *p, gnc_numeric value);
247 /** @} */
248 
249 /* ------------------ */
250 /** @name  Getters
251     All of the getters return data that's internal
252     to the GNCPrice, not copies, so don't free these values.
253     @{ */
254 
255     GNCPrice *      gnc_price_lookup (const GncGUID *guid, QofBook *book);
256 /*@ dependent @*/
257 gnc_commodity * gnc_price_get_commodity(const GNCPrice *p);
258 /*@ dependent @*/
259 gnc_commodity * gnc_price_get_currency(const GNCPrice *p);
260 time64          gnc_price_get_time64(const GNCPrice *p);
261 PriceSource     gnc_price_get_source(const GNCPrice *p);
262 const char *    gnc_price_get_source_string(const GNCPrice *p);
263 const char *    gnc_price_get_typestr(const GNCPrice *p);
264 gnc_numeric     gnc_price_get_value(const GNCPrice *p);
265 gboolean        gnc_price_equal(const GNCPrice *p1, const GNCPrice *p2);
266 
267 #define gnc_price_get_guid(X)    qof_entity_get_guid(QOF_INSTANCE(X))
268 #define gnc_price_return_guid(X) (*(qof_entity_get_guid(QOF_INSTANCE(X))))
269 #define gnc_price_get_book(X)    qof_instance_get_book(QOF_INSTANCE(X))
270 /**  @} */
271 
272 /** @name Internal/Debugging
273     @{ */
274 /** This simple function can be useful for debugging the price code */
275 void gnc_price_print(GNCPrice *db, FILE *f, int indent);
276 /** @} */
277 /** @name Denominator Constants Price policy: In order to avoid rounding
278  * problems, currency prices (often called exchange rates) are saved in terms of
279  * the smaller currency, so that price > 1, with a fixed denominator of
280  * 1/1000. Commodity prices in currency are always expressed as value per unit
281  * of the commodity with a fixed denominator of the pricing currency's
282  * SCU * 10000.
283  */
284 #define CURRENCY_DENOM 10000
285 #define COMMODITY_DENOM_MULT 10000
286 
287 /* ================================================================ */
288 /** @name GNCPrice lists
289     The database communicates multiple prices in and out via gnc price
290     lists.  These are just time sorted GLists of GNCPrice pointers.
291     Functions for manipulating these lists are provided.  These
292     functions are helpful in that they handle maintaining proper
293     reference counts on behalf of the price list for every price being
294     held in a given list.  I.e. insert "refs" the prices being
295     inserted, remove and destroy "unref" the prices that will no
296     longer be referred to by the list.
297    @{
298 */
299 
300 /** gnc_price_list_insert - insert a price into the given list, calling
301      gnc_price_ref on it during the process. */
302 gboolean gnc_price_list_insert(PriceList **prices, GNCPrice *p,
303                                gboolean check_dupl);
304 
305 /** gnc_price_list_remove - remove the price, p, from the given list,
306      calling gnc_price_unref on it during the process. */
307 gboolean gnc_price_list_remove(PriceList **prices, GNCPrice *p);
308 
309 /** gnc_price_list_destroy - destroy the given price list, calling
310      gnc_price_unref on all the prices included in the list. */
311 void     gnc_price_list_destroy(PriceList *prices);
312 
313 gboolean gnc_price_list_equal(PriceList *prices1, PriceList *prices2);
314 /**  @} */
315 /**  @}  end of the Price doxygen group */
316 
317 /* ================================================================ */
318 /** @addtogroup PriceDB
319   Whenever a you store a price in the pricedb, the pricedb adds its
320   own reference to the price, so you can safely unref that price after
321   inserting it into the DB if you're finished with it otherwise.
322 
323   Similarly, when the pricedb returns a price to you, either singly,
324   or in a price list, the price will have had a ref added for you, so
325   you only need to unref the price(s) when you're finished with
326   it/them.
327   @{
328 */
329 /** Data type */
330 typedef struct gnc_price_db_s GNCPriceDB;
331 
332 /** @brief Return the pricedb associated with the book
333  * @param book The QofBook holding the pricedb
334  * @return The GNCPriceDB associated with the book.
335  */
336 GNCPriceDB * gnc_pricedb_get_db(QofBook *book);
337 /** @brief Return the pricedb via the Book's collection.
338  * @param col The QofCollection holding the pricedb
339  * @return The GNCPriceDB in the QofCollection
340  */
341 GNCPriceDB * gnc_collection_get_pricedb(QofCollection *col);
342 
343 /** @brief Destroy the given pricedb and unref all of the prices it contains.
344  *
345  * This may not deallocate all of those prices.  Other code may still be holding
346  * references to them.
347  * @param db The pricedb to destroy.
348  */
349 void gnc_pricedb_destroy(GNCPriceDB *db);
350 
351 /** @brief Begin an edit. */
352 void gnc_pricedb_begin_edit (GNCPriceDB *);
353 /** @brief Commit an edit. */
354 void gnc_pricedb_commit_edit (GNCPriceDB *);
355 
356 /** @brief Set flag to indicate whether duplication checks should be performed.
357  *
358  * Normally used at load time to speed up loading the pricedb.
359  * @param db The pricedb
360  * @param bulk_update TRUE to disable duplication checks, FALSE to enable them.
361  */
362 void gnc_pricedb_set_bulk_update(GNCPriceDB *db, gboolean bulk_update);
363 
364 /** @brief Add a price to the pricedb.
365  *
366  * You may drop your reference to the price (i.e. call unref) after this
367  * succeeds, whenever you're finished with the price.
368  * @param db The pricedb
369  * @param p The GNCPrice to add.
370  * @return TRUE if the price was added, FALSE otherwise.
371  */
372 gboolean     gnc_pricedb_add_price(GNCPriceDB *db, GNCPrice *p);
373 
374 /** @brief Remove a price from the pricedb and unref the price.
375  * @param db The Pricedb
376  * @param p The price to remove.
377  */
378 gboolean     gnc_pricedb_remove_price(GNCPriceDB *db, GNCPrice *p);
379 
380 typedef enum
381 {
382     PRICE_REMOVE_SOURCE_FQ = 1,   // this flag is set when added by F:Q checked
383     PRICE_REMOVE_SOURCE_USER = 2, // this flag is set when added by the user checked
384     PRICE_REMOVE_SOURCE_APP = 4,  // this flag is set when added by the app checked
385     PRICE_REMOVE_SOURCE_COMM = 8, // this flag is set when we have commodities selected
386 } PriceRemoveSourceFlags;
387 
388 typedef enum
389 {
390     PRICE_REMOVE_KEEP_NONE,           // keep none
391     PRICE_REMOVE_KEEP_LAST_WEEKLY,    // leave last one of every week
392     PRICE_REMOVE_KEEP_LAST_MONTHLY,   // leave last one of every month
393     PRICE_REMOVE_KEEP_LAST_QUARTERLY, // leave last one of every quarter
394     PRICE_REMOVE_KEEP_LAST_PERIOD,    // leave last one of every annual period
395     PRICE_REMOVE_KEEP_SCALED,         // leave one every week then one a month
396 } PriceRemoveKeepOptions;
397 
398 /** @brief Remove and unref prices older than a certain time.
399  * @param db The pricedb
400  * @param comm_list A list of commodities
401  * @param fiscal_end_date the end date of the current accounting period
402  * @param cutoff The time before which prices should be deleted.
403  * @param source Whether Finance::Quote, user or all prices should be deleted.
404  * @param keep Whether scaled, monthly, weekly or no prices should be left.
405  * @return True if there were prices to process, False if not.
406  */
407 gboolean     gnc_pricedb_remove_old_prices(GNCPriceDB *db, GList *comm_list,
408                                            GDate *fiscal_end_date, time64 cutoff,
409                                            PriceRemoveSourceFlags source,
410                                            PriceRemoveKeepOptions keep);
411 
412 /** @brief Find the most recent price between the two commodities.
413  *
414  * The returned GNCPrice may be in either direction so check to ensure that its
415  * value is correctly applied.
416  * @param db The pricedb
417  * @param commodity The first commodity
418  * @param currency The second commodity
419  * @return A GNCPrice or NULL if no price exists.
420  */
421 GNCPrice   * gnc_pricedb_lookup_latest(GNCPriceDB *db,
422                                        const gnc_commodity *commodity,
423                                        const gnc_commodity *currency);
424 
425 /** @brief Find the most recent price between a commodity and all other
426  * commodities
427  *
428  * The returned GNCPrices may be in either direction so check to ensure that
429  * their values are correctly applied.
430  * @param db The pricedb
431  * @param commodity The commodity for which to obtain prices
432  * @return A PriceList of prices found, or NULL if none found.
433  */
434 PriceList * gnc_pricedb_lookup_latest_any_currency(GNCPriceDB *db,
435         const gnc_commodity *commodity);
436 
437 /** @brief Report whether the pricedb contains prices for one commodity in
438  * another.
439  *
440  * Does *not* check the reverse direction.
441  * @param db The pricedb to check
442  * @param commodity The commodity to check for the existence of prices
443  * @param currency The commodity in which prices are sought. If NULL reports all
444  * commodities.
445  * @return TRUE if matching prices are found, FALSE otherwise.
446  */
447 gboolean     gnc_pricedb_has_prices(GNCPriceDB *db,
448                                     const gnc_commodity *commodity,
449                                     const gnc_commodity *currency);
450 
451 /** @brief Return all the prices for a given commodity in another.
452  *
453  * Does *not* retrieve reverse prices, i.e. prices of the second commodity in
454  * the first.
455  * @param db The pricedb from which to retrieve prices.
456  * @param commodity The commodity for which prices should be retrieved.
457  * @param currency The commodity in which prices should be quoted. If NULL, all
458  * prices in any commodity are included.
459  * @return A PriceList of matching prices or NULL if none were found.
460 */
461 PriceList * gnc_pricedb_get_prices(GNCPriceDB *db,
462                                    const gnc_commodity *commodity,
463                                    const gnc_commodity *currency);
464 
465 /** @brief Find the price between two commodities at a time64.
466  *
467  * The returned GNCPrice may be in either direction so check to ensure that its
468  * value is correctly applied.
469  * @param db The pricedb
470  * @param commodity The first commodity
471  * @param currency The second commodity
472  * @param t The time64 at which to retrieve the price.
473  * @return A GNCPrice or NULL if none matches.
474  */
475 /* NOT USED */
476 GNCPrice * gnc_pricedb_lookup_at_time64(GNCPriceDB *db,
477                                         const gnc_commodity *commodity,
478                                         const gnc_commodity *currency,
479                                         time64 t);
480 
481 /** @brief Return the price between the two commodities on the indicated
482  * day. Note that the notion of day might be distorted by changes in timezone.
483  *
484  * The returned GNCPrice may be in either direction so check to ensure that its
485  * value is correctly applied.
486  * @param db The pricedb
487  * @param commodity The first commodity
488  * @param currency The second commodity
489  * @param t A time. The price returned will be in the same day as this time
490  * according to the local timezone.
491  * @return A GNCPrice or NULL on failure.
492  */
493 GNCPrice * gnc_pricedb_lookup_day_t64(GNCPriceDB *db,
494                                       const gnc_commodity *commodity,
495                                       const gnc_commodity *currency,
496                                       time64 t);
497 
498 /** @brief Return the price between the two commoditiesz nearest to the given
499  * time.
500  *
501  * The returned GNCPrice may be in either direction so check to ensure that its
502  * value is correctly applied.
503  * @param db The pricedb
504  * @param c The first commodity
505  * @param currency The second commodity
506  * @param t The time nearest to which the returned price should be.
507  * @return A GNCPrice or NULL if no prices exist between the two commodities.
508  */
509 GNCPrice   * gnc_pricedb_lookup_nearest_in_time64(GNCPriceDB *db,
510                                                   const gnc_commodity *c,
511                                                   const gnc_commodity *currency,
512                                                   time64 t);
513 
514 /** @brief Return the price nearest in time to that given between the given
515  * commodity and every other.
516  *
517  * The returned GNCPrices may be in either direction so check to ensure that
518  * their values are correctly applied.
519  *
520  * @param db, The pricedb
521  * @param c, The commodity for which prices should be obtained.
522  * @param t, The time nearest to which the prices should be obtained.
523  * @return A PriceList of prices for each commodity pair found or NULL if none
524  * are.
525  */
526 PriceList * gnc_pricedb_lookup_nearest_in_time_any_currency_t64(GNCPriceDB *db,
527         const gnc_commodity *c,
528         time64 t);
529 
530 /** @brief Return the nearest price between the given commodities before the
531  * given time.
532  *
533  * The returned GNCPrice may be in either direction so check to ensure that its
534  * value is correctly applied.
535  * @param db The pricedb
536  * @param c The first commodity
537  * @param currency The second commodity
538  * @param t The time before which to find the price
539  * @return A GNCPrice or NULL if no prices are found before t.
540  */
541 GNCPrice * gnc_pricedb_lookup_nearest_before_t64 (GNCPriceDB *db,
542                                                   const gnc_commodity *c,
543                                                   const gnc_commodity *currency,
544                                                   time64 t);
545 
546 /** @brief Return the nearest price between the given commodity and any other
547  * before the given time.
548  *
549  * The returned GNCPrice may be in either direction so check to ensure that its
550  * value is correctly applied.
551  * @param db The pricedb
552  * @param c The commodity
553  * @param t The time before which to find prices
554  * @return A PriceList of prices for each commodity found or NULL if none are.
555  */
556 PriceList * gnc_pricedb_lookup_nearest_before_any_currency_t64 (GNCPriceDB *db,
557                                                                 const gnc_commodity *c,
558                                                                 time64 t);
559 
560 /** @brief Retrieve the price one currency to another using the price
561  * nearest to before the given time.
562  * @param pdb The pricedb
563  * @param orig_currency The commodity in which the balance is currently
564  * expressed
565  * @param new_currency The commodity to which the balance should be converted
566  * @param t The time to be used for for comparison
567  * @return A price, or gnc_numeric_zero if no price is available.
568  */
569 gnc_numeric gnc_pricedb_get_nearest_before_price (GNCPriceDB *pdb,
570                                                   const gnc_commodity *orig_currency,
571                                                   const gnc_commodity *new_currency,
572                                                   const time64 t);
573 
574 /** @brief Retrieve the price one currency to another using the price
575  * nearest to the given time
576  * @param pdb The pricedb
577  * @param orig_currency The commodity in which the balance is currently
578  * expressed
579  * @param new_currency The commodity to which the balance should be converted
580  * @param t The time in which the nearest price should be used.
581  * @return A price, or gnc_numeric_zero if no price is available.
582  */
583 gnc_numeric gnc_pricedb_get_nearest_price (GNCPriceDB *pdb,
584                                            const gnc_commodity *orig_currency,
585                                            const gnc_commodity *new_currency,
586                                            const time64 t);
587 
588 /** @brief Retrieve the price one currency to another using the latest price
589  * @param pdb The pricedb
590  * @param orig_currency The commodity in which the balance is currently
591  * expressed
592  * @param new_currency The commodity to which the balance should be converted
593  * @return A price, or gnc_numeric_zero if no price is available.
594  */
595 gnc_numeric gnc_pricedb_get_latest_price (GNCPriceDB *pdb,
596                                           const gnc_commodity *orig_currency,
597                                           const gnc_commodity *new_currency);
598 
599 
600 /** @brief Convert a balance from one currency to another using the most recent
601  * price between the two.
602  * @param pdb The pricedb
603  * @param balance The balance to be converted
604  * @param balance_currency The commodity in which the balance is currently
605  * expressed
606  * @param new_currency The commodity to which the balance should be converted
607  * @return A new balance or gnc_numeric_zero if no price is available.
608  */
609 gnc_numeric
610 gnc_pricedb_convert_balance_latest_price(GNCPriceDB *pdb,
611                                          gnc_numeric balance,
612                                          const gnc_commodity *balance_currency,
613                                          const gnc_commodity *new_currency);
614 
615 /** @brief Convert a balance from one currency to another using the price
616  * nearest to the given time.
617  * @param pdb The pricedb
618  * @param balance The balance to be converted
619  * @param balance_currency The commodity in which the balance is currently
620  * expressed
621  * @param new_currency The commodity to which the balance should be converted
622  * @param t The time nearest to which price should be used.
623  * @return A new balance or gnc_numeric_zero if no price is available.
624  */
625 gnc_numeric
626 gnc_pricedb_convert_balance_nearest_price_t64(GNCPriceDB *pdb,
627                                               gnc_numeric balance,
628                                               const gnc_commodity *balance_currency,
629                                               const gnc_commodity *new_currency,
630                                               time64 t);
631 
632 /** @brief Convert a balance from one currency to another using the price
633  * nearest to before the given time.
634  * @param pdb The pricedb
635  * @param balance The balance to be converted
636  * @param balance_currency The commodity in which the balance is currently
637  * expressed
638  * @param new_currency The commodity to which the balance should be converted
639  * @param t The time in which the last price before it should be used.
640  * @return A new balance or gnc_numeric_zero if no price is available.
641  */
642 gnc_numeric
643 gnc_pricedb_convert_balance_nearest_before_price_t64 (GNCPriceDB *pdb,
644                                                      gnc_numeric balance,
645                                                      const gnc_commodity *balance_currency,
646                                                      const gnc_commodity *new_currency,
647                                                      time64 t);
648 
649 typedef gboolean (*GncPriceForeachFunc)(GNCPrice *p, gpointer user_data);
650 
651 /** @brief Call a GncPriceForeachFunction once for each price in db, until the
652  * function returns FALSE.
653  *
654  * If stable_order is not FALSE, make sure the ordering of the traversal is
655  * stable (i.e. the same order every time given the same db contents -- stable
656  * traversals may be less efficient).
657  * @param db The pricedb
658  * @param f The function to call
659  * @param user_data A data to pass to each invocation of f
660  * @param stable_order Ensure that the traversal is performed in the same order
661  * each time.
662  * @return TRUE if all calls to f succeeded (unstable) or if the order of
663  * processing was the same as the previous invocation (stable), FALSE otherwise.
664  */
665 gboolean     gnc_pricedb_foreach_price(GNCPriceDB *db,
666                                        GncPriceForeachFunc f,
667                                        gpointer user_data,
668                                        gboolean stable_order);
669 
670 /** @brief Get the number of prices, in any currency, for a given commodity.
671  * @param db The pricedb
672  * @param c The commodity
673  * @return The number of prices in the database for this commody, zero if none
674  */
675 int
676 gnc_pricedb_num_prices(GNCPriceDB *db,
677                        const gnc_commodity *c);
678 
679 /** @brief Get the nth price for the given commodity in  reverse date order
680  * @param db The pricedb
681  * @param c The commodity whose nth price is needed
682  * @param n Zero based index of the price wanted
683  * @return The nth price for this commodity in reverse chronological order, without
684  * regard for what currency the price is in
685  */
686 GNCPrice *
687 gnc_pricedb_nth_price (GNCPriceDB *db,
688                        const gnc_commodity *c,
689                        const int n);
690 
691 void gnc_pricedb_nth_price_reset_cache (GNCPriceDB *db);
692 
693 /* The following two convenience functions are used to test the xml backend */
694 /** @brief Return the number of prices in the database.
695  *
696  * For XML Backend Testing
697  */
698 guint gnc_pricedb_get_num_prices(GNCPriceDB *db);
699 
700 /** @brief Test equality of two pricedbs
701  *
702  * For XML Backend Testing */
703 gboolean gnc_pricedb_equal (GNCPriceDB *db1, GNCPriceDB *db2);
704 
705 /** @name Internal/Debugging
706     @{ */
707 /** This simple function can be useful for debugging the pricedb code */
708 void gnc_pricedb_print_contents(GNCPriceDB *db, FILE *f);
709 /** @} */
710 
711 /** @name Price Parameter Names
712  *  For use with QofQuery
713  */
714 /**@{*/
715 #define PRICE_COMMODITY  "price-commodity"
716 #define PRICE_CURRENCY   "price-currency"
717 #define PRICE_DATE       "price-date"
718 #define PRICE_SOURCE     "price-source"
719 #define PRICE_TYPE       "price-type"
720 #define PRICE_VALUE      "price-value"
721 /**@}*/
722 
723 /** @} */
724 
725 #ifdef __cplusplus
726 } /* extern "C" */
727 #endif
728 
729 #endif /* GNC_PRICEDB_H */
730 /** @} */
731 /** @} */
732