Nâng cấp addon lên Odoo 20 - tổng hợp thay đổi kỹ thuật

  Nov 12, 2026      2m      0   
 

Tut 23: Nâng cấp addon lên Odoo 20 - tổng hợp thay đổi kỹ thuật

Nâng cấp addon lên Odoo 20 - tổng hợp thay đổi kỹ thuật

Odoo Tut 23: Nâng cấp addon lên Odoo 20 - tổng hợp thay đổi kỹ thuật

Phần lớn thay đổi của framework không tập trung tại bản 20.0 mà được đưa vào dần qua các bản Odoo Online 19.1 đến 19.4. Vì vậy, một lần nâng cấp trực tiếp từ Odoo community 19.0 lên 20.0 tiếp nhận toàn bộ các thay đổi đó cùng lúc. Addon chưa được điều chỉnh phù hợp sẽ không khởi động được trên phiên bản mới.

Tổng quan: bảng xếp hạng mức độ rủi ro

Bảng dưới đây gom mức độ rủi ro, phạm vi ảnh hưởng và định danh cần xử lý cho từng nhóm thay đổi.

#Nhóm thay đổiPhạm vi ảnh hưởng và cách xử lý
1Nền tảng: Python 3.12, PostgreSQL 16, máy chủ HTTP h11Cài đặt Odoo trực tiếp trên host phải nâng cấp phiên bản Python và PostgreSQL, với Docker Compose chỉ cần chọn đúng image.
2Bảo mật:
Gộp ir.model.access và ir.rule thành ir.access
Mọi addon có tệp phân quyền phải cập nhật. Nếu không sẽ báo lỗi.
3External API: dịch vụ db bị loại bỏ, API key bắt buộc phạm vi rpcHệ thống tích hợp, trình kết nối chuyển sang JSON-2 /json/2/<model>/<method>; cấp lại key với scope='rpc', thu hồi key cũ.
4Trường binary thành BinaryValueỨng dụng khách đọc tệp qua RPC. Đọc dict {"content","filename","size"} thay vì base64, datas thành raw.
5Đổi tên và loại bỏ model, fieldTự kiểm tra khi báo lỗi và sửa cho phù hợp.
Ví dụ: product_uom* thành uom_id, hr.leave.type thành hr.work.entry.type.
6ORM framework: odoo.osv, tham số định kiểu, bộ nhớ đệm, requestMã nguồn Python phía máy chủ. odoo.osv thành odoo.fields.Domain; get_param thành get_str/get_int/get_bool; Registry.clear_cache() thành transaction.invalidate_ormcache(); request thành env.website.
7Web client: Owl 3, Material Symbols, QWeb t-outThành phần JavaScript, bố cục view, báo cáo PDF. static props thành useProps, thêm this., useState thành proxy; t-esc/t-raw thành t-out; fa fa-* thành Material Symbols.
8Module gộp hoặc loại bỏ, manifest 20.0.x.y.zKiểm tra dependencies trong __manifest__.py trỏ tới module còn tồn tại trong Odoo 20 không. Cập nhật version thành 20.0.x.y.z; base_vat, base_iban vào base, stock_picking_batch vào stock, industry_fsm* thành planning_field_service.
9Các điều chỉnh nhỏTiện ích bổ sung như populate, compute_sql, tên record khi duplicate, …

1. Nền tảng: Python 3.12 và PostgreSQL 16

Trong odoo/release.py của nhánh 20.0 đặc tả rõ:

MIN_PY_VERSION = (3, 12)   # Odoo 19: (3, 10)
MIN_PG_VERSION = 16        # Odoo 19: 13
Yêu cầuOdoo 19Odoo 20
Python (MIN_PY_VERSION)3.103.12
PostgreSQL (MIN_PG_VERSION)1316
Máy chủ HTTPwerkzeugh11
  • Phạm vi ảnh hưởng: yêu cầu này tác động trực tiếp đến các triển khai cài đặt Odoo trên host.
  • Với Docker Compose: đây không phải trở ngại lớn khi image Odoo 20 đã đóng gói Python 3.12 và image PostgreSQL 16 đáp ứng mức tối thiểu.

Các lệnh kiểm tra:

python3 --version     # yêu cầu >= 3.12
psql --version        # yêu cầu >= 16

2. ir.access thay cho ir.model.access và ir.rule

Odoo 20 loại bỏ model của access right (ir.model.access) và access rule (ir.rule), thay vào đó gộp thành một model duy nhất ir.access. Giờ đây mỗi addon chỉ còn một tệp security/ir.access.csv với các cột id, name, model_id, group_id/id, operation, domain.

  • group_id rỗng là restriction áp cho mọi người dùng;
  • operation là tập con của crud (r, ru, crud) và không có giá trị mặc định;
  • Quyền được gộp theo biểu thức OR(permissions) & AND(restrictions).

Ví dụ chuyển đổi đơn giản ở Odoo 19, quyền đọc riêng đơn hàng của nhân viên kinh doanh cần một dòng ACL và một record rule như sau:

security/ir.model.access.csv

# Odoo 19:
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_my_order_user,my.order user,model_my_order,sales_team.group_sale_salesman,1,0,0,0

security/my.xml

<!-- Odoo 19 -->
<record id="rule_my_order_own" model="ir.rule">
    <field name="name">my.order own</field>
    <field name="model_id" ref="model_my_order"/>
    <field name="domain_force">[('user_id', '=', user.id)]</field>
    <field name="groups" eval="[(4, ref('sales_team.group_sale_salesman'))]"/>
</record>

Ở Odoo 20, cả hai gộp thành một dòng gọn hơn nhiều:

security/ir.access.csv

# Odoo 20
id,name,model_id,group_id/id,operation,domain
access_my_order_own,my.order own,my.order,sales_team.group_sale_salesman,r,"[('user_id', '=', user.id)]"

Lưu ý: nếu chuyển đổi không đúng logic sẽ gây sai quyền người dùng (right) và dữ liệu người dùng được nhìn thấy (rule).

3. External API: dịch vụ db bị loại bỏ, API key bắt buộc phạm vi rpc

  • XML-RPC và JSON-RPC tại /xmlrpc, /xmlrpc/2, /jsonrpc được đánh dấu là DEPRECATED
  • Dịch vụ db bị loại bỏ trong Odoo 20, common và object dự kiến loại bỏ ở Odoo 22 (năm 2028).

Cách nâng cấp:

  • Chuyển tích hợp sang chuẩn mới JSON-2 API có từ 19.0
  • Cấp lại key cho từng tài khoản tích hợp với phạm vi scope='rpc' trên môi trường thử nghiệm, kiểm thử rồi thu hồi key cũ tại thời điểm chuyển đổi

Ví dụ một mẫu truy vấn:

POST /json/2/res.partner/search_read HTTP/1.1
Host: mycompany.example.com
Authorization: bearer <rpc-api-key>
Content-Type: application/json; charset=utf-8

{"domain": [["is_company", "=", true]], "fields": ["name"]}

4. Trường binary thành BinaryValue và định dạng RPC mới

Phương thức fields.Binary.convert_to_read() trả về dict với các key {"content", "filename", "size"} thay vì chuỗi base64, áp dụng cho read, search_read và web_read. Client gọi base64.b64decode(record["image_1920"]) (lệnh này rất hay dùng) sẽ gây lỗi TypeError

Chiều ghi giá trị (write) vào field vẫn nhận base64 lẫn dict. ir.attachment.datas bị loại bỏ, thay bằng raw.

Ta có thể dùng hàm sau để tương thích cả 2 phiên bản Odoo 19 và Odoo 20:

import base64

def binary_bytes(value):
    if not value:                    # trường binary rỗng đọc là False
        return None
    if isinstance(value, dict):      # 20.0: {"content", "filename"?, "size"}
        value = value["content"]
    return base64.b64decode(value)

5. Đổi tên và loại bỏ model, field

Odoo 19Odoo 20
ir.model.access, ir.ruleir.access
get_param / set_paramget_str, get_int, get_bool, get_float và set_*
ir.attachment.datasraw
product_uom* trên stock, purchase, mrpuom_id
stock.scrapstock.move với is_scrap, scrap_reason_tag_ids
hr.leave.type, hr.contract.typehr.work.entry.type, hr.employee.type
account.group, res.bank, mrp.bom.consumptionloại bỏ
……

Cách nâng cấp lên Odoo 20: Rà soát, cập nhật các model và wizard bị gộp hoặc loại bỏ.

Một vài method đổi tên:

check_access_rights(...)  ->  check_access(...)
toggle_active()           ->  action_archive()
_check_recursion()        ->  _has_cycle()

6. ORM

