The standard Reporting plugin provides the ability to generate reports based on historical data from many different sources.

Collections define a set of data/statistics/filters related to a type of StoreObject.


Collections are defined by implementing the "std:reporting:discover_collections" service and passing a function with an argument that will be the collection discover() function when called.

The discover function takes three arguments, a unique internal name for the collection, a human readable title/description, and an optional list of categories.

For example, to define a new collection:

P.implementService("std:reporting:discover_collections", function(discover) {
    discover("example", "Example Collection");


Collections are setup by implementing the "std:reporting:collection:COLLECTION_NAME:setup" service which passes in the collection object which can then be used to add facts, statistics, filters and properties.

This service can be implemented in any plugin, which allows plugins to add their facts about their own functionality/data to a collection.

P.implementService("std:reporting:collection:example:setup", function(collection) {

In addition, the wildcard "std:reporting:collection:*:setup" service is called to allow plugins to configure every collection.

Functions called on the collection object return themselves, and so can be chained.

Direct access

Collections can also be accessed directly by using P.reporting.collection. This returns the collection object, for use outside of a dashboard.

This should only be used for querying the underlying data. Any setup or modifications should be carried out inside the setup functions.


property name

Name of the collection.

property description

Readable description of the collection.

property isCollection

Always true.

property isUpdatingFacts

true if the Collection is known to be out of date and is updating facts in the background.

function fact(name, type, description)

Define a fact. name must be unique within the collection. description is the human readable name of the fact shown in the admin UI and in Dashboards when no heading is defined.

type may be any valid database type.

Note there is an implicit "ref" fact, which is the ref of the object being reported on.

In addition to the standard database types, the following types are also allowed as convenience methods

Name Data type JavaScript type
end-date Date Date

end-date is a convenience type useful for specifying facts that use the end property of a platform Datetime region.

function indexedFact(name, type, description)

As fact(), but a database index is created for the fact to improve the speed of filtering. Use only if you know it’s required.

function property(name)

Retrieve the user defined property for the given name, returning undefined if the property has not been set.

function property(name, value)

Set the user defined property for name to value. If the property is already defined, an exception will be thrown.

function statistic(specification)

Defines a statistic using specification. The specification must define an aggregate function to use or a calculate function that can be called to generate the statistic value.

specification is an object with the following properties:

Property Description
name Unique statistic name
description Human readable name for displaying in the UI
filter The filter to apply to the collection
aggregate The aggregate function to use to generate the statistic value
calculate A function with two arguments, a DatabaseQuery object and a context, which is either a collection or a dashboard and implements property().

function filter(name, filterFunction)

Defines a named filter on the collection. filterFunction is passed the select object which is used to filter the collection.

name is either a string, or one of the specially defined named filters which are available via the collection object.

Filter Description
collection.FILTER_ALL Filter applied to every usage of the collection
collection.FILTER_DEFAULT Filter applied to the collection if no filters are specified

function currentObjectsOfType(type, type2, …)

Tells the collection what object Types the collection should be storing facts for, every object of type type will be included in the collection.

This is a shortcut for implementing functions for currentObjects() and objectIsValidForCollection().

type arguments should be defined in the schema requirements

Multiple types can be specified by passing additional arguments.

This should only be called in the owning plugin.

function currentObjects(fn)

It is probably easier to use currentObjectsOfType() than this function, but if you do use it, remember to implement objectIsValidForCollection() too.

fn is a function which returns an Array or StoreQueryResults containing all StoreObject which are currently members of the collection.

fn is called when the collection is rebuilt to determine the current collection membership.

function objectIsValidForCollection(fn)

fn is called with a StoreObject as a single argument, and must return true if this object is currently a member of the collection.

function collectAllFactsInBackground()

Initiate a full rebuild of the collection.

function selectAllCurrentRows(filterName)

Returns all current rows from the collection.

The optional argument filterName is the name of one of the filters defined on the collection, and is used to restrict the rows returned from the query.

function selectAllRowsAtTime(date, filterName)

Returns rows from the collection for the data that was current at date.

The optional argument filterName is the name of one of the filters defined on the collection, and is used to restrict the rows returned from the query.


The following example shows a minimal collection implementation.

P.implementService("std:reporting:collection:books:setup", function(collection) {
        fact("title", "text", "Book title").
        fact("isCheckedOut", "boolean", "Book is checked out").
        fact("timesLoaned", "int", "Number of times book has been loaned").
            name: "checkedOut", description: "Number of books checked out",
            filter: function(select) { select.where("isCheckedOut","=",true); },
            aggregate: "COUNT"
        filter("neverLoaned", function(select) { select.where("timesLoaned","=",0); }).