Khung trao đổi (chatter) dưới mỗi bản ghi Odoo không chỉ để người dùng gõ tay. Từ code, bạn ghi vào đó bằng message_post — để lại vết "đã xử lý đơn này", "đã đổi trạng thái vì lý do X". Nhưng có một lựa chọn quan trọng dễ bỏ qua: bạn đang ghi một ghi chú nội bộ (chỉ lưu vết) hay một bình luận (gửi thông báo cho người theo dõi)? Chọn sai là hoặc làm phiền cả phòng, hoặc để lọt thông tin cần báo.

Một lời gọi, hai kiểu tin

Cùng message_post, chỉ khác subtype_xmlid:

Ảnh chụp đoạn mã Python nền tối hai phần. Phần trên GHI CHÚ NỘI BỘ gọi the message_post body Đã kiểm tra hồ sơ khách thông tin hợp lệ subject Ghi chú nội bộ subtype_xmlid mail mt_note kèm chú thích subtype Note internal True. Phần dưới BÌNH LUẬN gọi the message_post body Đã liên hệ và gửi lời chào tới khách hàng subtype_xmlid mail mt_comment kèm chú thích subtype Discussions internal False và partner_ids the partner_id ids báo thêm cho các partner này. Bên dưới là các tham số hay dùng body nhận HTML author_id người viết attachment_ids đính kèm tệp message_type comment hoặc notification, và the message_ids là recordset mail message của bản ghi

Hình 1: message_post(body=..., subtype_xmlid=...). Với mail.mt_note — ghi chú nội bộ, chỉ để lại vết. Với mail.mt_comment — bình luận, gửi thông báo cho follower (và các partner_ids truyền thêm). body nhận HTML; còn có author_id (người viết, mặc định là user hiện tại), attachment_ids (đính kèm), message_type. Đọc lại toàn bộ tin bằng record.message_ids.

Khác biệt thật nằm ở subtype

Hai loại tin trông na ná nhau trong chatter, nên đừng phân biệt bằng mắt — phân biệt bằng subtype:

Ảnh chụp phiên odoo shell nền tối, gọi m1 bằng c message_post với subtype_xmlid mail mt_note, in m1 subtype_id name và internal trả về tuple Note và True với chú thích internal True nghĩa là không gửi cho follower, gọi m2 bằng c message_post với subtype_xmlid mail mt_comment, in m2 subtype_id name và internal trả về tuple Discussions và False với chú thích internal False nghĩa là báo follower, in len c message_ids tăng thêm 2 với chú thích cả hai đều nằm trong chatter và chú thích đo xong đã unlink 2 message test

Hình 2: Đo trực tiếp. mt_note cho ra subtype "Note" với internal=True — Odoo hiểu đây là tin chỉ nội bộ, không đẩy thông báo tới người theo dõi. mt_comment cho ra "Discussions" với internal=False — tin công khai với follower, ai theo dõi bản ghi sẽ nhận thông báo (và email nếu họ bật). Cả hai đều được lưu và hiện trong chatter — khác biệt là ở ai được báo, không phải ở chỗ hiển thị.

Cả hai tin đều nằm trong khung trao đổi của bản ghi:

Ảnh chụp khung trao đổi của Odoo trên thẻ VIP-0003, có nút Gửi tin Ghi chú Hoạt động ở trên, dải Hôm nay, rồi hai tin nhắn của OdooBot lúc 2 giờ 10, tin trên ghi Đã liên hệ và gửi lời chào tới khách hàng, tin dưới ghi Đã kiểm tra hồ sơ khách thông tin hợp lệ

Hình 3: Hai tin đã ghi hiện trong chatter thẻ VIP-0003 — một bình luận, một ghi chú nội bộ. Trên giao diện, người dùng gõ tay qua nút "Gửi tin" (tạo bình luận mt_comment) hoặc "Ghi chú" (tạo ghi chú mt_note) — đúng hai loại ta vừa tạo bằng code. Đo xong tôi xoá hai tin test để giữ thẻ sạch.

Chọn loại nào, và vài lưu ý

  • Log tự động của hệ thống → mt_note. "Cron đã chuyển thẻ này hết hạn", "server action đã cộng điểm" — những vết máy ghi nên là ghi chú nội bộ, đừng spam thông báo cho follower mỗi lần.
  • Cần người biết → mt_comment. Khi thật sự muốn báo (khách phản hồi, đơn cần duyệt), dùng bình luận; truyền partner_ids để báo đích danh người ngoài danh sách follower.
  • body là HTML — dùng được <b>, <a>, danh sách; Odoo làm sạch để chống XSS. Muốn truyền chuỗi thuần thì cứ để nguyên, nó vẫn hiển thị.
  • message_post khác activity_schedule. message_post ghi lại việc đã xảy ra (quá khứ); activity giao việc cần làm (tương lai, có hạn). Đừng dùng message_post để nhắc việc — nó không có hạn, không hiện ở systray.
  • Đừng ghi tràn. Mỗi mt_comment có thể sinh email cho follower; trong vòng lặp xử lý hàng loạt, ưu tiên mt_note hoặc gộp thành một tin tổng.

Ba ý mang về

  1. message_post(body, subtype_xmlid, ...) ghi vào chatter của bản ghi; body nhận HTML, đọc lại bằng record.message_ids.
  2. Subtype quyết định ai được báo: mail.mt_note (Note, internal=True) chỉ lưu vết nội bộ; mail.mt_comment (Discussions, internal=False) gửi thông báo cho follower — tương ứng nút "Ghi chú" và "Gửi tin" trên giao diện.
  3. Phân vai rõ: log máy → mt_note (tránh spam); cần người biết → mt_comment; và message_post ghi việc đã xảy ra, khác activity (việc cần làm).

Chatter, activity, email — đều là các tiện ích quanh dữ liệu. Giờ quay lại chính dữ liệu: mỗi thẻ có một mã như "VIP-0003" tăng dần. Ai sinh ra con số đó, và làm sao để nó không trùng? Phần sau mổ xẻ ir.sequence — tự đánh số bản ghi: tiền tố, số bước, và cái bẫy khoảng trống khi giao dịch rollback.