At a Glance
Owner: Sysadmin (schedules) + Platform Admin (templates, mappings) · Table:tb_report_job+tb_report_schedule(tenant),tb_report_template+tb_print_template_mapping(platform) · Used by: every "Print" button + dashboard / scheduled exports · Full report and print-layout pipeline.
The report entity is the full report generation pipeline — ad-hoc on-demand exports + scheduled recurring exports + the print layout behind every "Print" button. Four tables across two schemas:
tb_report_template (platform) — template catalogue (analytical report or print layout); holds layout (dialog, content), data binding (source_type + source_name + source_params), orientation, signatures.tb_print_template_mapping (platform) — maps document_type (PO, PR, SR, GRN, CN, IA, …) to one or more templates; exactly one is_default = true per type.tb_report_job (tenant) — execution history (queued / processing / completed / failed / cancelled); filters, format, output metadata.tb_report_schedule (tenant) — cron-driven recurring runs; enqueues jobs.Mixed schemas reflect deployment: templates + mappings are curated centrally; jobs + schedules are tenant data.
Maintained by Platform Admin (templates, mappings), Sysadmin (schedules). Read by the report list, "Print as…" menu, dashboard widgets.
Report generation is split across two Go services, with the Dataset object (columns + rows + totals + summary) as the boundary contract:
| Concern | Columns on tb_report_template |
Owner | Does |
|---|---|---|---|
| Dataset | source_type, source_name, source_params, dialog, view_name, builder_key |
micro-data | Resolves the view / function / procedure, composes the WHERE clause from filters, fans out across tenant BUs, returns Dataset. Renders nothing. |
| Report | content, kind, report_group, format / orientation / signatures |
micro-report | Owns output format (PDF / Excel / CSV / JSON), template layout, kind, print mappings, and job tracking. |
micro-report no longer runs the query in-process — it calls micro-data's POST /api/datasets/execute (passing the source's builder_key or name, bu_codes, and filters) and renders the returned Dataset. The tb_report_template row still physically holds both column sets; micro-data reads only the dataset columns (mapped onto model.DatasetSource). Extracting them into a tb_dataset_source table is a noted future migration, not yet in effect.
| Task | Where | Notes |
|---|---|---|
| Run a report on demand | Reports menu → pick report → Run | Inserts a tb_report_job row |
| Download a finished job | Reports → Jobs → click filename | Resolves file_url; respects expires_at |
| Schedule a recurring export | Reports → Schedules → New | Cron expression + filters + recipients |
| Add a print layout for a document type | Platform Admin → Print Templates | Toggle is_default to switch default |
| BU-scope a template | Edit template allow_business_unit / deny_business_unit |
Null allow-list = all BUs |
| Re-run a failed job | Reports → Jobs → Re-run | Creates new tb_report_job |
| Symptom | Cause | Action |
|---|---|---|
Job stuck queued |
Executor not picking up | Check executor health and idx_report_job_status |
| Job fails with "view not found" | source_type / source_name drift |
Realign template binding with DB object |
| Multiple defaults per document type | App invariant violated | Repair: keep one is_default = true; others false |
| Download 404 | Output reaped per expires_at |
Re-run the job |
| Template not visible in BU | allow_business_unit excludes; or deny_business_unit includes |
Edit BU scoping |
source_type / source_name aligned with the actual DB object.is_standard = true UIs typically prevent deletion and warn on edit.queued → processing → (completed | failed | cancelled). Executor sets started_at / completed_at / duration_ms.expires_at is the storage reaper contract.Source: mixed — tenant for jobs/schedules, platform for templates/mappings.
tb_report_job (tenant)| Field | Prisma Type | Nullable | Description |
|---|---|---|---|
id |
String @db.Uuid |
No | Primary key. |
report_type |
String @db.VarChar(100) |
No | Logical report identifier. |
report_category |
enum_report_category |
No | inventory, procurement, recipe, vendor, financial, operational. |
format |
enum_report_format |
No | pdf, excel, csv, json. |
status |
enum_report_job_status |
No | Default queued. |
filters / options |
Json? @db.JsonB |
Yes | Defaults {}. |
file_url / file_name / file_size / row_count |
— | Yes | Output metadata. |
error_message |
String? |
Yes | Populated on failed. |
started_at / completed_at / expires_at |
DateTime? |
Yes | Timing. |
duration_ms |
Int? |
Yes | Cached duration. |
requested_by_id |
String @db.Uuid |
No | Requesting user. |
| Audit columns | — | Yes | created_*, updated_*, deleted_*. |
Indexes: status, report_type, requested_by_id, created_at DESC.
tb_report_schedule (tenant)| Field | Prisma Type | Nullable | Description |
|---|---|---|---|
id / name |
String |
No | Keys. |
report_type / report_template_id |
String |
Mixed | Logical id + optional template binding. |
format |
enum_report_format |
No | Output format. |
cron_expression |
String @db.VarChar(100) |
No | Standard cron. |
schedule_config / filters / options / recipients |
Json? |
Yes | Scheduler + run options + email/user IDs. |
is_active |
Boolean |
No | Default true. |
last_run_at / next_run_at |
DateTime? |
Yes | Scheduler bookkeeping. |
| Audit columns | — | Yes | created_*, updated_*, deleted_*. |
tb_report_template (platform)Carries name, description, report_group, kind (report / print), dialog, content, optional builder_key, source_type (view / function / procedure), source_name, source_params, orientation, signature_config, is_standard, allow_business_unit / deny_business_unit, is_active. @@unique([name, deleted_at]).
Service ownership note: the dataset columns (
source_type,source_name,source_params,dialog,view_name,builder_key) are read by micro-data (mapped ontomodel.DatasetSource); the remaining columns are read by micro-report. See §1.1 for the split rationale.
tb_print_template_mapping (platform)document_type → report_template_id; is_default, display_label, display_order, BU allow/deny lists, is_active. No DB uniqueness on (document_type, is_default) — app enforces single default.
report for analytical menu; print for the print pipeline (hidden from reports menu).source_type must match the DB object's nature; positional args declared in source_params.queued → processing → (completed | failed | cancelled).expires_at governs reaper.tb_print_template_mapping.export / print actions logged.requested_by_id + recipients.../carmen-turborepo-backend-v2/packages/prisma-shared-schema-tenant/prisma/schema.prisma — tb_report_job (lines ~5652-5683), tb_report_schedule (lines ~5685-5709).../carmen-turborepo-backend-v2/packages/prisma-shared-schema-platform/prisma/schema.prisma — tb_report_template (lines ~589-656), tb_print_template_mapping (lines ~663-688).../carmen-turborepo-frontend/apps/web/app/(app)/reporting/ (tenant reports/jobs/schedules); template admin in platform app.../micro-report/ — report execution worker.