### 2026-01-26 工作记录

#### 1) 实验性：DOCX 打印模板（.docx）占位符渲染与“剩余变量清空”

背景：
- 用户提供 `.docx` 打印模板（示例：仓库根目录 `print-template.docx`）
- 模板变量格式为 `#{...}` / `{...}`，且在 Word/WPS 中可能被拆分到多个 run（`w:t`）里
- 需求：将业务数据套版后，**未命中的模板变量必须用空字符串清空**，避免打印出原始变量文本

落地内容（实验性，可能废弃，需保留记录）：
- 新增渲染工具：
  - `printing/docx_template.py`
    - `render_docx_template(...)`：单页 docx 的占位符替换/清空（支持跨 run 断裂）
    - `extract_docx_placeholders(...)`：从 docx 抽取占位符 key（document/header/footer）
    - `render_docx_template_pages(...)`：按页复制模板并逐页渲染（用于固定容量表格分页）
- 新增 mock 数据生成（用于“尽可能饱满”的套版验证，无需数据库）：
  - `printing/print_docx_services.py`
    - `build_mock_sales_docx_pages(...)`：按模板“每页 9 行、每行 8 个销售数量格”生成多页 context
    - 每页汇总字段（按页计算）：
      - `#{打印-销售单（8*9）.匹数}`：本页非空“销售数量”格子数
      - `#{打印-销售单（8*9）.总数量}`：本页非空“销售数量”之和
      - 同时填充 `#{...当前页码}` / `#{...总页数}`
- 新增命令（便于本地/环境快速验证）：
  - `printing/management/commands/render_docx_template.py`
    - 用法：`uv run python manage.py render_docx_template <template.docx> --out <out.docx> --context-json '{...}'`
  - `printing/management/commands/render_printing_order_docx.py`
    - 从 DB 选取 PrintingOrder 渲染（当前环境无真实数据时会提示无法执行）
  - `printing/management/commands/render_mock_docx.py`
    - 用法（多页 mock）：`uv run python manage.py render_mock_docx --pages 3 --out .tmp_docx/mock-rendered-3pages.docx`
- 新增单测（锁住行为：不残留占位符、支持分页）：
  - `printing/test_docx_template.py`
  - `printing/test_docx_pagination.py`
  - `printing/test_docx_pagination.py`（按页抽取 `w:t` 文本做断言，避免被 XML 标签分割干扰）

产物（示例输出）：
- `.tmp_docx/mock-rendered-3pages.docx`（多页 mock 套版产物，便于打开核对页码与汇总）

依赖：
- `python-docx`（通过 `uv add python-docx` 引入；同时安装 `lxml`）

#### 2) 核对：明道云“开版暂存”同步（command / task / beat）

现状确认：
- command：`api_v1/management/commands/sync_mdy_plate_orders.py`
  - 底层调用：`api_v1.mdy_plate_order_sync.sync_mdy_plate_orders_to_staging(...)`
  - 支持参数：`--request-interval-seconds`（用于限流，默认 0.02，约 50 qps 建议值）
  - 支持游标：`--use-checkpoint/--skip-checkpoint`（DataSync）
- Celery task：`api_v1/tasks.py::sync_mdy_plate_orders`
  - 已存在，但当前 `flower/settings.py::CELERY_BEAT_SCHEDULE` **未配置该 task 的定时触发**

待决策（需用户确认后再实施）：
- 是否新增 Celery Beat：每天 02:00-08:00 持续运作（轮询），并通过 `request_interval_seconds` + 每次处理上限（page/max_records/related）控制不超过明道云 QPS 限制。

更新（已实施）：
- 已新增 Celery Beat：`flower/settings.py::CELERY_BEAT_SCHEDULE['mdy_plate_order_staging_sync']`
  - 时间窗：02:00-07:59（`crontab(minute='*/2', hour='2-7')`）
  - 任务：`api_v1.tasks.sync_mdy_plate_orders`
  - 限流参数：`.env` `MDY_PLATE_ORDER_SYNC_REQUEST_INTERVAL_SECONDS`（默认 0.05）
