📊 รายงานการวิเคราะห์: เพิ่มฟิลด์ Project Name ใน Invoice Analysis

ระบบ Odoo 16 | วิเคราะห์สาเหตุ กลไก Custom Group วิธีการแก้ปัญหา และผลกระทบต่อระบบ
Report: Invoices Analysis Target: account.move.project_name Impact: Zero Core Impact / Safe Scope: Analysis Only (No Code Touched)
💡

บทสรุปสำหรับผู้บริหารและผู้ใช้งาน (Executive Summary)

ต้นตอของปัญหา: หน้าจอ Invoice Analysis ดึงข้อมูลจากฐานข้อมูลเสมือนประเภท SQL View ที่ชื่อว่า account.invoice.report ซึ่งเป็นคนละโมเดลกับ account.move (หน้าใบแจ้งหนี้ปกติ) ดังนั้นแม้จะมีฟิลด์ project_name อยู่ในใบแจ้งหนี้แล้ว แต่ถ้าไม่ได้เพิ่มเข้าไปในโมเดลรายงาน Odoo จะไม่แสดงฟิลด์นี้ในเมนู Add Custom Group

การประเมินความเสี่ยงและผลกระทบ: ความปลอดภัยสูงมาก (Safe) การแก้ไขทำที่ระดับ Read-Only Report View เท่านั้น ไม่แตะต้องกระบวนการบันทึกบัญชี ไม่กระทบต่อการทำงานปกติของ Invoice เดิม และไม่กระทบงบการเงินใดๆ ทั้งสิ้น

STEP 1

หลักฐานปัญหาและจุดที่ต้องการปรับปรุง (Visual Evidence)

จากภาพหน้าจอจริงที่บันทึกมาจากระบบ:

Odoo Invoice Analysis Custom Group Screenshot
ภาพแสดง: เมนู Accounting > Reporting > Invoice Analysis และรายการฟิลด์ในดรอปดาวน์ Add Custom Group ที่ยังไม่มี Project Name
ตำแหน่ง สภาพปัจจุบัน (As-Is) เป้าหมายที่ต้องการ (To-Be)
Menu Path Accounting > Reporting > Management > Invoice Analysis ตำแหน่งเดิมในการเข้าถึงรายงาน
Pivot View Grouping กด Add Custom Group มีเฉพาะฟิลด์มาตรฐาน เช่น Company, Currency, Country, Due Date, Move, Move Type... เพิ่มตัวเลือก Project Name (และ/หรือ Project) ให้สามารถเลือกจัดกลุ่มยอดขายตามโครงการได้ทันที
Data Source Model account.move มีฟิลด์ project_name แล้ว แต่ account.invoice.report ยังไม่มี เชื่อมโยงดึง move.project_name เข้าสู่ account.invoice.report อย่างสมบูรณ์
STEP 2

วิเคราะห์สาเหตุเชิงลึก: ทำไมถึงไม่ขึ้นใน Add Custom Group? (Root Cause)

ใน Odoo กลไกการแสดงฟิลด์ในปุ่ม "Add Custom Group" ของหน้า Pivot / Graph / Search View มีหลักการทำงานดังนี้:

1. ความแตกต่างของโมเดล (Model Decoupling)

หน้าสร้าง Invoice ทำงานบนโมเดล account.move ซึ่งโมดูล yell_account_ext ได้ประกาศฟิลด์ project_name ไว้เรียบร้อยแล้ว แต่หน้าจอ Invoice Analysis ทำงานบนโมเดลวิเคราะห์ข้อมูลเฉพาะคือ account.invoice.report

2. ธรรมชาติของ SQL View (_auto = False)

โมเดล account.invoice.report เป็นตาราง View เสมือนใน PostgreSQL สร้างจากคำสั่ง SQL SELECT ... FROM ... ไม่ใช่ตารางจริง หากไม่มีการเขียนคำสั่ง SQL ดึงคอลัมน์ project_name มารองรับ Odoo จะมองไม่เห็นฟิลด์นี้

