Skip to main content

Configuration and data models

VeloxFactory is built around a small set of interconnected models. Understanding them is the key to understanding everything else, from how reports are set up, to how renderings are stored, to how print jobs and mails are dispatched.


Field Naming Conventions

VeloxFactory uses two naming styles consistently throughout the system. Database columns and Laravel model attributes are always snake_case, for example broadcast_id, report_config_id, created_by_token_id. The API and frontend use camelCase for all request and response fields, the same fields become broadcastId, reportConfigId, createdByTokenId.

This split is consistent without exception: whenever you are working with the API or the frontend, use camelCase. Whenever you are looking at raw database records, migration files, or server-side model attributes, expect snake_case. Throughout this documentation, all field names and JSON examples follow the API convention: camelCase.


The Model Hierarchy

Every piece of data in VeloxFactory fits into a clear hierarchy. At the top sits the ReportConfig, the central entity. Everything else either belongs to it, describes it, or records what happened when it was used.

ReportContext                             ← Organisational label for grouping reports
ReportConnectionConfig                    ← Optional live database connection
ReportConfig                              ← The report template + all its metadata
  ├── ReportParameter                     ← Input values passed at render time
  ├── ReportField                         ← Output columns from the SQL query or data payload
  └── ReportResource                      ← Graphic file asset (image, logo)
        └── (links to) CommonReportResource   ← Shared asset, used by reports and mails
ReportHistoryRecord                       ← Record of a past rendering (optional)
  ├── ReportPrintTask                     ← A print job dispatched from a history record
  │     └── (uses) Printer                ← Master data of the target printer
  └── ReportMailTask                      ← A mail dispatched from a history record
        ├── (uses) Mailer                 ← SMTP account the mail is sent through
        ├── (uses) MailTemplate           ← Subject and body of the mail
        └── (embeds) CommonReportResource ← Graphics placed in the mail body

Three of these are master data: Printer, Mailer and MailTemplate are maintained once under Configuration and then picked by name whenever a rendering is printed or mailed. They exist independently of any report.


ReportContext

A context is a visual label you assign to report configurations to group and identify them at a glance. It carries no functional logic, it is purely organisational.

Field Description
context_name Display name of the context
context_description Short description
context_text_color Hex color for the label text
context_badge_color Hex color for the badge background
context_border_color Hex color for the badge border

Every ReportConfig requires a context. A single context can be shared across any number of report configurations.


ReportConnectionConfig

A connection config represents a live database connection that VeloxFactory can use as a data source when rendering a report. When assigned to a ReportConfig, VeloxFactory executes the report's SQL query against this connection at render time and feeds the result rows into the report as field data.

Field Description
connection_name Friendly name for this connection
connection_driver Database driver (see table below)
connection_host IP address of the database server
connection_port Port (required)
connection_database Database / schema name
connection_username Username (stored encrypted)
connection_password Password (stored encrypted)
connection_test_query SQL query used to verify the connection
connection_tested Whether the connection has been successfully tested

Supported drivers:

Driver Database
mysql MySQL
mariadb MariaDB
pgsql PostgreSQL
sqlsrv Microsoft SQL Server

Connection status is derived from connection_tested:

Status Meaning
approved Connection has been tested successfully
unapproved Never tested or last test failed
⚠️ A report can only be rendered with a live connection if its status is approved. VeloxFactory will reject render requests for reports whose connection has not been successfully tested.

Network Requirements

VeloxFactory establishes the database connection directly from the server it runs on. The target database must therefore be reachable from that host, ideally within the same network or at minimum via a secured private channel.

⚠️ Do not expose your database to the public internet. Configuring a publicly accessible database (or opening firewall ports to make one reachable) is a significant security risk and is strongly discouraged. If VeloxFactory and your database run in separate networks, use an encrypted VPN tunnel instead: WireGuard or OpenVPN are both well-suited for this purpose.

When is a ReportConnectionConfig needed?

A ReportConnectionConfig is optional per ReportConfig. Whether you need one depends on how your report gets its data:

Scenario Connection needed?
Report has no detail band (purely static layout) No
Report has a detail band, data delivered via API at render time No
Report has a detail band and fetches data via SQL Yes

ReportConfig

The ReportConfig is the core entity of VeloxFactory. It represents a single JasperReports template (the .jrxml file) together with all the metadata VeloxFactory maintains about it.

