[cli-reports] run reports from cli

This commit is contained in:
Christopher Lam
2020-05-29 20:13:54 +08:00
committed by John Ralls
parent 1ea284d868
commit b34913feda
4 changed files with 178 additions and 0 deletions

View File

@@ -56,6 +56,9 @@ namespace Gnucash {
void configure_program_options (void);
bool m_add_quotes;
std::string run_report;
std::string export_type;
std::string output_file;
};
}
@@ -75,6 +78,15 @@ Gnucash::GnucashCli::parse_command_line (int argc, char **argv)
if (m_opt_map.count ("namespace"))
gnc_prefs_set_namespace_regexp(m_opt_map["namespace"].
as<std::string>().c_str());
if (m_opt_map.count ("run-report"))
run_report = m_opt_map["run-report"].as<std::string>();
if (m_opt_map.count ("export-type"))
export_type = m_opt_map["export-type"].as<std::string>();
if (m_opt_map.count ("output-file"))
output_file = m_opt_map["output-file"].as<std::string>();
}
// Define command line options specific to gnucash-cli.
@@ -85,6 +97,12 @@ Gnucash::GnucashCli::configure_program_options (void)
quotes_options.add_options()
("add-price-quotes", bpo::bool_switch(),
N_("Add price quotes to given GnuCash datafile.\n"))
("run-report", bpo::value<std::string>(),
N_("Runs a report\n"))
("export-type", bpo::value<std::string>(),
N_("Specify export type\n"))
("output-file", bpo::value<std::string>(),
N_("Output file for report\n"))
("namespace", bpo::value<std::string>(),
N_("Regular expression determining which namespace commodities will be retrieved"));

View File

@@ -44,6 +44,13 @@ extern "C" {
namespace bl = boost::locale;
struct run_report_args {
const char *file_to_load;
const char *run_report;
const char *export_type;
const char *output_file;
};
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_GUI;
@@ -108,6 +115,84 @@ fail:
gnc_shutdown(1);
}
static void
report_session_percentage (const char *message, double percent)
{
static double previous = 0.0;
if ((percent - previous) < 5.0)
return;
fprintf (stderr, "\r%3.0f%% complete...", percent);
previous = percent;
return;
}
static void
scm_run_report (void *data,
[[maybe_unused]] int argc, [[maybe_unused]] char **argv)
{
auto args = static_cast<run_report_args*>(data);
QofSession *session = NULL;
SCM cmdline, report, type, file;
const gchar *datafile;
scm_c_eval_string("(debug-set! stack 200000)");
scm_c_use_module ("gnucash utilities");
scm_c_use_module ("gnucash app-utils");
scm_c_use_module ("gnucash reports");
// gnc_report_init ();
// load_system_config();
// load_user_config();
gnc_prefs_init ();
qof_event_suspend ();
datafile = args->file_to_load;
cmdline = scm_c_eval_string ("gnc:cmdline-run-report");
report = scm_from_utf8_string (args->run_report);
type = args->export_type ? scm_from_utf8_string (args->export_type) : SCM_BOOL_F;
file = args->output_file ? scm_from_utf8_string (args->output_file) : SCM_BOOL_F;
/* dry-run? is #t: try report, check validity of options */
if (scm_is_false (scm_call_4 (cmdline, report, type, file, SCM_BOOL_T)))
goto fail;
fprintf (stderr, "Loading datafile %s...\n", datafile);
session = gnc_get_current_session ();
if (!session) goto fail;
qof_session_begin (session, datafile, TRUE, FALSE, FALSE);
if (qof_session_get_error (session) != ERR_BACKEND_NO_ERR) goto fail;
qof_session_load (session, report_session_percentage);
if (qof_session_get_error (session) != ERR_BACKEND_NO_ERR) goto fail;
fprintf (stderr, "\n");
/* dry-run? is #f: run the report */
scm_call_4 (cmdline, report, type, file, SCM_BOOL_F);
qof_session_end (session);
if (qof_session_get_error (session) != ERR_BACKEND_NO_ERR) goto fail;
qof_session_destroy (session);
qof_event_resume ();
gnc_shutdown (0);
return;
fail:
if (session)
{
if (qof_session_get_error (session) != ERR_BACKEND_NO_ERR)
g_warning ("Session Error: %d %s",
qof_session_get_error (session),
qof_session_get_error_message (session));
qof_session_destroy (session);
}
qof_event_resume ();
gnc_shutdown (1);
}
int
Gnucash::add_quotes (std::string &uri)
{
@@ -116,3 +201,17 @@ Gnucash::add_quotes (std::string &uri)
return 0;
}
int
Gnucash::run_report (const std::string file_to_load, std::string &run_report,
std::string &export_type, std::string &output_file)
{
auto args = run_report_args { file_to_load.c_str(),
run_report.c_str(),
export_type.c_str(),
output_file.c_str() };
if (not run_report.empty())
scm_boot_guile (0, nullptr, scm_run_report, &args);
return 0;
}

View File

@@ -30,6 +30,8 @@
namespace Gnucash {
int add_quotes (std::string &uri);
int run_report (const std::string file_to_load, std::string &run_report,
std::string &export_type, std::string &output_file);
}
#endif

View File

@@ -772,3 +772,62 @@ not found.")))
(gnc:debug "Renaming report " template-guid)
(gnc:report-template-set-name templ new-name)
(gnc:save-all-reports))))
(define (stderr-log tmpl . args)
(apply format (current-error-port) tmpl args)
#f)
(define (template-export report template export-type output-file dry-run?)
(let* ((report-guid (gnc:report-template-report-guid template))
(parent-template-guid (gnc:report-template-parent-type template))
(parent-template (hash-ref *gnc:_report-templates_* parent-template-guid))
(parent-export-thunk (gnc:report-template-export-thunk parent-template))
(parent-export-types (gnc:report-template-export-types parent-template)))
(cond
((not parent-export-thunk) (stderr-log "Report ~s has no export code\n" report))
((not parent-export-types) (stderr-log "Report ~s has no export-types\n" report))
((not (assoc export-type parent-export-types))
(stderr-log "Export-type disallowed: ~a. Allowed types: ~a\n"
export-type (string-join (map car parent-export-types) ", ")))
((not output-file) (stderr-log "No output file specified\n"))
(dry-run? #t)
(else
(display "Running export..." (current-error-port))
(parent-export-thunk
(gnc-report-find (gnc:make-report report-guid))
(assoc-ref parent-export-types export-type) output-file)
(display "done!\n" (current-error-port))))))
(define-public (gnc:cmdline-run-report report export-type output-file dry-run?)
(let ((template (or (gnc:find-report-template report)
(let lp ((custom-templates (gnc:custom-report-templates-list)))
(cond
((null? custom-templates) #f)
((equal? (gnc:report-template-name (cdar custom-templates))
report) (cdar custom-templates))
(else (lp (cdr custom-templates))))))))
(define (run-report output-port)
(display
(gnc:report-render-html
(gnc-report-find
(gnc:make-report
(gnc:report-template-report-guid template))) #t) output-port))
(cond
((not template)
(stderr-log "Cannot find report ~s. Valid reports are:\n" report)
(for-each
(lambda (template)
(stderr-log "* ~a\n" (gnc:report-template-name (cdr template))))
(gnc:custom-report-templates-list))
#f)
(export-type (template-export report template export-type output-file dry-run?))
(dry-run? #t)
(output-file
(format (current-error-port) "Saving report to ~a..." output-file)
(call-with-output-file output-file run-report)
(display "complete!\n" (current-error-port)))
(else
(run-report (current-output-port))))))