Add HTTP print API for packing list and sign-off receipt

- core/printing.py: SumatraPDF silent print backend (dry_run, timeout, error capture)
- core/print_document.py: orchestrate generate() + print, per-report paper size, printer fallback
- core/print_api.py: FastAPI POST /api/print + GET /api/health, HTTPBearer auth, English Swagger at /api/docs
- serve.py: uvicorn entrypoint
- config: printers/print/api sections in settings.yaml + core/settings.py
- requirements.txt: add fastapi, uvicorn
- .gitignore: ignore logs/
This commit is contained in:
Misaka_Company
2026-08-05 16:22:59 +08:00
parent df8f25f6da
commit bf9199189a
7 changed files with 399 additions and 1 deletions

61
core/print_document.py Normal file
View File

@@ -0,0 +1,61 @@
"""打印编排:生成报表 PDF -> 送打印机。
复用现有 run.generate() 完成「查询→装配→渲染→PDF→页脚盖印」全链路
再调用 core.printing 把 PDF 静默打印到默认/指定打印机。
"""
from __future__ import annotations
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parent.parent
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
# run.py 在项目根,生成逻辑已验证;此处直接复用,不改动 run.py
import run # noqa: E402
from core.settings import settings # noqa: E402
from core import printing # noqa: E402
VALID_REPORTS = ("packing_list", "sign_receipt")
def print_document(
report_type: str,
params: dict,
printer: str | None = None,
dry_run: bool = False,
) -> dict:
"""生成报表 PDF 并打印。
:param report_type: packing_list | sign_receipt
:param params: 报表参数(如 paichan_no/box_no 或 receipt_no
:param printer: 指定打印机名;为 None 时用 settings.printers.default
:param dry_run: True 时只构造打印命令不真正执行(用于验证链路)
:return: 结构化结果(含 pdf 路径、打印命令、ok 状态)
"""
if report_type not in VALID_REPORTS:
raise ValueError(f"未知报表类型:{report_type}(支持 {list(VALID_REPORTS)}")
# 1. 生成 PDFrun.generate 内部已做 required 参数校验与 DB 查询)
output = run._default_output(report_type, params)
out_path = run.generate(report_type, params, output)
# 2. 选打印机与纸张(装箱单 A5 横向 / 签收单 A4 纵向)
target_printer = printer or settings.printers.default
paper_settings = settings.print.settings_by_report.get(
report_type, settings.print.default_settings
)
# 3. 打印
result = printing.print_pdf(
pdf_path=out_path,
printer=target_printer,
settings=paper_settings,
sumatrapdf_path=settings.print.sumatrapdf_path,
dry_run=dry_run,
)
result["report_type"] = report_type
result["params"] = params
return result