Field Description
report_name Display name of the report
report_description Optional description
report_file_name Internal filename of the stored .jrxml
report_width Page width in mm (extracted from the .jrxml on upload)
report_height Page height in mm (extracted from the .jrxml on upload)
report_query SQL query, defined in VeloxFactory and stored in the database
report_has_detail_band Whether the template contains a detail band (extracted on upload)
report_context_id FK → ReportContext
report_connection_config_id FK → ReportConnectionConfig (nullable)
report_preview_base64 Base64-encoded preview image
report_thumbnail_base64 Base64-encoded thumbnail image
ℹ️ The SQL query is not defined in the .jrxml file. It is written and managed directly in VeloxFactory and stored in the database as part of the ReportConfig. The .jrxml only defines which fields the query result maps to.

When a .jrxml file is uploaded, VeloxFactory automatically analyses it and creates the associated ReportParameter, ReportField, and ReportResource records. You then review and complete the auto-generated data, for example setting example values or uploading resource files.

ReportParameter

Parameters are the inputs passed into a report at render time: dates, IDs, filter values, flags, and so on.

Field Description
parameter_name Parameter name as defined in the .jrxml
parameter_data_type Java class name (e.g. java.lang.String, java.lang.Integer)
parameter_required Read from the required custom property in the .jrxml
parameter_evaluation Evaluation time, extracted from the .jrxml
parameter_example_value Read from the exampleValue custom property in the .jrxml

Both parameter_required and parameter_example_value are sourced from custom properties embedded in the .jrxml parameter definition. They can also be set manually in VeloxFactory after upload.

Three parameter name prefixes carry meaning beyond the render itself:

Prefix Meaning
P_RESOURCE_ The parameter holds a graphic file asset, VeloxFactory creates a ReportResource for it
P_SCAN_ The parameter is filled by a barcode scan in Scan2Print
P_STATIC_ The parameter is preset once per Scan2Print session and stays untouched between scans

P_SCAN_ and P_STATIC_ are what makes a report usable in Scan2Print. Everything else about the report stays the same, the prefixes are a convention, not a separate model.

ReportField

Fields represent the data columns that populate the report's detail band, either from an SQL query result or from a data array delivered at render time.

Field Description
field_name Field name as defined in the .jrxml
field_data_type Java class name (e.g. java.lang.String, java.math.BigDecimal)
field_example_value Read from the exampleValue custom property in the .jrxml

field_example_value is used when rendering a preview without a live database connection.

ReportResource

Resources are graphic file assets (images and logos) embedded in the report template. They are referenced in the .jrxml via parameters following the P_RESOURCE_ naming convention.

Field Description
parameter_name The P_RESOURCE_ parameter name as referenced in the .jrxml
resource_file_name Filename of the directly uploaded file (nullable)
common_report_resource_id FK → CommonReportResource (nullable)

A ReportResource either holds its own uploaded file or it is linked to a CommonReportResource, never both at the same time. When linking to a common resource, the resource's own file is deleted and the common file is used in its place.


CommonReportResource

A CommonReportResource is a shared graphic asset (a company logo, a standard header image) that multiple report configurations can reference. Instead of uploading the same file to each report individually, you upload it once and link individual ReportResource records to it.

Field Description
resource_name Display name, unique, and at the same time the placeholder token used in a mail body
resource_description Optional description
resource_file_name Internal filename of the stored file
resource_mime_type Detected mime type, filled on upload
resource_width / resource_height Pixel dimensions, read from the file
resource_display_width Optional width the graphic is rendered with in a mail
resource_alt_text Alternative text for the mail graphic

A common resource serves two purposes. In a report it is the file behind a P_RESOURCE_ parameter. In a mail template it is an inline graphic: the body references it by [image.<resource_name>], and at send time the file is embedded into the mail itself, not linked from a server. A resource is mail capable when it is a real PNG or JPEG with readable dimensions, which is why the name has to be unique.

ℹ️ Linking is a one-way action. When a ReportResource is linked to a CommonReportResource, its own file is permanently deleted. Unlinking removes the reference but does not restore the file, you will need to re-upload it.

ReportHistoryRecord

A ReportHistoryRecord captures the full context of a rendering: what was requested, what was returned, and whether it succeeded. Creating a history record is optional and controlled by the createHistoryRecord flag in the render request.

Field Description
report_config_id FK → ReportConfig
trace_id Unique identifier for this rendering run
output_type How the PDF was returned (see below)
report_api_payload The exact request payload sent to the render call
report_api_response The full API response, stored for traceability
report_pdf_base64 Base64-encoded PDF content
report_pdf_file_name Filename of the PDF on disk
report_excel_file_name Filename of the xlsx export on disk, written when a mailing asked for one (nullable)
report_thumbnail_base64 Base64-encoded thumbnail of the first page (generated asynchronously)
status Outcome of the rendering (see below)

Output types (output_type):

Value Description
base64 PDF returned inline as a Base64 string
url PDF stored as a file, a URL is returned
preview Rendered for preview; file is not persisted
none No PDF output (used for print-only flows)

Status values (status):

