Documents
Beyond payslips and annual statements, HRMQ generates the standard Dutch HR letters from templates hosted in docudesk:
arbeidsovereenkomst— employment contractaanbiedingsbrief— offer letterwerkgeversverklaring— employer's statement (e.g. for a mortgage application)getuigschrift— reference/testimonial letter
HRMQ ships no template engine of its own — HrDocumentService
assembles the object references and calls docudesk's
DocumentService::generateDocument() same-instance, duck-typed via the
DI container, never over HTTP. Every generation attempt is recorded as a
GeneratedDocument — pending, generated, failed, or
skipped-no-docudesk.
Template selection: config first, discovery second, fail closed
For each document type, HRMQ first checks a configured template UUID
(SettingsService getter documents_template_{documentType}); if unset,
it falls back to discovering exactly one docudesk template tagged
namespace: hrmq with a matching category. Zero or multiple matches
fail the attempt closed with a diagnostic naming the ambiguity — nothing
is ever rendered against a guess.
Idempotency
At most one GeneratedDocument in pending or generated status exists
per idempotency key. The four letter types key on (contractId, documentType) — or (employeeId, documentType) when there's no
contract. Re-running generation for an already-documented contract is a
no-op; a failed or skipped-no-docudesk record never blocks a retry.
Generating documents
occ hrmq:documents:generate
occ hrmq:documents:generate --type=werkgeversverklaring --employee=<employee-id>
With no options, the default backlog is every permanent
EmploymentContract with writtenContract: true that has no active
arbeidsovereenkomst document yet. The letter types other than
arbeidsovereenkomst have no backlog semantics of their own and require
--employee. See Payslips for the
--type loonstrook and --type jaaropgaaf backlog behaviour.
A single guarded endpoint (POST /api/documents/generate) backs the
"Genereer arbeidsovereenkomst" action on EmploymentContractDetail and
the "Genereer PDF" action on PayslipDetail — resolved under the
caller's RBAC before any docudesk call, so an unknown or unauthorized
contract/payslip id returns 404 with nothing rendered.
Graceful degradation
When docudesk isn't installed, every attempt records
skipped-no-docudesk — no exception, exit code 0. Once docudesk is
installed, the next run supersedes the skip and renders normally. HRMQ
carries no info.xml or composer dependency on docudesk.