Inside Our Build: Locking Down a TCPDF Reporting Standard
If you've looked through the DOS ERP screenshots on our site, you've probably noticed something: every printed document looks like it belongs to the same system. The General Ledger report, a Journal Voucher, an Invoice, a Batch Card Recipe report — different content, same bones. That consistency didn't happen by accident. It's the result of a decision we made early and enforced strictly: one TCPDF standard, used by every report and every voucher, with no exceptions.
Here's how we got there, and why it mattered enough to lock down.
The Problem With "Just Generate a PDF"
TCPDF is a solid, mature PHP library for generating PDFs, and it's what DOS ERP uses under the hood for every printed document. But TCPDF on its own is just a toolkit — it doesn't enforce any layout conventions. Left unchecked, that's exactly how reporting systems rot: one developer builds the General Ledger report with a logo in the top-left and a footer page number. Another builds the Bank Reconciliation report with the logo centered and no footer at all. A third builds a voucher print with signature blocks in a different order than everyone else.
None of that is wrong, exactly. Each report works fine in isolation. But put ten of them side by side — which is exactly what happens when a client prints a batch of documents for an audit — and the inconsistency becomes obvious immediately. It looks like ten different systems, not one ERP.
What We Standardized
Before writing a single report-specific line, we defined a shared TCPDF base that every report and voucher extends. It locks down:
- The header — company logo, document title, and generation timestamp, positioned identically on every page of every document.
- The criteria line — a single line summarizing exactly what filters or parameters produced this report (date range, account, department, whatever's relevant). If you're looking at a printed General Ledger, you know exactly what date range and account you're looking at without hunting for it.
- Page numbering — every multi-page report gets the same "Page X of Y" footer, generated consistently rather than hand-rolled per report.
- Signature blocks — where a document needs sign-off (invoices, vouchers, batch card reports), the blocks are always in the same order: Prepared By, Checked By, Approved By, Received By — with the same spacing and line style every time.
Individual reports only ever define their own content — the table columns, the data, the specific layout of the report body. Everything around that content — header, footer, criteria line, signatures — comes from the shared base and is never reimplemented from scratch.
Why This Was Worth Enforcing
A few reasons this discipline paid off beyond just "it looks nicer":
It matches how DOS ERP already thinks about consistency elsewhere. The same platform enforces one voucher numbering format across all eleven voucher types and one maker-checker-approver workflow across every transaction. A locked report standard is the same philosophy applied to what comes out of the system, not just what goes in.
It made every new report faster to build, not slower. Once the base class existed, adding a new report type meant writing the query and the table layout — not re-solving "how do I put a logo and page number on a PDF" for the twelfth time. Engineering time spent on new modules like Batch Card Recipe or Bank Reconciliation went almost entirely into the actual reporting logic.
It made audit trails feel trustworthy. DOS ERP already logs every database change at the column level through DB Audit Trail Management. But an audit trail is only as useful as the documents it corroborates. When every printed voucher and report follows the exact same, predictable format, cross-referencing a change in the audit log against the printed paperwork is straightforward — there's no "wait, which version of the layout is this from" ambiguity.
The Result
Today, whether you're printing a Chart of Accounts setup, a General Ledger report, a Bank Reconciliation, a Batch Card Recipe, or a Sales Invoice, you're looking at output from the exact same underlying TCPDF standard. Same logo placement. Same criteria line. Same page numbering. Same signature block order. It's a small thing to notice and an easy thing to take for granted — which is exactly the point. Reporting infrastructure should be invisible when it's working right.
This is the same standard we bring into every custom ERP project we build for clients — not because printed PDFs are glamorous engineering, but because getting the boring parts locked down consistently is what makes everything built on top of them feel solid.