Mở một đơn hàng, một hoá đơn, một phiếu nghỉ phép trong Odoo — góc trên bên phải luôn có một dải các bước: Nháp → Đã xác nhận → Hoàn tất, với bước hiện tại được tô sáng. Dải đó tên là statusbar, và nó chỉ là một field Selection được hiển thị bằng một widget đặc biệt. Nó biến một field trạng thái khô khan thành một quy trình mà người dùng nhìn phát biết đang ở đâu. Bài này biến field trang_thai của thẻ thành viên thành statusbar và xem nó chạy.

Field Selection + widget statusbar

statusbar cần hai thứ: một field Selection (các bước) và widget statusbar đặt trong <header>:

# Model: field Selection các bước quy trình
trang_thai = fields.Selection([
    ('moi', 'Mới cấp'), ('dang_dung', 'Đang dùng'),
    ('het_han', 'Hết hạn'), ('khoa', 'Đã khoá')], default='moi')
<header>
  <button name="action_gia_han" type="object" string="Gia hạn thẻ"/>
  <field name="trang_thai" widget="statusbar"
         statusbar_visible="moi,dang_dung,het_han"   <!-- các bước LUÔN hiện -->
         options="{'clickable': '1'}"/>              <!-- cho bấm để chuyển -->
</header>

Ảnh chụp mã Python và XML nền tối, phần Python định nghĩa field trang_thai kiểu Selection với bốn cặp giá trị moi Mới cấp, dang_dung Đang dùng, het_han Hết hạn, khoa Đã khoá và mặc định moi, phần XML một thẻ header chứa một button action_gia_han và một field trang_thai widget statusbar với statusbar_visible liệt kê moi dang_dung het_han là các bước luôn hiện và options clickable bằng 1 cho phép bấm để chuyển, kèm chú thích rằng bước không liệt kê như khoa chỉ hiện khi đang ở đó và clickable cho người dùng bấm thẳng vào bước

Hình 1: Cấu tạo statusbar. Field trang_thai là Selection bình thường; widget="statusbar" trong <header> biến nó thành dải bước. statusbar_visible liệt kê các bước luôn hiện (moi,dang_dung,het_han); bước không liệt kê (khoa) chỉ hiện khi đang ở đó rồi ẩn — hợp cho trạng thái ngoại lệ. options="{'clickable': '1'}" cho người dùng bấm thẳng vào bước để chuyển.

Xem thật: quy trình ở đầu form

Đặt statusbar vào header và mở thẻ VIP-0003 (đang ở "Đang dùng"):

Ảnh chụp phần đầu form Odoo thẻ VIP-0003 hạng Vàng, góc trên bên phải header là dải statusbar ba bước Mới cấp rồi Đang dùng rồi Hết hạn với bước Đang dùng được tô sáng màu tím dạng mũi tên cho biết đang ở trạng thái đó, bên trái header là nút Cộng điểm màu xám, thân form hiển thị Mã thẻ VIP-0003 nhãn Khách hàng đỏ và ảnh thẻ tím góc phải

Hình 2: statusbar chạy thật. Dải "Mới cấp → Đang dùng → Hết hạn" nằm góc phải header; bước "Đang dùng" được tô sáng (dạng mũi tên tím) vì thẻ đang ở trạng thái đó. Người dùng nhìn phát biết thẻ đang ở đâu trong vòng đời. Trạng thái "Đã khoá" không hiện ở đây (không nằm trong statusbar_visible) — nó chỉ xuất hiện khi thẻ thực sự bị khoá.

Nhờ clickable, người dùng có thể bấm thẳng vào "Hết hạn" để chuyển trạng thái — hoặc dùng nút quy trình (như "Gia hạn thẻ") để chuyển kèm logic. Hai cách bổ trợ nhau.

statusbar_visible: giấu bước ngoại lệ

Đây là điểm tinh tế hay bị bỏ qua. Một quy trình thường có luồng chính (nháp → xác nhận → xong) và vài trạng thái ngoại lệ (huỷ, khoá). Bạn muốn dải bước chỉ hiện luồng chính cho gọn, còn trạng thái ngoại lệ chỉ hiện khi đang ở đó:

  • Liệt kê luồng chính trong statusbar_visible → luôn hiện, thành các bước cố định.
  • Không liệt kê trạng thái ngoại lệ → nó chỉ hiện khi bản ghi thực sự ở đó, xong thì ẩn.

Ví dụ ở đây: moi,dang_dung,het_han là luồng chính; khoa không liệt kê nên chỉ hiện khi thẻ bị khoá. Nhờ vậy dải bước không bị rối bởi mọi trạng thái có thể có.

Kết hợp statusbar với nút quy trình

Trong thực tế, statusbar hiếm khi đứng một mình — nó đi cùng nút (xem bài nút):

  • Nút chạy logic khi chuyển trạng thái (kiểm điều kiện, cộng điểm, gửi mail) rồi write trạng thái mới.
  • statusbar hiển thị trạng thái và (nếu clickable) cho chuyển nhanh những bước không cần logic.

Mẫu điển hình: nút "Xác nhận" (có logic) + statusbar hiện luồng. Người dùng bấm nút cho bước quan trọng, bấm statusbar cho bước đơn giản.

Vài lưu ý Odoo 19

  • statusbar đặt trong <header>, thường góc phải (Odoo tự căn).
  • clickable cho bấm chuyển thẳng — cẩn thận: nó bỏ qua logic nút, nên chỉ bật khi chuyển bước không cần kiểm gì.
  • statusbar_visible dùng tên kỹ thuật của các giá trị (không phải nhãn), ngăn cách bằng dấu phẩy.
  • Field Selection động (sinh từ method) vẫn dùng statusbar được, miễn các giá trị ổn định.
  • Với quy trình phức tạp nhiều nhánh, cân nhắc field state chuẩn + tracking=True để chatter ghi lại mỗi lần đổi (bài sau).

Ba ý mang về

  1. statusbar biến một field Selection thành dải bước quy trình ở đầu form: widget="statusbar" trong <header>, bước hiện tại tô sáng. Đã chứng minh: "Mới cấp → Đang dùng → Hết hạn" với "Đang dùng" sáng.
  2. statusbar_visible="a,b,c" liệt kê luồng chính luôn hiện; trạng thái ngoại lệ (như khoa) không liệt kê thì chỉ hiện khi đang ở đó — giữ dải bước gọn.
  3. options="{'clickable': '1'}" cho bấm chuyển thẳng; kết hợp với nút quy trình (nút chạy logic + write, statusbar hiển thị) là mẫu chuẩn.

statusbar hiển thị trạng thái, nhưng ai đã đổi và khi nào? Đó là việc của khung trao đổi bên phải form: Phần sau mổ xẻ chatter — gắn mail.thread lên form để có lịch sử thay đổi, ghi chú, và trao đổi ngay trên bản ghi.