static gint default_sort (GNCPrice *price_a, GNCPrice *price_b) { gnc_commodity *curr_a, *curr_b; Timespec ts_a, ts_b; gint result; /* Primary sort (i.e. commodity name) handled by the tree structure. */ /* secondary sort: currency */ curr_a = gnc_price_get_currency (price_a); curr_b = gnc_price_get_currency (price_b); result = safe_utf8_collate (gnc_commodity_get_namespace (curr_a), gnc_commodity_get_namespace (curr_b)); if (result != 0) return result; result = safe_utf8_collate (gnc_commodity_get_mnemonic (curr_a), gnc_commodity_get_mnemonic (curr_b)); if (result != 0) return result; /* tertiary sort: time */ ts_a = gnc_price_get_time (price_a); ts_b = gnc_price_get_time (price_b); result = timespec_cmp (&ts_a, &ts_b); if (result) /* Reverse the result to present the most recent quote first. */ return -result; /* last sort: value */ return gnc_numeric_compare (gnc_price_get_value (price_a), gnc_price_get_value (price_b)); }
/** Adds a split to a transaction. * @param trans The transaction to add a split to * @param account The split's account * @param amount The split's amount * @param rec_state The split's reconcile status * @param rec_date The split's reconcile date * @param price The split's conversion rate from account commodity to transaction commodity */ static void trans_add_split (Transaction* trans, Account* account, GncNumeric amount, const boost::optional<std::string>& action, const boost::optional<std::string>& memo, const boost::optional<char>& rec_state, const boost::optional<GncDate>& rec_date, const boost::optional<GncNumeric> price) { QofBook* book = xaccTransGetBook (trans); auto split = xaccMallocSplit (book); xaccSplitSetAccount (split, account); xaccSplitSetParent (split, trans); xaccSplitSetAmount (split, static_cast<gnc_numeric>(amount)); auto trans_curr = xaccTransGetCurrency(trans); auto acct_comm = xaccAccountGetCommodity(account); GncNumeric value; if (gnc_commodity_equiv(trans_curr, acct_comm)) value = amount; else if (price) value = amount * *price; else { auto time = xaccTransRetDatePosted (trans); /* Import data didn't specify price, let's lookup the nearest in time */ auto nprice = gnc_pricedb_lookup_nearest_in_time64(gnc_pricedb_get_db(book), acct_comm, trans_curr, time); if (nprice) { /* Found a usable price. Let's check if the conversion direction is right */ GncNumeric rate; if (gnc_commodity_equiv(gnc_price_get_currency(nprice), trans_curr)) rate = gnc_price_get_value(nprice); else rate = static_cast<GncNumeric>(gnc_price_get_value(nprice)).inv(); value = amount * rate; } else { PWARN("No price found, using a price of 1."); value = amount; } } xaccSplitSetValue (split, static_cast<gnc_numeric>(value)); if (memo) xaccSplitSetMemo (split, memo->c_str()); /* Note, this function assumes the num/action switch is done at a higher level * if needed by the book option */ if (action) xaccSplitSetAction (split, action->c_str()); if (rec_state && *rec_state != 'n') xaccSplitSetReconcile (split, *rec_state); if (rec_state && *rec_state == YREC && rec_date) xaccSplitSetDateReconciledSecs (split, static_cast<time64>(GncDateTime(*rec_date, DayPart::neutral))); }
/* Get the rate from the price db */ static gnc_numeric gtu_sr_get_rate_from_db (gnc_commodity *from, gnc_commodity *to) { GNCPrice *prc; QofBook *book = gnc_get_current_book (); prc = gnc_pricedb_lookup_latest (gnc_pricedb_get_db (book), from, to); if (!prc) return gnc_numeric_create (100, 100); if (gnc_commodity_equiv(from, gnc_price_get_currency(prc))) return gnc_numeric_invert(gnc_price_get_value(prc)); return gnc_price_get_value(prc); }
static gint sort_by_value (GtkTreeModel *f_model, GtkTreeIter *f_iter_a, GtkTreeIter *f_iter_b, gpointer user_data) { gnc_commodity *comm_a, *comm_b; GNCPrice *price_a, *price_b; gboolean result; gint value; if (!get_prices (f_model, f_iter_a, f_iter_b, &price_a, &price_b)) return sort_ns_or_cm (f_model, f_iter_a, f_iter_b); /* * Sorted by commodity because of the tree structure. Now sort by * currency so we're only comparing numbers in the same currency * denomination. */ comm_a = gnc_price_get_currency (price_a); comm_b = gnc_price_get_currency (price_b); if (comm_a && comm_b) { value = safe_utf8_collate (gnc_commodity_get_namespace (comm_a), gnc_commodity_get_namespace (comm_b)); if (value != 0) return value; value = safe_utf8_collate (gnc_commodity_get_mnemonic (comm_a), gnc_commodity_get_mnemonic (comm_b)); if (value != 0) return value; } /* * Now do the actual price comparison now we're sure that its an * apples to apples comparison. */ result = gnc_numeric_compare (gnc_price_get_value (price_a), gnc_price_get_value (price_b)); if (result) return result; return default_sort (price_a, price_b); }
static xmlNodePtr gnc_price_to_dom_tree(const xmlChar *tag, GNCPrice *price) { xmlNodePtr price_xml; const gchar *typestr, *sourcestr; xmlNodePtr tmpnode; gnc_commodity *commodity; gnc_commodity *currency; Timespec timesp; gnc_numeric value; if (!(tag && price)) return NULL; price_xml = xmlNewNode(NULL, tag); if (!price_xml) return NULL; commodity = gnc_price_get_commodity(price); currency = gnc_price_get_currency(price); if (!(commodity && currency)) return NULL; tmpnode = guid_to_dom_tree("price:id", gnc_price_get_guid(price)); if (!add_child_or_kill_parent(price_xml, tmpnode)) return NULL; tmpnode = commodity_ref_to_dom_tree("price:commodity", commodity); if (!add_child_or_kill_parent(price_xml, tmpnode)) return NULL; tmpnode = commodity_ref_to_dom_tree("price:currency", currency); if (!add_child_or_kill_parent(price_xml, tmpnode)) return NULL; timesp = gnc_price_get_time(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); if (sourcestr && (strlen(sourcestr) != 0)) { tmpnode = text_to_dom_tree("price:source", sourcestr); if (!add_child_or_kill_parent(price_xml, tmpnode)) return NULL; } typestr = gnc_price_get_typestr(price); if (typestr && (strlen(typestr) != 0)) { tmpnode = text_to_dom_tree("price:type", typestr); if (!add_child_or_kill_parent(price_xml, tmpnode)) return NULL; } value = gnc_price_get_value(price); tmpnode = gnc_numeric_to_dom_tree("price:value", &value); if (!add_child_or_kill_parent(price_xml, tmpnode)) return NULL; return price_xml; }
/* Get the rate from the price db */ static gnc_numeric gtu_sr_get_rate_from_db (gnc_commodity *from, gnc_commodity *to) { GNCPrice *prc; gnc_numeric rate_split; gboolean have_rate = FALSE; QofBook *book = gnc_get_current_book (); /* Do we have a rate allready */ prc = gnc_pricedb_lookup_latest (gnc_pricedb_get_db (book), from, to); if (prc) { rate_split = gnc_price_get_value (prc); gnc_price_unref (prc); have_rate = TRUE; } /* Lets try reversing the commodities */ if (!have_rate) { prc = gnc_pricedb_lookup_latest (gnc_pricedb_get_db (book), to, from); if (prc) { rate_split = gnc_numeric_div (gnc_numeric_create (100, 100), gnc_price_get_value (prc), GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE); gnc_price_unref (prc); have_rate = TRUE; } } /* No rate, set to 1/1 */ if (!have_rate) rate_split = gnc_numeric_create (100, 100); return rate_split; }