How Reports Are Composed in Baruch
Baruch uses a clean, layered reporting architecture designed for clarity, maintainability, and flexibility. Reports are built using a projection-driven approach, where data retrieval, transformation, and document rendering are clearly separated.
The result is always a PDF file generated from a Word template, allowing congregation administrators to maintain and adjust layout without changing code.
High-Level Flow
When a user generates a report, the following steps occur:
UI → Report Descriptor → Reporting Engine
↓
Projection Query (via MediatR)
↓
Projection (data model)
↓
Word Renderer
↓
PDF (via Syncfusion)
Each layer has a single responsibility.
1. Report Descriptor
A report in Baruch is defined by a descriptor.
The descriptor contains:
Report name
Report category
Required arguments (e.g., Month, Year)
Attribute linking to:
The projection query
Default Word template
Default paper format
The descriptor does not contain business logic or rendering logic. It only describes what the report is. This keeps reports lightweight and easy to maintain.
2. Reporting Engine
The Reporting Engine orchestrates the process.
Its responsibilities:
Read the descriptor metadata
Create the projection query dynamically
Execute the query through MediatR
Retrieve the projection (data model)
Locate the correct renderer
Generate the Word document
Convert the document to PDF
The engine does not know about specific reports.
It works generically using reflection and dependency injection.
3. Projection Queries
Each report has a dedicated projection query.
The query:
Gathers domain data
Performs aggregation and calculations
Shapes the data into a projection model
The projection is a pure data object (DTO) that contains exactly what the report needs — no formatting logic.
Because projections are separate from rendering, they can also be reused in:
Dashboards
Analytics views
Future APIs
4. Projections
A projection is a structured data model that represents the report’s final data state.
Example:
Active publishers
Meeting attendance averages
Congregation statistics
Upcoming events
Projections implement a marker interface (IReportProjection) so the Reporting Engine can enforce type safety. They contain no UI or document logic.
5. Word Renderers
Each projection has a corresponding Word renderer.
The renderer:
Receives the projection
Maps projection values to Word template tags
Assigns values to placeholders in the document
All tag assignments happen in the renderer — not in the report descriptor.
Example:
report.Assign("ACTIVE_PUBLISHERS_TEXT", projection.ActivePublishers.ToString());
This separation ensures:
Business logic stays in queries
Document mapping stays in renderers
Metadata stays in descriptors
6. Word Templates
Templates are standard Word (.docx) files.
They contain placeholder tags such as:
<CONGREGATION_NAME>
<ACTIVE_PUBLISHERS_THIS_MONTH>
<PRINTED_DATE>
Because templates are normal Word documents:
Layout can be edited without code changes
Formatting is fully customizable
Non-technical users can maintain them
7. PDF Generation
After the renderer maps all tags:
The Word document is processed using Syncfusion DocIO
It is converted to PDF
The PDF file is saved and returned to the UI
The final result is always a PDF, ensuring consistency and professional output.