reasoncorp/dossier

Question: Is there a correct way to add a total or summary row?

Opened this issue · 2 comments

Hello,

I'm trying to add a total row by adding up values from the results, something like this in my class

  def results
    original_results = super
    total_value = original_results.rows.map {|row| row.last.to_f}.sum.round(2)
    original_results.rows << ['Total', total_value.to_s]
    original_results
  end

This somewhat works however now my report has 2 additional rows:

Total 4546.1
Total 9092.2

The first one is correct, the second is exactly double. Is there a recommended way of adding a total or summary row? Thanks for the help.

@hughkelsey I'm not sure why your example doesn't work (all I've done is read it), but if I recall correctly, I think I once did totals by doing a UNION query to add a row to the SQL results and giving Dossier a footer parameter of 1, so that it renders the last 1 row of SQL results as a footer.

Does that make sense?

I do like your idea of doing it in Ruby, though. If you want to debug what's happening in your example, bundle open dossier will let you add puts statements or whatever, and gem pristine dossier will clean up for you when you're done.

In case anyone faces this issue, the problem seems to be that report.results gets called 4 times in the report show, which adds a row each time and recalculates the sum for all previous rows. I found two ways to get around the issue:

  1. Call report.results only once in the report show, save the result in a temp variable - res = report.results, and use that to render the report.
  2. Use an if statement to stop adding rows once the first one was added
  def results
    original_results = super
    unless original_results.rows.last[0] == 'Total'
      total_value = original_results.rows.map {|row| row.last.to_f}.sum.round(2)
      original_results.rows << ['Total', total_value.to_s]
    end
    original_results
  end

Neither of those two solutions seems particularly elegant. I tried using report.results.body and report.results.footers to do the calculation instead but that didn't work since the gem automatically assigns the last N rows as footers then puts whatever is left in the body.

It could be worth considering a way to add N empty footers which the user can then fill as needed instead of splitting one dataset between body and footers.