Release Notes — v0.3.0 (November 5, 2026)

Incompatible release. v0.3.0 changes the report authoring API, the report data model and the designer configuration format. Read the upgrade notes before deploying over a 0.2.x installation.

This release makes reporting a first-class framework subsystem: reusable data sources, database-backed report publishing, an advanced tabular designer, report placement in the module sidebar and document ribbons, and a single-parent report API. It also ships the workflow condition, approval-threshold and notification work that was staged after v0.2.22.

1. Unified single-inheritance report API

Report authors now inherit exactly one base from enezareporting/report_base.py:

  • BaseReportView
  • TabularReportView
  • SummaryReportView
  • DetailedReportView
  • CrosstabReportView
  • TimeSeriesReportView
  • DrillDownReportView
  • DocumentReportView

Each base contains its report type definition, view/dispatch machinery, designer rendering, query-builder filters and optional totals, so ReportEngineView, DesignTemplateMixin and TabularReportTotalsMixin no longer need to be combined by hand.

python
# New single-parent form
from enezareporting.report_base import TabularReportView


class SalesReport(TabularReportView):
    report_model = SalesOrder
    columns = [...]

Legacy two-parent definitions still work but emit DeprecationWarning:

python
# Deprecated
from enezareporting.report_types import TabularReport
from enezareporting.views import ReportEngineView


class SalesReport(TabularReport, ReportEngineView):
    ...

All in-repository definitions and developer documentation were migrated to the new bases.

2. Reusable data sources and dynamic publishing

  • New ReportDataSource model: one reusable row per registered report class, with module ownership, default query/parameter configuration, cached field metadata, entity scoping, active/stale state and dependency protection.
  • ReportDesign gained status, module, data_source, sidebar menu fields, access_code, publication metadata and seed-management fields.
  • Published designs receive a stable /reports/<slug>/ URL without a per-report Python view or URL entry.
  • A Reports fasttab is injected into each module sidebar and lists only reports owned by that module.
  • RBAC targets are generated per report (output.enezareporting.report.<slug>.<variant>); an optional access_code adds an extra gate.
  • Seeding and portability use a versioned JSON bundle with sync_report_data_sources, export_report_definitions and seed_reports.

Existing designs are migrated as published with legacy access and are not injected into every sidebar by default.

3. Advanced tabular report designer

  • Structured column configuration with formatting, visibility, headings and widths.
  • Multi-level sorting with priority, null and case controls.
  • Multi-level grouping with group headers/footers, subtotals and collapse.
  • Safe calculated-field expressions with validation, dependency checks and a formula builder UI.
  • Conditional formatting at cell, column and row level.
  • Configurable summary rows, running totals and custom summary expressions.
  • Hierarchy/master-detail tables, configurable pagination and repeated headers.
  • Pivot configuration backed by the existing crosstab generator.
  • Table-level limits and section-level validation.
  • Table Settings are separated from Report Settings: each table element owns its complete configuration and executes independently.

4. Report placement and system shell

  • Manage Reports uses the standard application layout (top bar, module sidebar and ribbon).
  • Creating a report starts with data-source selection and placement, then opens the designer.
  • Document reports are published to the record detail Reports tab for their document model and receive the open record id.
  • Document placement supports a configurable command icon and ribbon group name.
  • Tabular and other non-document reports target the module's Reports sidebar group.
  • Reports appear only after publication, with an active and non-stale data source.

5. Page geometry, millimetre widths and print parity

  • Column widths are stored and rendered in millimetres. The designer, preview, viewer, browser print and print-to-PDF render the same widths.
  • The designer reports total column width versus table box and page content width, and offers fit-to-box and fit-to-page actions instead of silently scaling.
  • Legacy pixel widths are migrated by preserving their rendered proportions.
  • Canonical page-size values are composite: A4 Landscape, A4 Portrait, A5 Landscape, A5 Portrait, Letter Landscape, Letter Portrait, A3 Landscape, A3 Portrait, Legal Landscape, Legal Portrait. Plain values plus pageOrientation remain supported for backward compatibility.
  • Page settings survive the designer save/reload cycle and are applied consistently in the viewer, print and PDF export.
  • The footer remains bottom-anchored, and the body table fills the remaining page body.
  • Designer reports now export via browser print-to-PDF. ExportToPDF remains available for non-designer report types.

6. Workflow engine additions

  • State-based Condition nodes driven by a SavedQuery, with automatic true/false routing and condition_failure_behavior.
  • State approval thresholds: single_approver, majority_approver and all_approver, using per-target votes from users or expanded group members.
  • Per-state assignment notification templates and an optional originator notification.
  • workflow.link_to_web and action_url resolve to the workflow document detail URL on the current request domain.
  • Migration 0013_state_condition_threshold_notifications.py.

7. Fixes

  • Workflow version cloning preserves state transition conditions, condition mode, condition result and comment requirements.
  • State assignment notification idempotency includes the step instance so re-entering a state sends a new notification.
  • State assignment emails resolve the per-state template explicitly, fall back to the active version's template for in-flight instances, and warn when the configured template is inactive/unpublished or missing.

8. Migrations

Run python manage.py migrate for:

  • enezareporting/0002_report_data_source_and_publication.py
  • enezareporting/0003_migrate_report_designs.py
  • enezareporting/0004_report_placement.py
  • enezareporting/0005_recompile_table_widths.py
  • enezaworkflowengine/0013_state_condition_threshold_notifications.py

9. Upgrading from 0.2.x

  1. Run the migrations above.
  2. Run python manage.py sync_report_data_sources.
  3. Replace class X(TabularReport, ReportEngineView) and mixin-first definitions with the matching *ReportView base from enezareporting.report_base.
  4. Review migrated report designs for module ownership, placement, sidebar visibility and access codes.
  5. Re-save designs that used legacy pixel column widths or report-level table configuration.
  6. Use seed_reports for versioned bundles and export_report_definitions to export the current set.
  7. Update any tooling that consumed the old report-level table configuration or server-side designer PDF export.

Packaging

  • Version bumped to 0.3.0 in setup.py, eneza/__init__.py and eneza/templates/project/requirements.txt.
  • Generated projects now require enezaframework==0.3.0.

Validation

Per project rules, the developer or agent does not run or claim test results. The user is solely responsible for all testing and validation of migrations, report rendering, print/PDF output, RBAC, seeding and workflow behaviour.