Các điểm đánh dấu lỗi thời từ Odoo 19 nay chính thức bị loại bỏ:

  • odoo.osv thành odoo.fields.Domain
  • Model._table_query bị gỡ
  • Registry.clear_cache() thành transaction.invalidate_ormcache()
  • request trong model code thành env.website
  • Từ 19.4, create() và write() sắp xếp field theo (field.write_sequence, field_index), nên hook phụ thuộc thứ tự có thể đổi hành vi.

Ví dụ:

# Odoo 19:
env['ir.config_parameter'].get_param('my.key')

# Odoo 20:
env['ir.config_parameter'].get_str('my.key')   # get_str / get_int / get_bool / get_float
env['ir.config_parameter'].set_str('my.key', value)

Khai báo ràng buộc bằng models.Constraint, UniqueIndex, Index thay _sql_constraints (đã đề cập ở Tut 21).


7. Frontend

OWL chuyển phiên bản từ 2.8.4 lên 3.0.0-alpha.49, Font Awesome bị thay bằng Material Symbols.

  • static props thành useProps()
  • useState thành proxy, thêm this. trong template
  • t-esc và t-raw thành t-out
  • t-set trong thân t-call chuyển thành thuộc tính của t-call
  • Biểu tượng fa fa-* đổi sang oi / data-icon
  • Bỏ start_month, end_month, start_year, end_year trên filter kiểu date.

Ví dụ:

<!-- Odoo 20: tham số truyền qua thuộc tính t-call, xuất nội dung bằng t-out -->
<t t-call="my.template" title="'Hello'"/>
<t t-out="this.state.value"/>

8. Module bị gộp, loại bỏ và khai báo phiên bản trong manifest

Khoảng 50 module bị loại bỏ và 50 module mới, phần lớn module mất được gộp:

  • base_vat và base_iban vào base
  • stock_picking_batch vào stock
  • industry_fsm* thành planning_field_service
  • wkhtmltopdf tách sang base_report_wkhtmltox, base_report_paper_muncher là tùy chọn.

Đổi version trong __manifest__.py từ 19.0.x.y.z thành 20.0.x.y.z.

9. Các điều chỉnh nhỏ

Các tiện ích mới, không yêu cầu sửa addon như:

  • populate sinh dữ liệu giả
  • Hàm sao chép mặc định thêm "(copy)" cho char field name
  • Field.compute_sql cho phép nhóm và sắp xếp computed field bằng SQL, SQL builder API
  • Model.concat và Model.union gọn hơn, ghi nhiều bản dịch trong một lần write
  • …

Thứ tự nâng cấp khuyến nghị (checklist)

  1. Đảm bảo môi trường triển khai đáp ứng yêu cầu Python 3.12, PostgreSQL 16. Có thể dùng minhng92/odoo-20-docker-compose để triển khai Odoo 20.
  2. Viết lại security/ir.access.csv, kiểm thử quyền truy cập sau khi chuyển đổi.
  3. Cấp lại API key scope='rpc', kiểm thử tích hợp trên môi trường thử nghiệm.
  4. Cập nhật những đoạn code liên quan đến trường Binary.
  5. Nâng cấp code frontend qua Owl 3, các directive trong Qweb và dùng biểu tượng Material Symbols.
  6. Manifest > khai báo phiên bản 20.0.x.y.z, cập nhật depends đến các module tồn tại trong Odoo 20.
  7. Cập nhật model, field và method đổi tên.
  8. Kiểm thử sau khi nâng cấp: phân quyền không dùng admin, tích hợp, báo cáo PDF, portal, có và không có dữ liệu demo.

Quy mô thay đổi Odoo 19 → 20

  • Odoo 20 thêm hoặc loại bỏ 186 model (thêm 123 mới, xóa bớt 63)
  • Thay đổi 194 ràng buộc, khoảng 50 module mất và 50 module mới, với 12 thay đổi gây lỗi không tương thích cho custom code và tích hợp.
  • Odoo 18 lên 19 có 129 model và 207 ràng buộc thay đổi.

Các số liệu này cho phép ước lượng khối lượng công việc trước khi bắt đầu nâng cấp từ Odoo 19 lên Odoo 20.

Tham khảo


Hãy tham gia group Facebook để trao đổi và học hỏi thêm về Odoo nhé các bạn => Khám phá Odoo: https://facebook.com/groups/odoo-dev

Tham gia wait-list Khóa học Lập trình Odoo 19: https://forms.gle/niDFrZxcoAcLU8qz6


Cài đặt Odoo:

Danh sách bài viết series Odoo:

Hãy tham gia group  Khám phá Odoo để cùng trao đổi và học hỏi.
Khám phá Odoo