3. การกรองของ Odoo Web Client

เมื่อผู้ใช้คลิก "Add Custom Group" ฝั่ง Web Client จะยิงคำสั่ง fields_get() ไปยังเซิร์ฟเวอร์เพื่อขอรายชื่อฟิลด์ทั้งหมดของโมเดลรายงาน เมื่อในโมเดลไม่มีฟิลด์นี้ จึงไม่ถูกนำมาแสดงในดรอปดาวน์

ℹ️

สรุปสั้นๆ เข้าใจง่าย

ฟิลด์ project_name มีอยู่ใน "ใบแจ้งหนี้" (account.move) แต่ยังไม่ได้ถูกเพิ่มเข้าไปใน "กระดานรายงานวิเคราะห์" (account.invoice.report) จึงทำให้ระบบไม่สามารถนำมาใช้จัดกลุ่ม (Group By) ได้

STEP 3

ขั้นตอนและแนวทางแก้ไขอย่างละเอียด (Detailed Technical Solution)

การแก้ไขทำได้ง่ายและตรงไปตรงมา โดยการสืบทอดโมเดล (Inherit) account.invoice.report ในโมดูลเดิมที่มีอยู่แล้ว เช่น yell_account_ext โดยมี 4 ขั้นตอนหลักดังนี้:

1. ประกาศฟิลด์ใน Python Model (Python Extension)

สร้างไฟล์ Python เช่น models/account_invoice_report.py เพื่อเพิ่มฟิลด์ลงในโมเดลรายงาน พร้อมกำหนด readonly=True:

python: models/account_invoice_report.py
from odoo import fields, models

class AccountInvoiceReport(models.Model):
    _inherit = 'account.invoice.report'

    # 1. เพิ่มฟิลด์ project_name (ข้อความ) ตามที่ผู้ใช้ต้องการ
    project_name = fields.Char(
        string='Project Name',
        readonly=True,
    )

    # 2. แนะนำเพิ่มเติม: ฟิลด์ project_id (Relational Many2one) เพื่อการจัดกลุ่มที่แม่นยำ
    project_id = fields.Many2one(
        comodel_name='project.project',
        string='Project',
        readonly=True,
    )

    def _select(self):
        # ดึงข้อมูล project_name และ project_id จากตาราง account_move (alias: move)
        select_str = super()._select()
        select_str += ", move.project_name AS project_name, move.project_id AS project_id"
        return select_str

2. เพิ่มทางลัดใน Search View Group By (XML Extension - แนะนำเพื่อ UX ที่ยอดเยี่ยม)

แม้ว่าการเพิ่มฟิลด์ใน Python จะทำให้ฟิลด์โผล่ใน "Add Custom Group" อัตโนมัติแล้ว แต่เพื่อความสะดวกสูงสุดของผู้ใช้งาน ไม่ต้องเสียเวลากดเลือกดรอปดาวน์ทุกครั้ง ควรเพิ่มปุ่มลัดในแท็บ Group By โดยตรง:

xml: views/account_invoice_report_views.xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <record id="view_account_invoice_report_search_inherit_project" model="ir.ui.view">
        <field name="name">account.invoice.report.search.inherit.project</field>
        <field name="model">account.invoice.report</field>
        <field name="inherit_id" ref="account.view_account_invoice_report_search"/>
        <field name="arch" type="xml">
            <xpath expr="//group" position="inside">
                <filter string="Project Name" name="group_by_project_name" context="{'group_by': 'project_name'}"/>
                <filter string="Project" name="group_by_project" context="{'group_by': 'project_id'}"/>
            </xpath>
        </field>
    </record>
</odoo>

3. อัปเดตไฟล์ __init__.py และ __manifest__.py

4. Upgrade โมดูลในระบบ Odoo

