Chuỗi bài về action khép lại bằng loại có sản phẩm cầm nắm được: report action (ir.actions.report). Nó biến một (hay nhiều) bản ghi thành tài liệu in được — hoá đơn, phiếu, thẻ — bằng cách trỏ tới một template QWeb, để Odoo render HTML rồi xuất ra PDF. Đây cũng là bài thứ 100 của loạt; đúng dịp dựng một thứ hoàn chỉnh: in một tấm thẻ thành viên ra PDF có logo và khung công ty.

Hai mảnh: report action + template QWeb

Report gồm một bản ghi ir.actions.report (khai in cái gì, kiểu gì) và một template QWeb (vẽ nội dung). Report action trỏ tới template qua report_name:

Ảnh chụp đoạn mã nền tối hai phần: phần report action model ir.actions.report với model quan.the.thanh.vien, report_type qweb-pdf, report_name quan_ca_phe.report_the_document, binding_model_id và binding_type report để hiện ở menu In; phần template QWeb id report_the_document lồng t-call web.html_container rồi t-foreach docs t-as o rồi t-call web.external_layout để có khung công ty, bên trong div page có h2 Thẻ thành viên với t-field o.name và span t-field o.diem điểm; kèm chú thích report_name khớp external id template, t-field tự format, thiếu wkhtmltopdf dùng qweb-html xem ở report html

Hình 1: report_type="qweb-pdf" (hoặc qweb-html). report_name phải khớp external id của template. Template dùng t-foreach="docs" để lặp các bản ghi được in, t-call="web.external_layout" mượn khung công ty (header/footer), và t-field để in field tự format. binding_type="report" khiến report hiện ở menu In.

Ba biến/khái niệm cốt lõi của QWeb report:

  • docs — biến chứa recordset đang in (một hay nhiều bản ghi).
  • web.external_layout — template chuẩn của Odoo bọc nội dung trong khung công ty: logo, địa chỉ, chân trang. Bạn chỉ viết phần ruột.
  • t-field vs t-esc — t-field="o.ngay_cap" tự format theo kiểu field (ngày ra dd/mm/yyyy, tiền có ký hiệu, selection ra nhãn); t-esc in thô giá trị.

Tấm thẻ in ra thật

Sau khi nâng cấp, mở bản render của report cho thẻ VIP-0001:

Ảnh chụp tài liệu report Odoo thật đã render: trên cùng là logo Cà Phê Việt và khối địa chỉ Công ty TNHH Cà Phê Việt 128 Đường Nguyễn Huệ Phường Bến Nghé Quận 1 Thành phố Hồ Chí Minh cùng Tax ID; giữa là tiêu đề nâu Thẻ thành viên VIP-0001 và bảng Khách hàng Nguyễn Văn An, Hạng thẻ Bạc, Điểm tích luỹ 150 điểm, Trạng thái Đang dùng, Ngày cấp 03 09 2026; dưới là dòng cảm ơn và chân trang số điện thoại email website

Hình 2: Report render đầy đủ. Khung công ty (logo, địa chỉ, Tax ID ở đầu; điện thoại/email/website ở chân) đến từ external_layout — tôi không viết dòng nào cho nó. Phần ruột là bảng thông tin thẻ: khách hàng, hạng, điểm, trạng thái, ngày cấp — mỗi ô là một t-field. Cùng report này render ra PDF thật (đo được 54.072 byte qua _render_qweb_pdf).

Đây là kết quả của cả chuỗi: dữ liệu trong model → template QWeb → HTML → PDF. Người dùng chỉ bấm "In", nhận tờ tài liệu chỉn chu.

PDF hay HTML?

  • qweb-pdf cần wkhtmltopdf (engine chuyển HTML→PDF) cài trên máy chủ. Có sẵn thì bấm In là tải PDF.
  • qweb-html không cần engine — report hiện thẳng dạng trang web. Hữu ích khi máy chủ thiếu wkhtmltopdf, hoặc để xem nhanh khi phát triển: mở /report/html/<report_name>/<id> là thấy ngay, không cần dựng PDF.

Mẹo phát triển: luôn xem bản HTML trước (/report/html/...) để chỉnh template cho nhanh, rồi mới thử PDF — vì lỗi template hiện rõ ở HTML, còn PDF thì khó soi hơn.

Vài lưu ý

  • report_name khớp external id template, gồm cả tên module: quan_ca_phe.report_the_document. Lệch là báo cáo không tìm thấy template.
  • external_layout cho khung chuẩn; nếu muốn khung trắng trơn, dùng web.basic_layout.
  • CSS report khai vào bó web.report_assets_common/web.report_assets_pdf nếu cần style riêng cho bản in; style inline đơn giản thì viết thẳng như ở đây.
  • t-field cần một field thật của bản ghi để biết cách format; biểu thức tính toán thì dùng t-esc.

Ba ý mang về

  1. Report action (ir.actions.report) + template QWeb biến bản ghi thành tài liệu in; report_name khớp external id template, report_type là qweb-pdf hoặc qweb-html, binding_type="report" đưa nút In vào menu.
  2. Template dùng docs (recordset in), web.external_layout (khung công ty), t-field (tự format) / t-esc (in thô) — bạn chỉ viết phần ruột, Odoo lo header/footer và chuyển HTML→PDF.
  3. qweb-pdf cần wkhtmltopdf; qweb-html xem ngay ở /report/html/<name>/<id> — dùng HTML để chỉnh template nhanh khi phát triển.

Vậy là trọn bộ action (window, server, client, URL, report). Sang chương mới: Phần sau về wizard với TransientModel — mô hình "tạm" cho các hộp thoại nhập liệu nhiều bước mà không lưu rác vào cơ sở dữ liệu.