When I started working on B2B e-invoicing, I thought the technical part would be straightforward. Generate a PDF, embed an XML, follow a standard. On paper, it seemed linear.
In practice, it's something else entirely.
Here's what actually took time — not the concepts, but the details that break everything in production.
The Comfort profile is not declared — it is earned
EN16931 defines several profiles. The Comfort profile, the one that guarantees real interoperability with accounting systems, requires strict identifier completeness.
SIREN alone is not enough. SIRET alone is not enough. The combination of SIREN + SIRET + VAT number determines the profile declared in the XML. If one identifier is missing, the profile changes. And an incorrect profile means a technically invalid invoice — even if it looks perfectly fine visually.
I implemented conditional validation logic before generation. No silent correction, no approximation. Either the data is complete, or the invoice does not go out.
Multi-period invoicing is a state problem, not a calculation problem
Invoicing across multiple months in a single document seems simple. It is not.
The real issue: a period included in an issued invoice is permanently closed. It cannot be re-invoiced, partially modified, or cancelled. This is not a software constraint — it is a legal and accounting one.
I had to model an explicit state system per period and per client, using immutable archiving flags. No database — only locked, deterministic and traceable files.
Deduplication without a database
The classic question: how do you prevent issuing the same invoice twice if the process is restarted?
My answer: file-based locks. Each execution cycle checks for the existence of a lock file before generating anything. No race condition, no distributed transaction, no external dependency. One execution = one deterministic cycle. If the file exists, skip. Otherwise, generate and lock.
Simple, traceable, reliable.
The pipeline runs on cron — no background process, no service to keep alive
No persistent process running in the background, no service to maintain active, no SaaS dependency. The engine triggers, processes, archives and stops. Each execution is independent and reproducible.
This architectural choice has a direct consequence: if something goes wrong, there is nothing to restart, nothing to debug live. Logs are exhaustive, states are explicit, generated files are evidence.
What I take from this
Factur-X is not a PDF generation problem. It is a structured pipeline problem — controlled states and normalized data before production.
Tools that "generate Factur-X" are plentiful. Systems that guarantee end-to-end compliance, full traceability and zero implicit correction are far less common.
https://palks-studio.com/en/batch-invoicing-facturx
If you're interested in how it works under the hood:
Here’s a technical breakdown of the system architecture.
Overview Project
This repository presents a financial automation system designed to handle:
- invoice generation (single & batch)
- revenue tracking
- payment reconciliation
- client balances
- accounting-ready exports
The system is deterministic, auditable, and explicit by design.
It operates:
- without a database
- without a CMS
- without a SaaS dependency
- without any exposed web interface
All executions run server-side, via CLI scripts and cron, with a strict separation of responsibilities.
This project is not a product, not a SaaS, and not a plug-and-play tool.
It documents a production-grade approach to financial automation.
Over time, the engine has been progressively extended
to cover real-world business cases,
without compromising its original design principles.
The billing system now supports:
- multi-line invoices
- multiple VAT rates per invoice
- complex or extended service periods
- multi-month billing scenarios
- complex combinations while remaining EN16931 Comfort compliant
This functional expansion did not alter
the deterministic, auditable, and traceable nature of the system.
Electronic invoicing (Factur-X)
The system natively integrates Factur-X electronic invoicing (hybrid PDF with embedded XML),
in compliance with the European EN 16931 standard (Comfort profile):
- generation of a semantically EN 16931-compliant Factur-X XML
- XML validation (XSD and Schematron)
- injection of the XML into the PDF
- production of a single final document: the Factur-X hybrid PDF
- direct integration into the
run.phpandrun_batch.phppipelines - no parallel formats
- no persistent XML storage
The system targets business compliance and e-invoicing interoperability (France / EU).
PDF/A compliance (document archiving) is not a functional objective of the project and is deliberately out of scope.
Factur-X is handled as a native component of the engine,
not as an external or optional module.
Project structure
automation_finance/
│
├── engine/ → Core automation engine (billing, generation, processing)
├── data/ → Internal data storage (clients, invoices, tracking)
├── tools/ → Internal utilities and maintenance scripts
├── exports/ → Data export and reporting
├── downloads/ → Generated document delivery
├── clients/ → Client configuration
├── contracts/ → Legal and contractual documents
│
├── LICENCE.md → Conditions d’utilisation et cadre légal (FR)
├── LICENSE.md → Terms of use and legal Framework
│
├── LICENCE.md → Conditions d’utilisation et cadre légal (FR)
├── LICENSE.md → Terms of use and legal Framework
│
└── docs/
├── README_FR.md → Documentation générale du système (FR)
├── README.md → General system documentation
│
├── SERVICE_MEMO_FR.md → Note interne de positionnement du service (FR)
├── SERVICE_MEMO.md → Internal Service Positioning Memo
│
├── README_DEPLOY_FR.md → Guide d’installation et d’exploitation (FR)
├── README_DEPLOY_EN.md → Installation and Production Guide
│
├── VUE_DENSEMBLE_AUTOMATION.md → Vue d’ensemble du système d’automatisation de facturation (FR)
└── SYSTEM_OVERVIEW_AUTOMATION.md → Billing Automation System Overview
If you want to explore the technical implementation, you can find it here:
https://github.com/Palks-Studio/automation-finance

Top comments (0)