เนื่องจากเป็นตาราง SQL View ใน Database จะต้องสั่ง Upgrade โมดูลเพื่อให้ Odoo รันคำสั่ง CREATE OR REPLACE VIEW account_invoice_report ใหม่:

Terminal / Deployment Command
odoo-bin -c /etc/odoo/odoo.conf -u yell_account_ext -d yell-main --stop-after-init
STEP 4

วิเคราะห์ผลกระทบต่อการทำงานส่วนอื่นๆ อย่างละเอียด (Detailed Impact Analysis)

ตามที่ผู้ใช้ร้องขอให้ประเมินผลกระทบต่อส่วนต่างๆ ของระบบอย่างละเอียด ทีมงานได้วิเคราะห์ผลกระทบใน 5 มิติดังนี้:

1. การทำงานหลักของระบบบัญชี (Core Accounting) ZERO IMPACT

ไม่มีผลกระทบใดๆ ทั้งสิ้น: โมเดล account.invoice.report ทำหน้าที่เป็นเพียงกระดานอ่านข้อมูล (Read-Only) สำหรับกราฟและตาราง ไม่ได้มีส่วนเกี่ยวข้องกับการ Post ใบแจ้งหนี้, การกระทบยอด (Reconciliation), การรับชำระเงิน หรือการลงสมุดบัญชีรายวัน

2. ประสิทธิภาพและความเร็วฐานข้อมูล (Database Performance) VERY LOW / SAFE

ปลอดภัยสูงมาก: ตาราง account_move มีการเชื่อม (JOIN) อยู่ใน SQL View ของ account.invoice.report อยู่แล้วแต่เดิม การเพิ่มเพียง move.project_name เข้าไปใน SELECT จึงเป็นการอ่านคอลัมน์ที่มีอยู่แล้ว ไม่มีการสร้าง Join ข้ามตารางใหม่ จึงไม่มีผลต่อความเร็วของระบบ

3. รายงานเดิมและ Favorites ที่เคยบันทึกไว้ ZERO IMPACT

ไม่กระทบรายงานเดิม: การเพิ่มฟิลด์ใหม่ไม่กระทบกับตัวกรอง (Filters), Favorites หรือ Custom Dashboards ที่ผู้ใช้งานคนอื่นสร้างไว้เดิม เนื่องจากไม่มีการเปลี่ยนชื่อหรือลบฟิลด์เดิมออก

4. ข้อมูลย้อนหลังในอดีต (Historical Data) HANDLED / NOTICE

ผลของการจัดกลุ่ม: สำหรับใบแจ้งหนี้ในอดีตที่ไม่ได้เลือก Project เอาไว้ (project_id = False) ค่าของ project_name จะเป็นค่าว่าง (NULL) ซึ่งเมื่อกด Group By ใน Pivot View ระบบจะจัดเรคคอร์ดเหล่านี้ไปอยู่ในกลุ่ม "Undefined" ซึ่งเป็นพฤติกรรมมาตรฐานที่ถูกต้องของ Odoo

5. ความเสี่ยงในขั้นตอน Deploy / Upgrade ATTENTION NEEDED

ข้อควรระวังของ Dev: ในการเขียน SQL ของ _select() ต้องมั่นใจว่าใส่เครื่องหมายจุลภาค (Comma ,) คั่นถูกต้อง หากไวยากรณ์ SQL ผิดพลาด ฐานข้อมูลจะไม่สามารถสร้าง View ได้ และจะส่งผลให้หน้าจอ Invoice Analysis เกิด Error จนกว่าจะแก้ไวยากรณ์และ Upgrade อีกครั้ง

STEP 5

เกณฑ์การตรวจสอบและทดสอบระบบ (QA Acceptance Checklist)

เมื่อนำแนวทางนี้ไปมอบหมายให้ทีม Developer พัฒนาเสร็จสิ้น สามารถใช้ Checklist 6 ข้อนี้ในการตรวจรับงานได้ทันที: