Từ đầu loạt bài về giao diện, ta chỉ dùng những gì Odoo cho sẵn: widget, class Bootstrap, bố cục group. Nhưng khi cần một diện mạo riêng — màu thương hiệu, khoảng cách khác, một vạch nhấn — thì phải chạm tới CSS. Và cách làm đúng của Odoo không phải sửa file lõi, mà thêm một file SCSS của chính module rồi khai vào bó asset. Bài này nhuộm form thẻ thành viên theo tông cà phê để minh hoạ.

SCSS trong module, khai vào assets

Odoo biên dịch SCSS (biến, lồng, mixin) ngay trong hệ thống asset. Ta đặt file .scss vào static/src/ của module, viết style, rồi khai đường dẫn vào web.assets_backend trong manifest:

Ảnh chụp đoạn mã nền tối hai phần: phần SCSS khai hai biến ca_phe_nau màu 6f4e37 và ca_phe_kem, rồi khối .o_quan_form lồng các quy tắc cho .oe_title h1 đổi màu nâu và border-left, .o_horizontal_separator màu nâu, .o_form_sheet nền gradient kem sang trắng; phần manifest khai assets web.assets_backend với đường dẫn file scss; kèm chú thích form gắn class o_quan_form để CSS chỉ áp cho form của mình, Odoo biên dịch SCSS và nhắm class có sẵn hoặc class riêng, đừng sửa file core

Hình 1: File SCSS dùng biến ($ca-phe-nau) và lồng (nesting) — đặc trưng của SCSS. Nó nhắm class .o_quan_form (ta tự gắn vào <form>) để giới hạn phạm vi, cùng vài class có sẵn của Odoo (.oe_title, .o_horizontal_separator, .o_form_sheet). Manifest khai file vào web.assets_backend.

Mấu chốt của "làm đúng": tôi thêm class="o_quan_form" vào chính thẻ <form> của mình, rồi mọi quy tắc bọc trong .o_quan_form. Nhờ vậy CSS chỉ tác động form của module này, không rò rỉ sang form khác của Odoo.

Form nhuộm màu cà phê

Sau khi nâng cấp module, mở form thẻ VIP-0001:

Ảnh chụp giao diện Odoo thật form thẻ VIP-0001 sau khi áp SCSS: mã thẻ VIP-0001 in màu nâu cà phê với một vạch dọc nâu bên trái làm điểm nhấn, hai tiêu đề nhóm THÔNG TIN THẺ và ĐIỂM VÀ SỐ DƯ cũng màu nâu, phần đầu của sheet có nền chuyển sắc kem nhạt rồi nhạt dần về trắng; bên dưới là các field chủ thẻ ngày cấp điểm tích luỹ hạng thẻ số dư tiền tệ ưu đãi

Hình 2: Kết quả. "VIP-0001" giờ màu nâu cà phê (#6f4e37) với vạch nhấn dọc bên trái. Hai tiêu đề nhóm cũng nâu cho đồng bộ. Đỉnh sheet có nền gradient kem nhạt dần về trắng. Tất cả từ đúng một file SCSS, không đụng gì tới lõi Odoo.

Đây là kiểu tuỳ biến hay gặp khi làm module cho khách: gắn màu thương hiệu, tạo điểm nhấn cho màn hình quan trọng, mà vẫn nâng cấp Odoo bình thường vì không sửa core.

Nguyên tắc tuỳ biến an toàn

  • Đừng sửa file lõi Odoo. Mọi tuỳ biến nằm trong asset của module bạn. Sửa core là mất hết khi nâng cấp, và vỡ ở chỗ khó lần.
  • Giới hạn phạm vi. Bọc quy tắc trong một class riêng bạn kiểm soát (.o_quan_form) để không vô tình đổi giao diện toàn hệ thống. CSS toàn cục rất dễ gây hiệu ứng phụ.
  • Nhắm class ổn định. Class kiểu .o_form_view, .oe_title, .o_list_view khá bền qua các bản Odoo. Tránh bám vào class sinh động hoặc cấu trúc DOM sâu dễ đổi.
  • SCSS cho bạn biến và lồng — dùng biến cho màu thương hiệu để đổi một chỗ áp mọi nơi; lồng cho gọn. Odoo lo phần biên dịch.

Vài lưu ý kỹ thuật

  • File SCSS phải được khai trong manifest mới có tác dụng — chỉ tạo file không đủ. (Cơ chế asset là chủ đề bài sau.)
  • Nâng cấp module (-u) để Odoo nạp lại danh sách asset sau khi sửa manifest; sửa nội dung file SCSS thì thường chỉ cần tải lại trang (Odoo build lại asset), nhưng thêm/bớt file thì cần -u.
  • Xung đột độ ưu tiên: CSS của Odoo có thể mạnh hơn; khi cần, tăng độ đặc hiệu bằng cách lồng sâu hơn thay vì lạm dụng !important.

Ba ý mang về

  1. Tuỳ biến giao diện backend bằng SCSS của chính module: đặt file trong static/src/, khai vào web.assets_backend; Odoo biên dịch SCSS (biến, lồng) — không bao giờ sửa file core.
  2. Giới hạn phạm vi bằng class riêng (gắn vào view của bạn) để CSS chỉ áp đúng chỗ, tránh rò rỉ ra toàn hệ thống; nhắm các class ổn định của Odoo.
  3. File phải được khai trong manifest mới chạy; -u để nạp lại khi thêm/bớt file; tăng độ đặc hiệu bằng lồng thay vì lạm dụng !important.

Ta vừa viết CSS/SCSS. Bài sau đi sâu vào cơ chế đứng sau nó: Phần sau về assets_backend — cách Odoo gom, nạp và phân bó các file CSS/JS, và những bó asset khác nhau (backend, frontend, điểm bán hàng...) khác nhau ra sao.