Ở phần trước, server action "Cộng 5 điểm tri ân" tự dưng xuất hiện trong menu ⚙ Tác vụ. Còn hai report thì nằm ở nút In. Không phải Odoo đoán mò — cả ba đều được bind vào model qua đúng ba trường, và chính ba trường đó quyết định loại action nào hiện ở menu nào, trên view nào. Hiểu chúng, bạn gắn được bất kỳ action nào vào đúng chỗ trong menu ngữ cảnh.
Ba trường quyết định tất cả
Bất kỳ action nào — server action, report, act_window, client action — đều gắn vào menu ngữ cảnh của một model bằng ba trường:

Hình 1: Ba trường. binding_model_id nói action gắn vào model nào. binding_type quyết định menu nào: action (mặc định) đưa vào ⚙ Tác vụ, report đưa vào nút In. binding_view_types (list, form, kanban...) giới hạn action chỉ hiện ở những view đó. Bỏ một trong ba đi là action lạc chỗ hoặc biến mất khỏi menu.
Một điểm cú pháp quan trọng và dễ sai: <record> khai binding phải nạp sau khi model đã tồn tại, vì nó tham chiếu ref="model_quan_the_thanh_vien" — external id của model chỉ có sau khi model được đăng ký. Nếu file binding nạp quá sớm trong data của manifest, ref chưa phân giải được và module lỗi khi cài.
Cùng cơ chế, hai đích đến
binding_type chia action thành hai nhóm rơi vào hai menu khác nhau. Report có binding_type="report" rơi vào nút In:

Hình 2: Nút In mở ra — bên trong là hai report đã bind: "Thẻ thành viên" và "Sao kê điểm theo tháng". Chúng không lẫn vào menu Tác vụ (chỗ của server action) vì binding_type="report" đẩy chúng sang đây. Hai rổ tách biệt, hai menu riêng, cùng một cơ chế binding phía sau.
Nhìn lại phần trước: server action "Cộng 5 điểm tri ân" nằm ở Tác vụ, còn hai report này ở In — chỉ khác nhau đúng giá trị binding_type.
Registry đứng sau: get_bindings
Web client không tự đoán menu. Nó gọi một hàm registry để lấy danh sách action đã bind cho model, rồi dựng menu từ đó. Bạn gọi được chính hàm đó trong shell:

Hình 3: get_bindings('quan.the.thanh.vien') trả về một dict với các rổ 'action' và 'report' (và 'print'). Rổ action chứa server action, rổ report chứa hai report — đúng những gì thấy trên hai menu. Đây là nguồn sự thật mà giao diện đọc để dựng menu ngữ cảnh; muốn biết vì sao một action hiện/không hiện, soi hàm này là ra.
Vài lưu ý khi bind
binding_typemặc định làaction. Server action và act_window không cần khai nếu muốn vào Tác vụ; report thì bắt buộc ghireportđể vào nút In.binding_view_typeslọc theo view. Muốn một lệnh chỉ chạy khi mở một bản ghi (form) mà không cho chạy hàng loạt từ list, đặtbinding_view_types="form"— nó biến mất khỏi menu Tác vụ của list.- Gỡ action khỏi menu = xoá
binding_model_id. Action vẫn tồn tại và gọi được bằng code/menu, chỉ là không còn tự hiện trong menu ngữ cảnh nữa. - act_window cũng bind được để "mở danh sách liên quan" từ menu Tác vụ — không chỉ server action mới vào được đó.
Ba ý mang về
- Ba trường
binding_model_id+binding_type+binding_view_typesquyết định action của bạn hiện ở menu nào, trên view nào của model nào — đây là cách gắn bất kỳ action vào menu ngữ cảnh. binding_typechia đích đến:action(mặc định) → ⚙ Tác vụ;report→ nút In. Cùng cơ chế, hai rổ tách biệt.get_bindings(model)là registry web client đọc để dựng menu; khai binding phải nằm sau khi model tồn tại (dùngref="model_..."), và gỡ binding chỉ là xoábinding_model_id.
Đến đây ta đã điều khiển action theo người dùng bấm. Nhưng có những việc phải tự chạy không cần ai bấm — dọn dữ liệu ban đêm, gửi nhắc hạn thẻ mỗi sáng. Phần sau bước vào ir.cron — việc chạy định kỳ: khai một tác vụ nền, đặt chu kỳ, và gọi đúng method của model.