Value Description
ok Rendering succeeded, PDF received
render_fail No errors reported, but no PDF received
error JasperReports returned one or more errors
unknown Status cannot be determined

History records are retained for a configurable number of days, see Environment Configuration below. Thumbnails are generated asynchronously after rendering completes. Deleting a history record removes its PDF and its xlsx from disk together with the record.


ReportPrintTask

A ReportPrintTask represents a print job dispatched to a physical printer. It is always linked to a ReportHistoryRecord, you always print a specific past rendering, not a report config directly.

Field Description
report_config_id FK → ReportConfig
report_history_record_id FK → ReportHistoryRecord
printer_id FK → Printer (nullable, set when the printer was picked from the master data)
trace_id Unique identifier for this print run
broadcast_id WebSocket channel ID for real-time status updates (nullable)
printer_name Target printer name
copies Number of copies to print
output_file_name Filename of the PDF sent to the printer
output_base64_string Base64-encoded PDF (consumed by the print service)
error_message Error detail if printing failed
status Current print status (see below)

Status values (status):

Value Description
pending Created, waiting for the print service
printed Successfully printed and confirmed
error Printing failed
unknown Status cannot be determined
ℹ️ Real-time updates via WebSocket only apply when broadcastId is provided in the render request. The C# print service subscribes to that channel, picks up the task, executes the print job, and reports status back. Without a broadcastId, the task is created silently, the print service must poll for new tasks.

Printer

A Printer is master data for a physical printer. Without it, every print request had to carry the exact queue name of the print server, and everyone had to know it by heart. With it, a printer is configured once and then picked from a list.

Field Description
printer_display_name The name people see, for example Warehouse Label 01. Unique, 3 to 50 characters
printer_name The queue name on the print server, for example WH-LABEL-01. This is what the print service receives. Unique
printer_type label-printer, a4-printer, mfc-printer or digital-printer. Descriptive, it drives icon and filter
printer_location Where the machine stands, for example Hall 2, Shipping (nullable)
printer_broadcast_id WebSocket channel of the print service instance that serves this printer (nullable)
printer_description Free note, for example the loaded media (nullable)
printer_is_active Inactive printers keep working in existing configurations but are no longer offered in pickers

A render request may name either the display name or the queue name, VeloxFactory resolves both. A name that matches no master data record is still accepted and passed through unchanged, so integrations written before the master data existed keep working.


Mailer

A Mailer is master data for one SMTP account. It is to mailing what a ReportConnectionConfig is to data: the credentials live in one place, are tested from the UI, and are then referenced by name.

Field Description
mailer_name Unique name used to reference the mailer in a request
mailer_transport Transport, smtp by default
mailer_host / mailer_port SMTP server and port
mailer_scheme smtp, smtps or empty for the transport default
mailer_username / mailer_password Credentials, stored encrypted
mailer_from_address / mailer_from_name Sender of every mail sent through this mailer
mailer_reply_to Optional reply-to address
mailer_timeout / mailer_local_domain Optional transport details
mailer_rate_limit_per_minute Max mails per minute, empty means the window is not enforced
mailer_rate_limit_per_hour Max mails per hour, 500 by default
mailer_rate_limit_per_day Max mails per day, empty means the window is not enforced
mailer_is_active Inactive mailers are not offered and are refused by the API
mailer_tested Whether a test mail has been sent successfully
mailer_description Free note
ℹ️ The three rate limit windows are independent and all have to allow a send. Providers cap differently: Office 365 counts per minute, most hosters per hour, Gmail per day. A blocked send is not lost, it is queued and goes out when the window opens.

The global MAIL_* variables of Laravel are not used by the mailing pipeline. Every mail goes through a Mailer record, registered as a runtime mail connection for the duration of the send and removed again afterwards, exactly the way a ReportConnectionConfig handles its database connection.


MailTemplate

A MailTemplate holds the subject and the body of a mail, both written once and filled with placeholders at send time.

Field Description
mail_template_name Unique name used to reference the template in a request
mail_template_subject Subject line, placeholders allowed
mail_template_body_html HTML body, written in a rich text editor, placeholders allowed
mail_template_header_color Optional override of the header bar colour
mail_template_body_color Optional override of the body background
mail_template_hide_logo Hides the logo in the header
mail_template_logo_resource_id FK → CommonReportResource, an own logo for this template (nullable)
mail_template_footer_text Optional override of the global footer text, placeholders allowed
mail_template_is_active Inactive templates are not offered and are refused by the API
mail_template_description Free note

Placeholders use the [token] syntax and cover the render ([traceId], [reportFileName]), the report, the history record, the user, the API token, the printer, every parameter ([parameters.<NAME>]), the data rows ([data.first.<FIELD>]), the current time ([now.date]), the recipients and the graphics ([image.<RESOURCE_NAME>]). The full catalog is available in the editor. An unknown token resolves to an empty string and is reported, it never fails a mail.

