Report Types Overview

Developer guide for the Enezaframework reporting engine. Part of the Add Report series.

Table of Contents

  1. Overview
  2. The Unified Base Hierarchy
  3. Common Attributes
  4. Choosing a Report Type
  5. How a Report Type Is Registered
  6. Required-Attribute Validation
  7. Related Guides

Overview

Every report is built from a unified report base in enezareporting.report_base — a single class that declares the shape of the report and already includes the view, designer rendering, query-builder filters, and totals hooks. Inherit exactly one base:

python
from enezareporting.report_base import TabularReportView

class MyReport(TabularReportView):
    ...

The pure type classes in enezareporting.report_types remain the metadata and validation layer used internally. See Report Views.


The Unified Base Hierarchy

classDiagram
    class BaseReportView {
        <<abstract>>
        +report_model
        +parameter_spec
        +columns
        +design_slug
        +add_totals
    }
    class TabularReportView
    class SummaryReportView
    class DetailedReportView
    class CrosstabReportView
    class TimeSeriesReportView
    class DrillDownReportView
    class DocumentReportView
    class BaseDocumentReport

    BaseReportView <|-- TabularReportView
    BaseReportView <|-- CrosstabReportView
    BaseReportView <|-- TimeSeriesReportView
    BaseReportView <|-- DrillDownReportView
    TabularReportView <|-- SummaryReportView
    TabularReportView <|-- DetailedReportView
    BaseDocumentReport <|-- DocumentReportView
Unified base Layout Default parameters Dedicated guide
DocumentReportView Header + lines + totals DocumentParam("document_id") Document Reports
TabularReportView Rows + aggregates DateRangeParam("date_range") Tabular Reports
SummaryReportView Aggregates only, no detail rows inherited from TabularReportView Tabular Reports
DetailedReportView Full granular rows, no aggregation inherited from TabularReportView Tabular Reports
CrosstabReportView 2D pivot none (add your own) Crosstab Reports
TimeSeriesReportView Chronological buckets none (add your own) Time Series Reports
DrillDownReportView Hierarchical levels empty ParameterSet() Drill-Down Reports

Common Attributes

These attributes are available on every unified base (inherited from the metadata layer in enezareporting/report_types.py and the view layer in enezareporting/views.py):

Attribute Type Purpose
report_model model class The main Django model for the report.
parameter_spec ParameterSet Filter parameters used to build the form.
generator_class class Overrides the generator chosen by the view.
columns list Column definitions: field names, computation names, or callables.
chart_settings list Optional chart configuration.
template_blocks dict Maps template block names to overrides.
queryset queryset Optional pre-filtered queryset.
table_name str If set, a dynamic model is created from this DB table.
auto_discover_filters bool Build the form from the model schema.
date_field str Date field used for date-range filtering.
group_by str Field rows are grouped by.
report_title str Display title (defaults to the class name).
report_slug str URL/identifier slug.
report_name str Name segment used by document-report URL generation.
context_variables list Extra context values.
swap_sign bool Swap debit/credit sign handling.
limit_records int Cap the number of records returned.
default_order_by str Default result ordering.
design_slug str Report designer layout slug; rendering is built into every unified base.
add_totals bool Append a totals row; set totals_group_column and line_total_fields too.
use_query_builder bool Enable the query-builder filter UI.
dashboard_enabled bool Opt the report in as a dashboard data source.

ReportEngineView remains available for advanced/legacy use and can take an explicit report_type_class attribute. Unified bases read the type metadata directly from the class.


Choosing a Report Type

flowchart TD
    START[What does the report show?] --> H{Lines of a single\ndocument?}
    H -->|Yes| DOC[DocumentReportView]
    H -->|No| PIVOT{2D pivot by a field?}
    PIVOT -->|Yes| CROSS[CrosstabReportView]
    PIVOT -->|No| TIME{Buckets over time?}
    TIME -->|Yes| TS[TimeSeriesReportView]
    TIME -->|No| HIER{Drill into levels?}
    HIER -->|Yes| DD[DrillDownReportView]
    HIER -->|No| GROUP{Aggregated rows?}
    GROUP -->|Summary only| SUM[SummaryReportView]
    GROUP -->|Detail rows only| DET[DetailedReportView]
    GROUP -->|Grouped + totals| TAB[TabularReportView]

How a Report Type Is Registered

ReportTypeMeta registers every concrete unified base subclass in the report_type_registry (enezareporting/registry.py:35-47). Abstract bases such as TabularReportView and DocumentReportView are skipped.

python
class ReportTypeMeta(ABCMeta):
    def __new__(mcs, name, bases, namespace):
        cls = super().__new__(mcs, name, bases, namespace)
        if name == "ReportType":
            return cls
        mcs._validate(cls)
        if has_legacy_report_engine_base(bases):
            warnings.warn("... use the unified *ReportView base ...")
        if not namespace.get("__abstract__", False):
            report_type_registry.register(cls)
        return cls

Registering makes the type discoverable by name: report_type_registry.get_by_name("myapp.reports.SalesReport").


Required-Attribute Validation

Several unified bases validate themselves at class-creation time via __init_subclass__ and raise django.core.exceptions.ImproperlyConfigured when a required attribute is missing. Abstract bases are skipped until a concrete report class is defined:

Base Required attributes
DocumentReportView header_fields, line_columns (when header_model is set)
CrosstabReportView crosstab_field, crosstab_columns
TimeSeriesReportView time_series_pattern, time_series_columns, date_field
DrillDownReportView hierarchy (non-empty)

DrillDownReportView clamps max_depth to the size of the hierarchy with min(max_depth, len(hierarchy)).