Add sign-off receipt report and refine packing list: single-line info bar, real-glyph row height, auto-paginated detail table
- Packing list: info bar changed to a single-line three-column layout (schedule no. | order no. | box no.); packing date moved to bottom-right on the same row as the total; date separator changed to slash - Packing list: range column widened 20->30mm; quantity/position-no./remark start shifted right 10mm; remark column narrowed to compensate; total width unchanged - Packing list: detail cells now use line_spacing=1.0 + valign=top; separators changed to thin solid lines at row bottom (+1mm line spacing); placeholder empty rows no longer step y - Packing list: row height estimation now uses fpdf2's same simhei glyph measured width (replacing rough character-count estimate); _clean adds control-character cleanup - New sign-off receipt report reports/sign_receipt: master+detail linked query, ReportBro auto-paginated table, PyMuPDF stamped footer (document no. / page no. / sign-off column) - run.py: required params now read from each report's config.yaml; default output path auto-generated; added transform.stamp_footer post-processing hook - .gitignore: ignore .workbuddy/
This commit is contained in:
49
run.py
49
run.py
@@ -27,6 +27,7 @@ if str(PROJECT_ROOT) not in sys.path:
|
||||
|
||||
from core.db import run_query # noqa: E402
|
||||
from core.fonts import additional_fonts # noqa: E402
|
||||
import yaml # noqa: E402
|
||||
|
||||
|
||||
def parse_params(param_strs: list[str]) -> dict:
|
||||
@@ -48,6 +49,37 @@ def parse_params(param_strs: list[str]) -> dict:
|
||||
return params
|
||||
|
||||
|
||||
def _load_config(report_dir: Path) -> dict | None:
|
||||
"""读取报表目录下的 config.yaml(不存在返回 None)。"""
|
||||
cfg_path = report_dir / "config.yaml"
|
||||
if not cfg_path.exists():
|
||||
return None
|
||||
with open(cfg_path, "r", encoding="utf-8") as f:
|
||||
return yaml.safe_load(f)
|
||||
|
||||
|
||||
def _required_params(report_dir: Path) -> set[str]:
|
||||
"""从 config.yaml 收集标记为 required 的参数名(兼容各报表)。"""
|
||||
cfg = _load_config(report_dir)
|
||||
if not cfg or "params" not in cfg:
|
||||
return set()
|
||||
return {
|
||||
name
|
||||
for name, spec in cfg["params"].items()
|
||||
if isinstance(spec, dict) and spec.get("required")
|
||||
}
|
||||
|
||||
|
||||
def _default_output(report_name: str, params: dict) -> str:
|
||||
"""根据参数智能生成默认输出路径。"""
|
||||
if "receipt_no" in params:
|
||||
return f"out/{params['receipt_no']}.pdf"
|
||||
if "paichan_no" in params:
|
||||
bn = params.get("box_no", 0)
|
||||
return f"out/{params['paichan_no']}_box{bn}.pdf"
|
||||
return f"out/{report_name}.pdf"
|
||||
|
||||
|
||||
def generate(report_name: str, params: dict, output: str) -> Path:
|
||||
"""生成指定报表的 PDF。"""
|
||||
from reportbro import Report # 延迟导入,CLI 报错时信息更清晰
|
||||
@@ -56,8 +88,8 @@ def generate(report_name: str, params: dict, output: str) -> Path:
|
||||
if not report_dir.is_dir():
|
||||
raise FileNotFoundError(f"报表不存在:{report_dir}(检查 --report 名称)")
|
||||
|
||||
# 必需参数校验
|
||||
required = {"paichan_no", "box_no"}
|
||||
# 必需参数校验(从 config.yaml 读取,兼容各报表)
|
||||
required = _required_params(report_dir)
|
||||
missing = required - params.keys()
|
||||
if missing:
|
||||
raise ValueError(f"缺少必需参数:{', '.join(sorted(missing))}(用 --param key=value 提供)")
|
||||
@@ -89,6 +121,13 @@ def generate(report_name: str, params: dict, output: str) -> Path:
|
||||
out_path = PROJECT_ROOT / out_path
|
||||
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
report.generate_pdf(str(out_path))
|
||||
|
||||
# 报表级后处理:如报表模块提供 stamp_footer(签收单用 PyMuPDF 盖印页脚家具),
|
||||
# 则在已生成 PDF 上逐页盖印单据号/页码/签收栏等。其它报表无此函数则跳过。
|
||||
stamp_fn = getattr(transform, "stamp_footer", None)
|
||||
if stamp_fn is not None:
|
||||
stamp_fn(str(out_path), context)
|
||||
|
||||
return out_path
|
||||
|
||||
|
||||
@@ -104,11 +143,7 @@ def main(argv: list[str] | None = None) -> int:
|
||||
|
||||
try:
|
||||
params = parse_params(args.param)
|
||||
output = args.output
|
||||
if not output:
|
||||
pc = params.get("paichan_no", "report")
|
||||
bn = params.get("box_no", 0)
|
||||
output = f"out/{pc}_box{bn}.pdf"
|
||||
output = args.output or _default_output(args.report, params)
|
||||
|
||||
out_path = generate(args.report, params, output)
|
||||
print(f"✅ 已生成:{out_path}")
|
||||
|
||||
Reference in New Issue
Block a user