สารบัญ
Odoo Automated Action: ทำไม import ไม่ได้ และแก้ IMPORT_NAME อย่างไร
คำตอบสั้น: ถ้าเจอ ValueError: forbidden opcode(s) in "...": IMPORT_NAME แปลว่าโค้ดมีคำสั่ง import ซึ่ง safe_eval ของ Odoo ห้ามไว้ วิธีแก้คือลบบรรทัด import ทิ้งแล้วใช้สิ่งที่ Odoo เตรียมไว้ให้อยู่แล้ว เช่น env, datetime, dateutil, time, user
สภาพแวดล้อม
- Odoo 17 / 18 / 19
- Settings > Technical > Automation > Automated Actions > Execute Python Code
ตัวอย่างที่พัง
import datetime
for record in records:
record.write({'x_reminder_date': datetime.date.today()})
error ที่ได้:
ValueError: forbidden opcode(s) in "<string>": IMPORT_NAME
ทำไม Odoo ห้าม import
safe_eval อนุญาตเฉพาะชื่อ (names) ที่ Odoo ใส่ไว้ใน execution context เท่านั้น คำสั่ง import จะดึง module ภายนอกเข้ามาซึ่ง Odoo ควบคุมไม่ได้ จึงถูกตัดออกตั้งแต่ระดับ opcode พร้อมกับ STORE_ATTR และ opcode เสี่ยงอื่น ๆ
ข่าวดีคือของที่ใช้บ่อย Odoo เตรียมไว้ให้หมดแล้ว ไม่ต้อง import เอง
รายชื่อที่ใช้ได้โดยไม่ต้อง import
| ชื่อ | ใช้ทำอะไร | ตัวอย่าง |
|---|---|---|
env | เรียก model อื่น | env['res.partner'].search([]) |
records / record | record ที่ trigger | for record in records: |
user | ผู้ใช้ปัจจุบัน | user.id, user.company_id |
datetime | วันที่เวลา | datetime.date.today() |
dateutil | คำนวณวันที่สัมพัทธ์ | dateutil.relativedelta.relativedelta(days=7) |
time | เวลา | time.strftime('%Y-%m-%d') |
float_compare ฯลฯ | helper ของ Odoo | ขึ้นกับเวอร์ชัน ให้ลองใน UI |
วิธีแก้: เขียนใหม่โดยไม่ใช้ import
โค้ดตัวอย่างข้างบนแก้เป็นแบบนี้ (ลบบรรทัด import ทิ้งเฉย ๆ ที่เหลือเหมือนเดิม):
for record in records:
record.write({'x_reminder_date': datetime.date.today()})
ตัวอย่างคำนวณวันครบกำหนด 7 วันข้างหน้า:
for record in records:
deadline = datetime.date.today() + dateutil.relativedelta.relativedelta(days=7)
record.write({'x_deadline': deadline})
ตัวอย่างค้นหา partner แล้วผูกกับ record:
for record in records:
partner = env['res.partner'].search([('email', '=', record.x_contact_email)], limit=1)
if partner:
record.write({'partner_id': partner.id})
ข้อผิดพลาดที่พบบ่อย
from datetime import date— ก็เป็นIMPORT_NAMEเหมือนกัน ห้ามทุกท่าที่มีคำว่า importimport jsonเพื่อแปลงข้อมูล — ใช้วิธีอื่นแทน เช่น ส่ง string ผ่านฟิลด์Char/Textตรง ๆ หรือเก็บเป็นreprถ้าจำเป็นจริง ๆ ให้ย้าย logic ไปเขียนเป็น server action แบบ module (custom addon) แทน- ใช้ library ภายนอกเช่น
requests— ทำไม่ได้ใน Automated Action ถ้าต้องยิง API ภายนอก ให้ใช้ webhook action ที่ Odoo มีให้ หรือเขียน custom module - สับสนกับ
STORE_ATTR— ถ้าแก้ import แล้วเจอSTORE_ATTRต่อ แปลว่าโค้ดยัง assign ฟิลด์ตรง ๆ ให้เปลี่ยนเป็นrecord.write()อ่านวิธีแก้ที่ แก้ forbidden opcode STORE_ATTR ด้วย record.write()
เมื่อไรควรเลิกใช้ Automated Action แล้วเขียน module แทน
- ต้องใช้ library ภายนอก (
requests,pandas, อื่น ๆ) - logic ซับซ้อนเกิน 30–40 บรรทัด อ่านยาก ดูแลยาก
- ต้องมี unit test หรือ version control จริงจัง
Automated Action เหมาะกับงาน if-then-write สั้น ๆ ถ้าเกินนี้ custom addon จะถูกกว่าในระยะยาว
อ้างอิง
- Odoo 19 Automated Actions เอกสารภาษาไทย: https://www.odoo.com/documentation/19.0/th/applications/studio/automated_actions.html
บทความที่เกี่ยวข้อง
- Odoo Automated Action: แก้ forbidden opcode STORE_ATTR ด้วย record.write()
- Odoo QWeb: วิธีแก้ PDF ตัดหน้า Page Break พร้อมตัวอย่างจริง
- โน้ต Odoo ทั้งหมด
ผู้เขียน: ณภัทร ภมรสูตร — เกี่ยวกับผู้เขียน · ผลงาน · โน้ตทั้งหมด