The four whitelabel fields are each a nullable override of a global default. Left empty, the mail uses the theme colours read from the application's own stylesheet, so a mail looks like the application without anything being configured twice.


ReportMailTask

A ReportMailTask represents one mail. Like a ReportPrintTask it belongs to a ReportHistoryRecord, you always mail a specific past rendering.

Field Description
report_history_record_id FK → ReportHistoryRecord (nullable if no history record was created)
mailer_id FK → Mailer
mail_template_id FK → MailTemplate
trace_id Unique identifier for this mail run
recipients_to / recipients_cc / recipients_bcc Resolved address lists
mail_subject The rendered subject, placeholders already resolved
mail_body_html The rendered body, stored so the UI can show what was actually sent
attachment_pdf_file_name The PDF on the history disk, always <trace id>.pdf
attachment_excel_file_name The xlsx on the history disk, always <trace id>.xlsx
attachment_pdf_name The name the PDF carries as an attachment of the mail
attachment_excel_name The name the xlsx carries as an attachment of the mail
send_async Whether the mail was queued instead of sent synchronously
dispatch_after Set when the rate limit pushed the send into the future
sent_at Timestamp of the successful send
error_message Error detail if sending failed
status Current mail status (see below)

Status values (status):

Value Description
pending Created, not sent yet, or waiting for a rate limit window
sent Handed over to the SMTP server successfully
error Sending failed
unknown Status cannot be determined
ℹ️ A mail task never owns a file. The PDF and the xlsx belong to the history record, stay downloadable from it and are deleted with it. The two attachment name columns only say what the files are called inside the mail. Mail tasks are retained for a configurable number of days, independently of the history records.

Audit Trail

Every model in VeloxFactory tracks who created and last updated a record, and which API token was used. This information is available on all records via the withAudit=true query parameter in the API.

Field Description
created_at Timestamp of creation
created_by User ID of the creator
created_by_token_id API token ID used (if created via API)
updated_at Timestamp of last update
updated_by User ID of the last updater
updated_by_token_id API token ID used (if updated via API)

The creationMethod and updateMethod fields in the API response ("Frontend" vs. "API") are derived automatically, based on whether a token was present on the request.


Environment Configuration

VeloxFactory's runtime behaviour is controlled via environment variables in .env or as container environment variables.

Application

Variable Default Description
APP_SCHEME http URL scheme for generated links (http or https)
API_RATE_LIMIT_PER_MINUTE 10 Max API requests per minute per token
PAGINATION_DEFAULT_COUNT 25 Default number of results per API response

Queue & Redis

Variable Default Description
QUEUE_CONNECTION database Queue driver (must be set to redis for Horizon)
REDIS_CLIENT phpredis Redis client library (phpredis required)
REDIS_HOST 127.0.0.1 Redis server hostname or IP
REDIS_PORT 6379 Redis server port
REDIS_PASSWORD null Redis password (leave null if not set)

Horizon

Variable Default Description
HORIZON_PATH horizon URL path for the Horizon dashboard
HORIZON_PREFIX derived from APP_NAME Redis key prefix for all Horizon data
HORIZON_DOMAIN - Optional custom domain for the Horizon dashboard

Mailing

Variable Default Description
MAIL_LOGO_URL - Logo shown in the mail header. Empty falls back to the application name as text.
MAIL_FOOTER_TEXT Sent automatically by VeloxFactory. Footer of every mail, overridable per template
MAIL_RATE_LIMIT_PER_MINUTE 0 Default minute limit for a newly created mailer. 0 means not enforced.
MAIL_RATE_LIMIT_PER_HOUR 500 Default hour limit for a newly created mailer
MAIL_RATE_LIMIT_PER_DAY 0 Default day limit for a newly created mailer
MAIL_THROTTLE_FALLBACK_TO_QUEUE true A throttled synchronous send is queued instead of answered with an error
MAIL_MAX_ASSET_SIZE_KB 2048 Maximum size of a graphic that can be embedded into a mail

The standard Laravel MAIL_* keys stay untouched. They are the framework fallback and are not used for report mails.

Retention & Purge

Variable Default Description
PURGE_HISTORY_DAYS 30 Age in days after which history records are purged. Set to -1 to disable.
PURGE_PRINTTASKS_DAYS 30 Age in days after which print tasks are purged. Set to -1 to disable.
PURGE_MAILTASKS_DAYS 30 Age in days after which mail tasks are purged. Set to -1 to disable.
PURGE_ORPHANED_FILES_DAYS 30 Age in days after which orphaned files on disk are purged. Set to -1 to disable.