Pre-alpha. No tagged release and no upgrade path between versions. Use for evaluation and development only, not production.
Core DevPre-alpha

Report engine

Website canonical copy: website/guides/build/report-engine.md mirrors guides/build/report-engine.html. Prefer editing the website HTML, then make docs-mirror.

CSV/PDF download and CSV bulk import for workspace views. The engine lives only in sumeru/ (core/report/, core/sdk/report.go, web handlers, render + JS). Addons enable features with XML on views — no export/import Go code in sumeru_addons/ or sumeru_custom_addons/.

Reporting is opt-in per view. If a view has no report XML or widgets, no Report toolbar appears.

Architecture

flowchart TB
  subgraph addon [Addon XML only]
    ViewXML["view XML: report tag / attrs / widgets"]
  end
  subgraph sumeru_core [sumeru core]
    Parser["parser → CapabilitiesFromView"]
    Render["render: Report toolbar + JS"]
    Web["web handlers"]
    Engine["core/report"]
    BaseWizard["base: sys.bulk.import views"]
    SDK["core/sdk/report.go"]
    Engine --> SDK
    Web --> Engine
    Render --> Web
    BaseWizard --> Engine
  end
  ViewXML --> Parser
  Parser --> Render
LayerLocationRole
Enginesumeru/core/report/Export CSV/PDF, bulk template, staging, mapping preview, import execution
SDKsumeru/core/sdk/report.goStable facade for core and optional addon formatters
Websumeru/core/server/web/Session routes for export, template, upload, confirm, cancel
Rendersumeru/core/engine/render/Toolbar on list/form/kanban when capabilities enabled
Frontendcore/engine/assets/js/ui/report-exchange.jsField picker, download, upload → redirect
Wizard shellsumeru/addons/base/sys.bulk.import model + mapping form XML only

Enable on a view (XML)

Three equivalent ways to declare capabilities. The parser merges them into one capability set.

<view id="view_crm_lead_list" model="crm.lead" type="list">
    <report download="csv,pdf" upload="bulk" pdf_sizes="a4,legal,letter" modes="create,upsert"/>
    <field name="name"/>
    ...
</view>

Option 2 — View attributes

<view type="list" model="product.product"
      report_download="csv,pdf"
      bulk_upload="1"
      pdf_sizes="a4,legal,letter"
      bulk_modes="create,upsert">
    <field name="name"/>
</view>

Option 3 — Header widgets (form or list)

<view type="form" model="crm.lead">
    <header>
        <widget type="report_download" formats="csv,pdf" pdf_sizes="a4,legal,letter"/>
        <widget type="bulk_upload" modes="create,upsert"/>
    </header>
    ...
</view>

XML reference

Attribute / elementValuesMeaning
download / report_download / formatscsv, pdf (comma-separated)Enable report download formats
upload / bulk_uploadbulk, 1, true, yes, onEnable bulk CSV upload
pdf_sizesa4, legal, letterAllowed PDF page sizes (default: all three)
modes / bulk_modescreate, upsertImport modes offered in UI (default: both)

Nested arch roots (, without wrapping ) also support and the view attributes above.

Supported view types

View typeDownload scopeBulk upload
listRows matching the window action domain (max 500)Yes
kanbanSame as listYes
formCurrent record as a single-row exportYes (single-row template)
pivotNot supported in v1No

Download flow

  1. User opens a view with download enabled.
  2. Clicks Report in the toolbar → chooses Download CSV or Download PDF.
  3. Field picker opens (defaults = visible view columns); user selects fields.
  4. For PDF, user picks page size (A4 / Legal / Letter).
  5. Browser downloads the file.

List/kanban exports respect the window action domain (same rows as the current list, capped at 500). Form export uses the open record only.

Bulk upload flow

Bulk import reuses the same engine as export (field whitelist, coercion, ACL). There is no silent direct import — every upload goes through mapping and preview before data is written.

sequenceDiagram
  participant User
  participant View as EnabledView
  participant Engine as core_report
  participant MapForm as sys_bulk_import

  User->>View: Report → Bulk upload
  User->>View: Select fields + import mode
  User->>View: Upload CSV
  View->>Engine: Stage file + create batch
  Engine->>MapForm: Open mapping form
  User->>MapForm: Map columns + Preview tab
  User->>MapForm: Confirm import
  MapForm->>Engine: ExecuteBulkImport
  Engine->>View: Redirect with result message

Step details

StepWhat happens
Field selectionUser picks model fields (same picker as download)
TemplateDownload import template → CSV with headers only for selected fields
UploadPOST /web/bulk/upload — file staged in sys.attachment, batch row sys.bulk.import created
MappingStandard form: Column mapping tab — CSV header → model field (or Skip)
PreviewPreview tab — first 10 rows validated after mapping
ConfirmConfirm import object action → create-only or upsert per batch mode
ResultRedirect back to source view with created / updated / skipped counts

Create only — new rows only. Create or update (upsert) — updates when id is mapped and valid; otherwise creates.

Limits and security

LimitValue
Export row cap500 rows
Upload file size8 MB
Preview validationFirst 10 rows (full validation); remainder counted in total
StagingCSV in sys.attachment; batch on sys.bulk.import; cleaned up after confirm/cancel
CheckRequirement
AuthenticationSigned-in session on all routes
POST requestsCSRF token required
Export / previewRead ACL on target model
ImportCreate (and write for upsert) ACL on target model
FieldsWhitelist from registered model metadata — only declared fields can be exported or imported

What addons may and may not do

AllowedForbidden
Add or widgets to view XMLCustom export/bulk HTTP handlers in addons
sdk.RegisterReportCellFormatter(model, fn) in init()PDF/CSV libraries in addon go.mod
Business data in normal modelsSecond bulk-upload implementation or copied mapping UI

To enable CRM lead export, add one line to the list view XML and update the module — no Go changes in the addon.

Optional cell formatting for exports:

import "sumeru/core/sdk"

func init() {
    sdk.RegisterReportCellFormatter("crm.lead", func(model, field string, raw interface{}) string {
        // return display text for export cells
        return sdk.AsString(raw)
    })
}

Bulk import wizard (sys.bulk.import)

Registered in the base addon:

  • Model: sumeru/addons/base/models/sys_bulk_import.go (thin registration only)
  • Views: sumeru/addons/base/views/sys_bulk_import_views.xml
  • Logic: core/report/ (preview, execute, object actions action_confirm_import, action_cancel_import)

v1 limitations

  • Pivot / graph export not supported
  • No XLSX, scheduled reports, or email delivery
  • No direct import without the mapping view
  • Invoice HTML print routes remain separate from this engine

See also