Bạn vẫn xem được toàn bộ bài học mà không cần đăng nhập.
Chọn sai kiểu field là nợ dữ liệu, không phải lỗi kỹ thuật. Câu hỏi phân biệt Selection với Many2one, và cách nhận ra từng kiểu bằng mắt.

Một dự án nhân sự, trường giới tính được làm thành ô nhập chữ tự do vì lúc thiết kế không ai nghĩ nó đáng bàn.
Hai năm sau, phòng nhân sự muốn thống kê tỷ lệ nam nữ theo phòng ban và phát hiện trong dữ liệu có bảy cách viết cho hai giá trị: nam, Nam, NAM, nữ, Nữ, một ô để trống, và một ô ghi là không muốn khai báo.
Không ai làm sai quy trình ở đây cả. Mỗi người nhập đúng thứ họ nghĩ, và hệ thống không có lý do gì để chặn họ.
Cái sai đã xảy ra từ hai năm trước, ở đúng một ô trong bảng mô tả trường mà lúc đó không ai coi là việc của mình.
Kiểu dữ liệu nghe như chuyện của lập trình viên, và trong tài liệu đặc tả thì cột đó hay bị bỏ trống với lý do để đội phát triển tự quyết.
Tuy nhiên theo tôi, quyết định này có ba hệ quả nghiệp vụ, và cả ba đều thuộc về người hiểu nghiệp vụ chứ không thuộc về người viết code.
Đội phát triển không có thông tin để trả lời ba câu đó.
Họ biết kiểu nào lưu được gì, còn bạn mới là người biết dữ liệu này về sau sẽ được dùng làm gì.
Nhóm kiểu đầu tiên lưu giá trị đơn lẻ và không tạo quan hệ với đối tượng nào khác. Toàn bộ hành vi mô tả trong bài này là trên Odoo 19, và đây là loại chi tiết bạn nên dựng lại trên đúng bản mình đang chạy chứ không nên tin theo trí nhớ.
Kiểu Char dùng cho chuỗi ngắn như tên, mã, tiêu đề, và trên giao diện nó thường hiển thị thành một dòng duy nhất chứ không phải một ô nhiều dòng. Kiểu Text thì dành cho nội dung dài hơn và hiển thị thành ô nhiều dòng, dùng cho mô tả chi tiết. Bên cạnh đó còn kiểu Html, cho phép định dạng chữ đậm nghiêng, màu sắc và gạch đầu dòng ngay trong ô.
Kiểu Integer dùng cho số lượng, tuổi, mã số, và có một chi tiết đáng nhớ vì nó là nguồn của những sai lệch âm thầm. Trên form, gõ một số có phần thập phân vào ô số nguyên thì ô báo không hợp lệ; nhưng khi giá trị lẻ được đẩy vào từ một phép tính, một automation hay một tích hợp thì hệ thống cắt cụt phần lẻ chứ không làm tròn, nên một phẩy chín vào thành một chứ không thành hai, và không ai nhận được thông báo nào.
Kiểu Float thì giữ được phần thập phân, dùng cho tỷ giá, khối lượng, hay số lượng theo đơn vị chia nhỏ được.
Kiểu Boolean hiển thị thành ô tích và thường kéo theo logic phía sau chứ không chỉ lưu một giá trị. Trên màn hình sản phẩm chẳng hạn, khi đã cài phân hệ bán hàng thì tích vào ô Sales sẽ làm xuất hiện cả tab Sales với phần cấu hình bán hàng, bỏ tích thì tab đó biến mất. Đây là lý do bạn phải mô tả rõ trong tài liệu rằng tích vào ô này thì cái gì xuất hiện, thay vì chỉ ghi tên trường.
Riêng với tiền tệ thì có kiểu chuyên dụng Monetary, đi kèm một trường chỉ ra đơn vị tiền tệ, nhờ đó số chữ số thập phân và ký hiệu tiền được lấy đúng theo đồng tiền của từng bản ghi. Dùng Float cho tiền thì vẫn chạy, nhưng bạn mất phần xử lý đơn vị tiền tệ mà hệ thống làm sẵn.
Còn một kiểu nữa trong nhóm này mà bảng mô tả trường hay bỏ quên, đó là Binary, kiểu lưu dữ liệu nhị phân như tệp đính kèm, cùng biến thể Image dành cho ảnh. Dấu hiệu nhận ra nó rất đơn giản: chỗ nào tải tệp lên hoặc tải về được thì đó là kiểu này, chẳng hạn ảnh sản phẩm hay ảnh đại diện của một liên hệ.
Dưới góc nhìn nghiệp vụ, tôi thấy kiểu này kéo theo ba câu hỏi nên hỏi ngay lúc thiết kế.
Hai kiểu Date và Datetime khác nhau đúng một chuyện, và ranh giới giữa chúng được quyết định bởi đúng một câu hỏi: trường này có thật sự cần lưu giờ không.
Ngày ký hợp đồng thì không cần giờ. Thời điểm tạo đơn hàng thì cần, vì bạn sẽ muốn biết đơn nào tới trước đơn nào tới sau trong cùng một ngày.
Câu hỏi nghe đơn giản nhưng nó đáng hỏi, bởi chọn kiểu có giờ khi không cần thì người dùng phải nhập thêm một thông tin vô nghĩa mỗi lần, còn chọn kiểu không có giờ khi cần thì tới lúc muốn xếp thứ tự trong ngày bạn không có gì để xếp.
Đây là quyết định hay gặp nhất và cũng là chỗ chọn sai tốn kém nhất, nên đáng dành riêng một mục. Trước khi vào thì cần nói rõ một chuyện về cách gọi tên: Many2one và One2many hay bị coi là hai chuyện riêng, nhưng thực ra chúng là hai đầu của cùng một quan hệ, tức quan hệ nhiều-một nhìn từ hai phía, và Many2one không phải quan hệ một-một như đôi khi vẫn bị ghi nhầm trong tài liệu.
Selection và Many2one nhìn trên màn hình khá giống nhau, vì cả hai đều cho người dùng chọn một giá trị từ một danh sách thả xuống. Khác biệt nằm ở chỗ danh sách đó đến từ đâu.
Selection có danh sách được cố định ngay trong thiết kế, nên muốn thêm một giá trị mới thì phải sửa hệ thống chứ người dùng không tự thêm được. Many2one thì ngược lại: danh sách chính là các bản ghi của một đối tượng khác, nên nó lớn dần theo thời gian và người dùng tự thêm được nếu có quyền.
Từ đó ra tiêu chí phân biệt, và đây là cách tôi vẫn dùng để quyết trong vài giây. Nếu danh sách là một tập cố định, hiếm khi đổi, và việc thêm một giá trị mới là chuyện lớn cần cân nhắc, như giới tính, loại khách hàng hay trạng thái, thì đó là Selection. Nếu danh sách phát sinh trong vận hành và việc thêm một giá trị mới là chuyện bình thường hằng ngày, như khách hàng, sản phẩm hay nhà cung cấp, thì đó là Many2one.
Bên cạnh đó còn một cặp hay bị nhầm nữa, đáng nói ngay ở đây, đó là giữa Boolean với một Selection chỉ có hai giá trị hiển thị dạng nút tròn. Trên màn hình chúng trông giống nhau tới mức khó phân, nhưng có một dấu hiệu rất chắc: Boolean thì tích vào rồi bỏ tích ra được, còn Selection dạng nút tròn thì một khi đã chọn là không trả về trống được nữa mà chỉ chuyển sang giá trị khác.
Lựa chọn Person hay Company trên màn hình liên hệ là ví dụ quen thuộc: chỉ có hai giá trị nhưng nó là Selection chứ không phải Boolean.
Quay lại cặp chính, chọn sai theo hướng thứ nhất, tức dùng Selection cho thứ lẽ ra là quan hệ, thì bạn sẽ phải gọi đội phát triển mỗi lần khách có thêm một dòng danh mục. Chọn sai theo hướng ngược lại thì bạn có một danh mục mà ai cũng thêm được, và sau một năm nó đầy những giá trị trùng nhau chỉ khác cách viết, tức đúng câu chuyện ở đầu bài, chỉ ở một mức độ tinh vi hơn.
Chỉ ba kiểu tạo ra quan hệ thật giữa hai đối tượng, và trên giao diện thì mỗi kiểu có một dấu hiệu riêng.
Cần lưu ý rằng dấu hiệu nhận dạng chỉ là thường thấy chứ không phải luôn đúng. Cùng là One2many nhưng danh sách địa chỉ và người liên hệ của một công ty lại hiện thành các ô thẻ xếp cạnh nhau chứ không phải một bảng; và cùng là Many2many nhưng trường tuyến cung ứng trên màn hình sản phẩm lại hiện thành danh sách ô tích chứ không phải thẻ.
Do đó khi cần chắc chắn thì vẫn phải tra bằng công cụ chứ không đoán bằng mắt, và cách tra là chủ đề của bài về chế độ nhà phát triển ngay sau bài này.
Đi kèm ba kiểu này có ba lưu ý mà bạn nên ghi vào tài liệu.
Lưu ý thứ nhất là quyền dữ liệu. Muốn người dùng chọn được khách hàng trong đơn hàng thì họ phải có quyền đọc dữ liệu liên hệ.
Trên Odoo 19, một người có quyền tạo đơn mà không có quyền đọc liên hệ vẫn thấy tên khách trên đơn có sẵn, nhưng gõ tìm để chọn khách hay bấm mở sang bản ghi khách hàng thì sẽ vướng lỗi thiếu quyền, và đây là loại sự cố rất khó đoán nếu bạn không biết trước. Cách phân quyền cho đúng thì tôi để ở bài riêng.
Lưu ý thứ hai là chuyện tạo mới ngay tại chỗ. Với một ô Many2one, người dùng gõ một cái tên chưa có thì mặc định hệ thống mời họ tạo mới luôn. Đây là hành vi tiện nhưng cũng là nguồn sinh dữ liệu rác, nên trong tài liệu bạn phải nêu rõ trường này có được phép tạo mới ngay tại đó hay không.
Lưu ý thứ ba là đừng lạm dụng One2many. Nó không phải một cột lưu trên bản ghi mà là một danh sách hệ thống phải đi đọc từ đối tượng bên kia mỗi khi cần hiển thị, nên nguyên tắc là chỉ dùng khi thật sự cần một danh sách chứ không phải khi chỉ cần một tham chiếu.
Trong nhiều bảng liệt kê kiểu field có một dòng không giống các dòng còn lại, đó là trường lấy dữ liệu qua một liên kết có sẵn, hay còn gọi là trường related.
Nó không tạo ra quan hệ mới mà dựa vào một quan hệ đã có để kéo thông tin về hiển thị. Trên đơn hàng đã có liên kết tới khách hàng thì bạn thêm được các trường lấy số điện thoại, email, địa chỉ của khách về ngay trên đơn, mà không phải nhập lại và cũng không tạo thêm liên kết nào.
Cần lưu ý rằng related là một thuộc tính đặt lên một trường chứ không phải một kiểu, và tài liệu chính thức của Odoo xếp nó là một trường hợp riêng của trường tính toán. Một trường related lấy số điện thoại thì vẫn có kiểu Char, lấy khách hàng thì vẫn có kiểu Many2one.
Do đó nếu bạn gặp những bảng đếm số kiểu field lệch nhau một dòng giữa các nguồn, chỗ lệch thường nằm ở đây, và trong cột kiểu dữ liệu của tài liệu thì bạn ghi kiểu thật của trường kèm chú thích nó lấy từ đâu.
Còn một thứ nữa cũng không phải kiểu dữ liệu, và nó thậm chí không nằm trong bảng, đó là widget, tức tiện ích hiển thị. Một trường điện thoại về bản chất là kiểu Char, nhưng khi gắn widget dành cho điện thoại thì trên màn hình nó thành đường liên kết bấm để gọi, và người dùng nhìn thấy một trải nghiệm khác hẳn với một trường Char thường.
Nhầm hai thứ này với nhau thì bạn sẽ ghi sai kiểu trong tài liệu, và đội phát triển làm ra một trường trông giống nhưng hành xử khác.
Sau khi chọn xong thì phần còn lại là ghi cho đúng, và ở đây có một quy tắc giao tiếp đáng nhớ hơn cả kỹ thuật.
Quy tắc đó là nói tên kỹ thuật với đội phát triển, nói nhãn hiển thị với khách hàng. Vì sao bảng mô tả trường phải tách hai cột ấy, cùng cách trình bày đầy đủ của bảng gồm những cột nào và mỗi cột tồn tại để làm gì, tôi đã nói ở bài về bảng GUI element, và bài về chế độ nhà phát triển sẽ quay lại quy tắc này từ phía công cụ.
Điều cần nhớ ở đây chỉ là cột kiểu dữ liệu không phải cột để điền cho đủ, nó là chỗ ghi lại một quyết định nghiệp vụ mà bạn vừa đưa ra.
Chọn xong kiểu và ghi xong tài liệu thì còn một câu hỏi nữa về chính những trường đó, và câu này thì không nằm trong bảng: ai được nhìn thấy trường nào.
Thảo luận (0)
Bạn cần đăng nhập để thảo luận