Began initial work to support specifying a series of commodities to -V.
This commit is contained in:
parent
e914b476e9
commit
697f6a6bce
3 changed files with 107 additions and 57 deletions
|
|
@ -290,7 +290,7 @@ void read_commodity_base_extra(const char *& data,
|
||||||
// duplicated (and thus not lost when the journal's item_pool is deleted).
|
// duplicated (and thus not lost when the journal's item_pool is deleted).
|
||||||
if (! commodity->history)
|
if (! commodity->history)
|
||||||
commodity->history = commodity_t::history_t();
|
commodity->history = commodity_t::history_t();
|
||||||
commodity->history->prices.insert(commodity_t::base_t::history_pair(when, amt));
|
commodity->history->prices.insert(commodity_t::history_t::value_type(when, amt));
|
||||||
|
|
||||||
read_history = true;
|
read_history = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,54 +45,83 @@ namespace ledger {
|
||||||
|
|
||||||
void commodity_t::add_price(const datetime_t& date, const amount_t& price)
|
void commodity_t::add_price(const datetime_t& date, const amount_t& price)
|
||||||
{
|
{
|
||||||
if (! base->history)
|
if (! base->varied_history)
|
||||||
base->history = history_t();
|
base->varied_history = varied_history_t();
|
||||||
|
|
||||||
history_map::iterator i = base->history->prices.find(date);
|
optional<history_t&> hist = history(price.commodity());
|
||||||
if (i != base->history->prices.end()) {
|
if (! hist) {
|
||||||
|
std::pair<history_by_commodity_map::iterator, bool> result
|
||||||
|
= base->varied_history->insert(history_by_commodity_map::value_type
|
||||||
|
(&price.commodity(), history_t()));
|
||||||
|
assert(result.second);
|
||||||
|
hist = (*result.first).second;
|
||||||
|
}
|
||||||
|
assert(hist);
|
||||||
|
|
||||||
|
history_map::iterator i = hist->prices.find(date);
|
||||||
|
if (i != hist->prices.end()) {
|
||||||
(*i).second = price;
|
(*i).second = price;
|
||||||
} else {
|
} else {
|
||||||
std::pair<history_map::iterator, bool> result
|
std::pair<history_map::iterator, bool> result
|
||||||
= base->history->prices.insert(history_map::value_type(date, price));
|
= hist->prices.insert(history_map::value_type(date, price));
|
||||||
assert(result.second);
|
assert(result.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool commodity_t::remove_price(const datetime_t& date)
|
bool commodity_t::remove_price(const datetime_t& date, const commodity_t& comm)
|
||||||
{
|
{
|
||||||
if (base->history) {
|
if (base->varied_history) {
|
||||||
history_map::size_type n = base->history->prices.erase(date);
|
optional<history_t&> hist = history(comm);
|
||||||
|
if (hist) {
|
||||||
|
history_map::size_type n = hist->prices.erase(date);
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
if (base->history->prices.empty())
|
if (hist->prices.empty())
|
||||||
base->history.reset();
|
hist.reset();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<amount_t> commodity_t::value(const optional<datetime_t>& moment)
|
optional<amount_t>
|
||||||
|
commodity_t::value(const optional<datetime_t>& moment,
|
||||||
|
const optional<std::vector<const commodity_t *> >& commodities)
|
||||||
{
|
{
|
||||||
optional<datetime_t> age;
|
optional<datetime_t> age;
|
||||||
optional<amount_t> price;
|
optional<amount_t> price;
|
||||||
|
optional<history_t&> hist;
|
||||||
|
|
||||||
if (base->history) {
|
if (base->varied_history) {
|
||||||
assert(base->history->prices.size() > 0);
|
const commodity_t * comm = NULL;
|
||||||
|
if (commodities) {
|
||||||
|
// Walk the list of commodities, finding the first one applicable
|
||||||
|
comm = commodities->back();
|
||||||
|
} else {
|
||||||
|
if (base->varied_history->size() > 1)
|
||||||
|
throw_(commodity_error,
|
||||||
|
"Cannot find commodity value: multiple possibilities exist");
|
||||||
|
comm = (*base->varied_history->begin()).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
hist = history(*comm);
|
||||||
|
if (hist) {
|
||||||
|
assert(hist->prices.size() > 0);
|
||||||
|
|
||||||
if (! moment) {
|
if (! moment) {
|
||||||
history_map::reverse_iterator r = base->history->prices.rbegin();
|
history_map::reverse_iterator r = hist->prices.rbegin();
|
||||||
age = (*r).first;
|
age = (*r).first;
|
||||||
price = (*r).second;
|
price = (*r).second;
|
||||||
} else {
|
} else {
|
||||||
history_map::iterator i = base->history->prices.lower_bound(*moment);
|
history_map::iterator i = hist->prices.lower_bound(*moment);
|
||||||
if (i == base->history->prices.end()) {
|
if (i == hist->prices.end()) {
|
||||||
history_map::reverse_iterator r = base->history->prices.rbegin();
|
history_map::reverse_iterator r = hist->prices.rbegin();
|
||||||
age = (*r).first;
|
age = (*r).first;
|
||||||
price = (*r).second;
|
price = (*r).second;
|
||||||
} else {
|
} else {
|
||||||
age = (*i).first;
|
age = (*i).first;
|
||||||
if (*moment != *age) {
|
if (*moment != *age) {
|
||||||
if (i != base->history->prices.begin()) {
|
if (i != hist->prices.begin()) {
|
||||||
--i;
|
--i;
|
||||||
age = (*i).first;
|
age = (*i).first;
|
||||||
price = (*i).second;
|
price = (*i).second;
|
||||||
|
|
@ -105,12 +134,13 @@ optional<amount_t> commodity_t::value(const optional<datetime_t>& moment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (! has_flags(COMMODITY_STYLE_NOMARKET) && parent().get_quote) {
|
if (! has_flags(COMMODITY_STYLE_NOMARKET) && parent().get_quote) {
|
||||||
if (optional<amount_t> quote = parent().get_quote
|
if (optional<amount_t> quote = parent().get_quote
|
||||||
(*this, age, moment,
|
(*this, age, moment,
|
||||||
(base->history && base->history->prices.size() > 0 ?
|
(hist && hist->prices.size() > 0 ?
|
||||||
(*base->history->prices.rbegin()).first : optional<datetime_t>())))
|
(*hist->prices.rbegin()).first : optional<datetime_t>())))
|
||||||
return *quote;
|
return *quote;
|
||||||
}
|
}
|
||||||
return price;
|
return price;
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,8 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
DECLARE_EXCEPTION(commodity_error, std::runtime_error);
|
||||||
|
|
||||||
class commodity_t
|
class commodity_t
|
||||||
: public delegates_flags<>,
|
: public delegates_flags<>,
|
||||||
public equality_comparable1<commodity_t, noncopyable>
|
public equality_comparable1<commodity_t, noncopyable>
|
||||||
|
|
@ -63,13 +65,16 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::map<const datetime_t, amount_t> history_map;
|
typedef std::map<const datetime_t, amount_t> history_map;
|
||||||
typedef std::pair<const datetime_t, amount_t> history_pair;
|
|
||||||
|
|
||||||
struct history_t {
|
struct history_t {
|
||||||
history_map prices;
|
history_map prices;
|
||||||
ptime last_lookup;
|
ptime last_lookup;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::map<const commodity_t *, history_t> history_by_commodity_map;
|
||||||
|
|
||||||
|
typedef history_by_commodity_map varied_history_t;
|
||||||
|
|
||||||
#define COMMODITY_STYLE_DEFAULTS 0x00
|
#define COMMODITY_STYLE_DEFAULTS 0x00
|
||||||
#define COMMODITY_STYLE_SUFFIXED 0x01
|
#define COMMODITY_STYLE_SUFFIXED 0x01
|
||||||
#define COMMODITY_STYLE_SEPARATED 0x02
|
#define COMMODITY_STYLE_SEPARATED 0x02
|
||||||
|
|
@ -82,7 +87,7 @@ public:
|
||||||
amount_t::precision_t precision;
|
amount_t::precision_t precision;
|
||||||
optional<string> name;
|
optional<string> name;
|
||||||
optional<string> note;
|
optional<string> note;
|
||||||
optional<history_t> history;
|
optional<varied_history_t> varied_history;
|
||||||
optional<amount_t> smaller;
|
optional<amount_t> smaller;
|
||||||
optional<amount_t> larger;
|
optional<amount_t> larger;
|
||||||
|
|
||||||
|
|
@ -102,8 +107,11 @@ public:
|
||||||
|
|
||||||
typedef base_t::history_t history_t;
|
typedef base_t::history_t history_t;
|
||||||
typedef base_t::history_map history_map;
|
typedef base_t::history_map history_map;
|
||||||
|
typedef base_t::varied_history_t varied_history_t;
|
||||||
typedef uint_least32_t ident_t;
|
typedef uint_least32_t ident_t;
|
||||||
|
|
||||||
|
typedef base_t::history_by_commodity_map history_by_commodity_map;
|
||||||
|
|
||||||
shared_ptr<base_t> base;
|
shared_ptr<base_t> base;
|
||||||
|
|
||||||
commodity_pool_t * parent_;
|
commodity_pool_t * parent_;
|
||||||
|
|
@ -188,14 +196,30 @@ public:
|
||||||
base->larger = arg;
|
base->larger = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<history_t> history() const {
|
optional<varied_history_t&> varied_history() const {
|
||||||
return base->history;
|
if (base->varied_history)
|
||||||
|
return *base->varied_history;
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
optional<history_t&> history(const commodity_t& comm) const {
|
||||||
|
if (base->varied_history) {
|
||||||
|
history_by_commodity_map::iterator i = base->varied_history->find(&comm);
|
||||||
|
if (i != base->varied_history->end())
|
||||||
|
return (*i).second;
|
||||||
|
}
|
||||||
|
return none;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_price(const datetime_t& date, const amount_t& price);
|
void add_price(const datetime_t& date, const amount_t& price);
|
||||||
bool remove_price(const datetime_t& date);
|
bool remove_price(const datetime_t& date, const commodity_t& comm);
|
||||||
|
|
||||||
optional<amount_t> value(const optional<datetime_t>& moment = none);
|
optional<amount_t>
|
||||||
|
value(const optional<datetime_t>& moment = none,
|
||||||
|
const optional<std::vector<const commodity_t *> >& commodities = none);
|
||||||
|
|
||||||
|
static void exchange(commodity_t& commodity,
|
||||||
|
const amount_t& per_unit_cost,
|
||||||
|
const datetime_t& moment);
|
||||||
|
|
||||||
struct cost_breakdown_t {
|
struct cost_breakdown_t {
|
||||||
amount_t amount;
|
amount_t amount;
|
||||||
|
|
@ -203,10 +227,6 @@ public:
|
||||||
amount_t basis_cost;
|
amount_t basis_cost;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void exchange(commodity_t& commodity,
|
|
||||||
const amount_t& per_unit_cost,
|
|
||||||
const datetime_t& moment);
|
|
||||||
|
|
||||||
static cost_breakdown_t exchange(const amount_t& amount,
|
static cost_breakdown_t exchange(const amount_t& amount,
|
||||||
const amount_t& cost,
|
const amount_t& cost,
|
||||||
const bool is_per_unit = false,
|
const bool is_per_unit = false,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue