1
0
forked from erp-dev/erp
Files
erpnew/printing/management/commands/render_printing_order_docx.py

111 lines
4.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from pathlib import Path
from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from django.db.models import Count
class Command(BaseCommand):
help = "Render a PrintingOrder into a .docx template using real DB data (pick the most 'full' order by default)."
def add_arguments(self, parser):
parser.add_argument(
"--order-id",
type=int,
default=None,
help="指定 PrintingOrder.id不传则自动选择 PrintingJob 明细最多的一单",
)
parser.add_argument(
"--template",
type=str,
default=str(Path(settings.BASE_DIR) / "print-template.docx"),
help="docx 模板路径(默认 BASE_DIR/print-template.docx",
)
parser.add_argument(
"--out",
type=str,
default="",
help="输出 docx 路径(默认 .tmp_docx/printing-order-{id}.docx",
)
parser.add_argument(
"--printer",
type=str,
default="系统自动生成",
help="填充 {打印人}",
)
parser.add_argument(
"--keep-unresolved",
action="store_true",
help="不清空未命中的占位符(默认会清空)",
)
def handle(self, *args, **options):
order_id = options.get("order_id")
template = str(options.get("template") or "")
out = str(options.get("out") or "")
printer = str(options.get("printer") or "")
keep_unresolved = bool(options.get("keep_unresolved"))
tp = Path(template)
if not tp.exists():
raise CommandError(f"模板文件不存在:{template}")
if tp.suffix.lower() != ".docx":
raise CommandError("template 必须是 .docx 文件")
from printing.models import PrintingOrder
qs = PrintingOrder.objects.all()
if order_id:
order = (
qs.select_related("customer", "merchant", "process")
.prefetch_related("printing_jobs__product")
.filter(id=int(order_id))
.first()
)
if not order:
raise CommandError(f"PrintingOrder 不存在id={order_id}")
else:
order = (
qs.annotate(job_count=Count("printing_jobs"))
.filter(job_count__gt=0)
.order_by("-job_count", "-id")
.select_related("customer", "merchant", "process")
.prefetch_related("printing_jobs__product")
.first()
)
if not order:
raise CommandError("未找到包含 printing_jobs 的 PrintingOrder无法做“饱满”渲染测试")
# output path default
if not out:
out = str(Path(settings.BASE_DIR) / ".tmp_docx" / f"printing-order-{order.id}.docx")
Path(out).parent.mkdir(parents=True, exist_ok=True)
from printing.docx_template import extract_docx_placeholders, render_docx_template
from printing.print_docx_services import build_debug_context_summary, build_printing_order_docx_context
placeholders = extract_docx_placeholders(template_path=str(tp))
ctx = build_printing_order_docx_context(order=order, placeholders=placeholders, printer_label=printer)
ctx_stats = build_debug_context_summary(ctx)
stats = render_docx_template(
template_path=str(tp),
output_path=str(out),
context=ctx,
clear_unresolved=(not keep_unresolved),
)
job_count = order.printing_jobs.count()
self.stdout.write(
self.style.SUCCESS(
"渲染完成:"
f" order_id={order.id}"
f" job_count={job_count}"
f" out={out}"
f" paragraphs_touched={stats.paragraphs_touched}"
f" placeholders_replaced_or_cleared={stats.placeholders_replaced_or_cleared}"
f" context_filled={ctx_stats['context_filled_keys']}/{ctx_stats['context_total_keys']}"
)
)