summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/pool.cc72
-rw-r--r--src/pool.h6
-rw-r--r--src/report.cc15
-rw-r--r--src/report.h1
4 files changed, 94 insertions, 0 deletions
diff --git a/src/pool.cc b/src/pool.cc
index 6b422351..ad97a9c6 100644
--- a/src/pool.cc
+++ b/src/pool.cc
@@ -364,4 +364,76 @@ commodity_pool_t::parse_price_expression(const std::string& str,
return NULL;
}
+void commodity_pool_t::print_pricemap(std::ostream& out,
+ const keep_details_t& keep,
+ const optional<datetime_t>& moment)
+{
+ typedef std::map<commodity_t *, commodity_t *> comm_map_t;
+
+ comm_map_t comm_map;
+
+ foreach (const commodities_map::value_type& comm_pair, commodities) {
+ commodity_t * comm(&comm_pair.second->strip_annotations(keep));
+ comm_map.insert(comm_map_t::value_type(comm, NULL));
+ }
+
+ out << "digraph commodities {\n";
+
+ foreach (const comm_map_t::value_type& comm_pair, comm_map) {
+ commodity_t * comm(comm_pair.first);
+ if (comm->has_flags(COMMODITY_BUILTIN))
+ continue;
+
+ out << " ";
+ if (commodity_t::symbol_needs_quotes(comm->symbol()))
+ out << comm->symbol() << ";\n";
+ else
+ out << "\"" << comm->symbol() << "\";\n";
+
+ if (! comm->has_flags(COMMODITY_NOMARKET) &&
+ (! commodity_pool_t::current_pool->default_commodity ||
+ comm != commodity_pool_t::current_pool->default_commodity)) {
+ if (optional<commodity_t::varied_history_t&> vhist =
+ comm->varied_history()) {
+ foreach (const commodity_t::history_by_commodity_map::value_type& pair,
+ vhist->histories) {
+ datetime_t most_recent;
+ amount_t most_recent_amt;
+ foreach (const commodity_t::history_map::value_type& inner_pair,
+ pair.second.prices) {
+ if ((most_recent.is_not_a_date_time() ||
+ inner_pair.first > most_recent) &&
+ (! moment || inner_pair.first <= moment)) {
+ most_recent = inner_pair.first;
+ most_recent_amt = inner_pair.second;
+ }
+ }
+
+ if (! most_recent.is_not_a_date_time()) {
+ out << " ";
+ if (commodity_t::symbol_needs_quotes(comm->symbol()))
+ out << comm->symbol();
+ else
+ out << "\"" << comm->symbol() << "\"";
+
+ out << " -> ";
+
+ if (commodity_t::symbol_needs_quotes(pair.first->symbol()))
+ out << pair.first->symbol();
+ else
+ out << "\"" << pair.first->symbol() << "\"";
+
+ out << " [label=\""
+ << most_recent_amt.number() << "\\n"
+ << format_date(most_recent.date(), FMT_WRITTEN)
+ << "\" fontcolor=\"#008e28\"];\n";
+ }
+ }
+ }
+ }
+ }
+
+ out << "}\n";
+}
+
} // namespace ledger
diff --git a/src/pool.h b/src/pool.h
index c1325944..ac66d7a6 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -131,6 +131,12 @@ public:
const bool add_prices = true,
const optional<datetime_t>& moment = none);
+ // Output the commodity price map for a given date as a DOT file
+
+ void print_pricemap(std::ostream& out,
+ const keep_details_t& keep,
+ const optional<datetime_t>& moment = none);
+
#if defined(HAVE_BOOST_SERIALIZATION)
private:
/** Serialization. */
diff --git a/src/report.cc b/src/report.cc
index 81234b0f..e51736fd 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -842,6 +842,18 @@ value_t report_t::echo_command(call_scope_t& scope)
return true;
}
+value_t report_t::pricemap_command(call_scope_t& scope)
+{
+ interactive_t args(scope, "&s");
+ std::ostream& out(output_stream);
+
+ commodity_pool_t::current_pool->print_pricemap
+ (out, what_to_keep(), args.has(0) ?
+ optional<datetime_t>(datetime_t(parse_date(args.get<string>(0)))) : none);
+
+ return true;
+}
+
option_t<report_t> * report_t::lookup_option(const char * p)
{
switch (*p) {
@@ -1415,6 +1427,9 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
HANDLER(prepend_width_).value.to_long()),
*this, "#pricedb"));
}
+ else if (is_eq(p, "pricemap")) {
+ return MAKE_FUNCTOR(report_t::pricemap_command);
+ }
else if (is_eq(p, "payees")) {
return WRAP_FUNCTOR(reporter<>(new report_payees(*this), *this,
"#payees"));
diff --git a/src/report.h b/src/report.h
index 6fa238f0..99b8781b 100644
--- a/src/report.h
+++ b/src/report.h
@@ -198,6 +198,7 @@ public:
value_t reload_command(call_scope_t&);
value_t echo_command(call_scope_t& scope);
+ value_t pricemap_command(call_scope_t& scope);
keep_details_t what_to_keep() {
bool lots = HANDLED(lots) || HANDLED(lots_actual);