module TrackRecordReport

A container for report code. TrackRecordReport::Report instances are passed to generators - see TrackRecordReportGenerator for details.

A compilable Report sets attributes from parameters passed in, which might be the result of a Rails form submission for a potentially new or edited SavedReport instance - or more commonly, the “attributes()” call result on an existing SavedReport instance. Either way, all the attributes are copied internally with extra processing and filtering, so you can read things like the saved report “range_start_cache” and “range_start_cache” attributes, or instead use the compilable report’s computed “range” property - a Range instance giving the two inclusive Dates for the report start and end.

Once compiled with “compile”, a report can be queried by first iterating over its rows with “each_row”. Discover cells within rows with “each_cell_for”. If parameters tell the report to include per-user data during compilation, then for each row call “each_user_on_row” to enumerate users with relevant data on that row, then for each such user within the row, “each_cell_for_user_on_row” to enumerate the cells giving totals for each user in that row and column (you can also do this manually with “each_cell_for” and the Cell “user_total” method).

Ranges of columns for an x-axis-is-date report can be iterated over with “each_column_range” and human-readable headings generated using “column_heading”. Overall totals for all rows can be obtained with the “each_column_total” iterator. For each object returned, per-user data can be discovered via the “user_total” method if required.

A Report mixes in behaviour from TrackRecordSections so that as well as providing report data, it provides section and group information with per-section/per-section-per-user calculations all integrated. You can use the section interface via the report just as you might use the interface directly via TrackRecordSections::Sections.

If you want to get the sorted array of tasks a compiled report covers, use the “filtered_tasks” property. To see if a report includes per-user details, see if the array in its “users” property is empty. If not, the list of users with non-zero totals for a compiled report can be found in the “filtered_users” array.

Note that if the “filtered_tasks” array is empty after compilation, the report determined that it could perform no useful calculations. Proceed as if the report was never compiled in the first place - don’t attempt to iterate over its rows for example - and just let the user know that the report is ‘empty’ / has no useful data.

A Report itself is a calculation object (see the Calculator and CalculatorWithUsers classes) and its own committed and not-committed hour values represent the overall report total. The rows and cells and various other calculated portions are similarly subclassed. Additonally a final pass over the report’s non-zero hour tasks is made and three numbers generated to indicate overall task results: “total_duration” is a BigDecimal giving the total task duration (for tasks with that set), “total_actual_remaining” is the total duration minus all committed hours (only meaningful if all your reported tasks have valid durations) and “total_potential_remaining” further subtracts not-committed hours, in timesheets which may yet be edited by their owners - hence it is an indication of potential, rather than definite remaining time.

For examples of how all this information can be used, along with where precalculated total information is stored and how to generate your own totals using report calculator objects yourself, examine the CSV export code - see TrackRecordReportGenerator::UkOrgPondCSV inside lib/report_generators/track_record_report_generator_uk_org_pond_csv.rb. You can also consult app/views/reports partials for various report types, though the mixture of ERb code and HTML therein can make it harder to see what’s going on.

Database dependence

For information about this, please see the documentation for TrackRecordReport::Report and the FREQUENCY constant.