Bỏ qua để đến Nội dung
Soul of NOTE
  • Khóa học
  • Check-in
    • NOTE
    • Headspace Vietnam
    • Fosllea
  • Diễn đàn
  • Company
    • Blog
    • Success Stories
  • 0
  • 0
  • Đăng nhập
Soul of NOTE
  • 0
  • 0
    • Khóa học
    • Check-in
      • NOTE
      • Headspace Vietnam
      • Fosllea
    • Diễn đàn
    • Company
      • Blog
      • Success Stories
  • Đăng nhập

[T09] T09 — Odoo 19 Payslip worked_days gộp OT — salary rules OT không chạy

  • Tất cả blog
  • Knowledge Base
  • [T09] T09 — Odoo 19 Payslip worked_days gộp OT — salary rules OT không chạy
  • 15 tháng 3, 2026 bởi
    [T09] T09 — Odoo 19 Payslip worked_days gộp OT — salary rules OT không chạy
    Viet Nguyen
    ⚠️ HIGH  |  Category: Odoo Tips  |  ID: T09  |  Owner: CEO

    T09 — Odoo 19 Payslip worked_days gộp OT — salary rules OT không chạy

    Tóm tắt

    Odoo 19 gộp TẤT CẢ OT work entries vào worked_days['OVERTIME'] — KHÔNG tách riêng OT150/OT200/OT300. Salary rule condition worked_days['OT150'] LUÔN FALSE → rules không execute → OT không tính.

    Chi tiết

  • Hành vi: Khi payslip generate, Odoo gom tất cả work entry types có is_overtime=True thành 1 dòng worked_days duy nhất với code OVERTIME
  • Kỳ vọng: Mỗi OT type (OT150, OT200, OT300) có dòng riêng trong worked_days
  • Thực tế: worked_days.OT150 → False | worked_days.OVERTIME → True (chứa tổng hợp)
  • Impact: 13 salary rules cần update:
  • - 9 rules tính OT (150%, 200%, 300% × ngày thường/CN/lễ) - 4 rules TNCN OT exemption

    Solution

    Query hr.work.entry trực tiếp thay vì dùng worked_days:

    WRONG — luôn False

    result = worked_days['OT150'] and worked_days['OT150'].number_of_hours or 0

    CORRECT — query work entries trực tiếp

    entries = payslip.env['hr.work.entry'].search([ ('employee_id', '=', employee.id), ('work_entry_type_id.code', '=', 'OT150'), ('date', '>=', payslip.date_from), ('date', '<=', payslip.date_to), ('state', '=', 'validated'), ]) result = sum(entries.mapped('duration'))

    Pattern này giống cách tính ALW_LUNCH_PT (query attendance trực tiếp).

    Ảnh hưởng

  • Ai bị ảnh hưởng: Mọi NV có OT (13/28 NV)
  • Mức độ: high — OT không tính = thiếu lương
  • Tần suất gặp: mỗi payroll cycle nếu dùng worked_days cho OT
  • Cách xử lý / Phòng tránh

    1. KHÔNG dùng worked_days['OT_CODE'] cho OT types — luôn False 2. Query hr.work.entry trực tiếp với filter work_entry_type_id.code 3. Dùng payslip.env để access ORM từ salary rule Python code 4. Test bằng cách print worked_days dict trong salary rule → verify keys

    Bằng chứng / Tham khảo

  • Commit aef5ffa — fix OT salary rules
  • HR/scripts/fix_ot_salary_rules.py — script apply fix
  • Odoo 19 source: hr_payroll/models/hr_payslip.py → _get_worked_day_lines()
  • Liên quan

  • [T05](T05-default-rules-duplicate.md) — duplicate rules cũng gây sai OT
  • [T06](T06-payrun-silent-skip.md) — Pay Run skip NV nếu thiếu work entries
  • [T07](T07-salary-rule-sequence.md) — OT rules phải có sequence đúng

  • 📚 Published from Company Knowledge Base — T09
    Last updated: 2026-03-12
    Review by: 2026-06-10

    trong Knowledge Base
    # Odoo Tips
    [T08] T08: Odoo 19 Multi-company Models — Không có company_id



    Bản quyền thuộc CÔNG TY TNHH NOTE
    Cung cấp bởi Odoo - Một nền tảng thương mại điện tử mã nguồn mở hàng đầu