Files
einvoice/jr_einvoice/invoice_number.py
T

45 lines
1.3 KiB
Python

from __future__ import annotations
from pathlib import Path
import re
from datetime import date
DEFAULT_PATTERN = r"(?P<year>\d{4})-(?P<seq>\d{4})"
def suggest_next_invoice_number(invoices_root: Path, year: int | None = None, pattern: str = DEFAULT_PATTERN) -> str:
invoices_root = invoices_root.expanduser().resolve()
y = year or date.today().year
rx = re.compile(pattern)
max_seq = 0
if invoices_root.exists():
for d in invoices_root.iterdir():
if not d.is_dir():
continue
m = rx.search(d.name)
if not m:
continue
try:
yr = int(m.group("year"))
seq = int(m.group("seq"))
except Exception:
continue
if yr == y and seq > max_seq:
max_seq = seq
return f"{y}-{max_seq+1:04d}"
from contextlib import contextmanager
@contextmanager
def invoice_root_lock(root: Path):
"""Serialize local number allocation and folder creation on Linux."""
import fcntl
root = root.expanduser().resolve()
root.mkdir(parents=True, exist_ok=True)
with (root / '.jr-einvoice.lock').open('a') as lock:
fcntl.flock(lock, fcntl.LOCK_EX)
try:
yield
finally:
fcntl.flock(lock, fcntl.LOCK_UN)