Initial version of the E-Invoice solution of JR IT Services

This commit is contained in:
2026-02-16 17:02:03 +01:00
commit e0c15fc7f2
36 changed files with 1407 additions and 0 deletions

67
jr_einvoice/pipeline.py Normal file
View File

@@ -0,0 +1,67 @@
from __future__ import annotations
from pathlib import Path
from dataclasses import dataclass
from typing import Optional
from .io import load_invoice_yaml
from .render import render_html, render_pdf
from .facturx import generate_facturx_xml
from .mustang import combine_facturx, validate
@dataclass
class BuildResult:
invoice_dir: Path
out_dir: Path
invoice_pdf: Path
facturx_xml: Path
facturx_pdf: Optional[Path] = None
validate_report: Optional[Path] = None
def build_in_folder(
invoice_dir: Path,
out_subdir: str,
template_path: Path,
logger,
mustang_jar: Optional[Path] = None,
combine: bool = False,
do_validate: bool = False,
prefer_weasyprint: bool = True,
invoice_filename: str = "invoice.yaml",
) -> BuildResult:
invoice_dir = invoice_dir.resolve()
invoice_yaml = invoice_dir / invoice_filename
if not invoice_yaml.exists():
raise FileNotFoundError(f"Missing {invoice_filename} in invoice folder: {invoice_dir}")
inv = load_invoice_yaml(invoice_yaml)
out_dir = invoice_dir / out_subdir
(out_dir / "logs").mkdir(parents=True, exist_ok=True)
logger.info("Loaded invoice: %s (folder=%s)", inv.meta.invoice_number, invoice_dir)
logger.info("Artifacts directory: %s", out_dir)
html = render_html(inv, template_path)
pdf_path = out_dir / "invoice.pdf"
pdf_res = render_pdf(html, pdf_path, logger, prefer_weasyprint=prefer_weasyprint, base_url=str(invoice_dir))
if not pdf_res.ok or not pdf_res.path:
raise RuntimeError(f"PDF rendering failed: {pdf_res.error}")
xml_path = out_dir / "factur-x.xml"
generate_facturx_xml(inv, xml_path, logger)
result = BuildResult(invoice_dir=invoice_dir, out_dir=out_dir, invoice_pdf=pdf_path, facturx_xml=xml_path)
if combine or do_validate:
if not mustang_jar:
raise RuntimeError("Mustang jar required for --combine/--validate. Provide --mustang-jar path.")
facturx_pdf = out_dir / "invoice.facturx.pdf"
logger.info("Combining PDF + XML -> Factur-X PDF via Mustang")
result.facturx_pdf = combine_facturx(mustang_jar, pdf_path, xml_path, facturx_pdf, logger, profile="E")
if do_validate:
logger.info("Validating Factur-X PDF via Mustang")
report = out_dir / "validation" / "validate_report.xml"
result.validate_report = validate(mustang_jar, result.facturx_pdf or (out_dir / "invoice.facturx.pdf"), report, logger)
return result