feat: create validated ZUGFeRD invoices in one console command

This commit is contained in:
admin committed 2026-10-16 09:29:08 +02:00
1 parent e0c15fc7f2
commit a643cf5227
30 files changed
+1509 -207

No files matched your search

+13 -3
View File
@@ -1,10 +1,11 @@
from __future__ import annotations
from pathlib import Path
import shutil
from .paths import presets_root
from datetime import date, timedelta
from .presets import load_yaml, deep_merge, load_customer_preset
from .invoice_number import suggest_next_invoice_number
from .invoice_number import suggest_next_invoice_number, invoice_root_lock
from .folder_naming import default_invoice_folder_name
import yaml
@@ -24,6 +25,8 @@ def init_invoice_folder(
project: str | None = None,
) -> Path:
target_dir = target_dir.resolve()
if (target_dir / "invoice.yaml").exists() and not force:
raise FileExistsError(f"{target_dir / 'invoice.yaml'} already exists")
target_dir.mkdir(parents=True, exist_ok=True)
# Create standard subfolders
@@ -44,6 +47,8 @@ def init_invoice_folder(
# Apply seller defaults
seller_defaults = load_yaml(repo_root / "presets" / "seller.default.yaml")
local = presets_root(repo_root)
seller_defaults = deep_merge(seller_defaults, load_yaml(local / "seller.default.yaml"))
merged = deep_merge(base_tpl, seller_defaults)
# Apply customer preset
@@ -53,7 +58,7 @@ def init_invoice_folder(
merged = deep_merge(merged, preset)
logger.info("Applied customer preset: %s", customer)
else:
logger.warning("Customer preset not found for: %s (continuing with generic buyer)", customer)
raise ValueError(f"Unknown customer preset: {customer}")
# Smart defaults for meta/payment
today = date.today()
@@ -102,7 +107,7 @@ def init_invoice_folder(
logger.info("Initialized invoice folder: %s", target_dir)
return target_dir
def init_invoice_under_root(
def _init_invoice_under_root(
invoices_root: Path,
repo_root: Path,
logger,
@@ -135,3 +140,8 @@ def init_invoice_under_root(
invoices_root=invoices_root,
project=project,
)
def init_invoice_under_root(invoices_root: Path, **kwargs) -> Path:
with invoice_root_lock(invoices_root):
return _init_invoice_under_root(invoices_root, **kwargs)