odooでのコードを主としたマスタモデルの実装（未検証:2025/04/17）

# マスタテーブルの設計

システムを設計する際、コードと名称、その他の属性を含むマスタテーブルを作成することがよくあると思います。
odooのモデル設計において、あまり、コードを前面に出しておらず、名称（`name`）を主としています。

ここでは、コードを主として扱えるマスタテーブルをodooでどのように実装するかを提案します。

# odooでの実装例

odooでもコードと名称とでマスタ管理しているものがあります。例えば、商品マスタ(`product.template`,`product.product`)がそれです。

商品マスタの場合、`product.product`モデルに`default_code`フィールドが存在し、この`default_code`フィールドの値を一覧表示で検索することができます。

# マスタモデルの実装

次のテーブル設計を元にマスタモデルを実装します。
部署マスタと部員マスタがあり、部員は複数の部署に所属します。

```plantuml
@startuml
entity "部署マスタ [custom.department]" as department {
  - id : Integer <<PK>>
  code : String <<UNIQUE>>
  name : String
  description : String
}

entity "部員マスタ [custom.member]" as member {
  - id : Integer <<PK>>
  code : String <<UNIQUE>>
  name : String
  email : String
}

entity "部署-部員マスタ" as department_member {
  - department_id : Integer <<PK>>
  - member_id : Integer <<PK>>
}

department ||--o{ department_member : "配属する"
member ||--o{ department_member : "所属する"

department .r.> member : 配属→
department <.r. member : ←所属
@enduml

```

## モデル定義

```py: 部署マスタ
from odoo import models, fields

class Department(models.Model):
    _name = 'custom.department'
    _description = 'Department'

    name = fields.Char(string='Department Name', required=True)
    code = fields.Char(string='Department Code', required=True, unique=True)
    description = fields.Text(string='Description')
    member_ids = fields.Many2many(
        'custom.member',
        'department_member_rel',
        'department_id',
        'member_id',
        string='Members'
    )
    
```

```py: 部員マスタ
class Member(models.Model):
    _name = 'custom.member'
    _description = 'Member'

    name = fields.Char(string='Member Name', required=True)
    code = fields.Char(string='Member Code', required=True, unique=True)
    email = fields.Char(string='Email')
    department_ids = fields.Many2many(
        'custom.department',
        'department_member_rel',
        'member_id',
        'department_id',
        string='Departments'
    )
```

## フォームビュー定義

```xml: 部署フォームビュー
<record id="view_department_form" model="ir.ui.view">
    <field name="name">custom.department.form</field>
    <field name="model">custom.department</field>
    <field name="arch" type="xml">
        <form string="Department">
            <sheet>
                <group>
                    <field name="name"/>
                    <field name="code"/>
                    <field name="description"/>
                </group>
                <notebook>
                    <page string="Members">
                        <field name="member_ids">
                            <tree string="Members">
                                <field name="name"/>
                                <field name="employee_code"/>
                            </tree>
                            <form string="Member">
                                <field name="name"/>
                                <field name="employee_code"/>
                                <field name="email"/>
                            </form>
                        </field>
                    </page>
                </notebook>
            </sheet>
        </form>
    </field>
</record>
```

```xml:部員フォームビュー
<record id="view_member_form" model="ir.ui.view">
    <field name="name">custom.member.form</field>
    <field name="model">custom.member</field>
    <field name="arch" type="xml">
        <form string="Member">
            <sheet>
                <group>
                    <field name="name"/>
                    <field name="employee_code"/>
                    <field name="email"/>
                </group>
                <notebook>
                    <page string="Departments">
                        <field name="department_ids">
                            <tree string="Departments">
                                <field name="name"/>
                                <field name="code"/>
                            </tree>
                            <form string="Department">
                                <field name="name"/>
                                <field name="code"/>
                                <field name="description"/>
                            </form>
                        </field>
                    </page>
                </notebook>
            </sheet>
        </form>
    </field>
</record>
```

## 一覧ビュー定義

```xml: 部署一覧ビュー
<record id="view_department_tree" model="ir.ui.view">
    <field name="name">custom.department.tree</field>
    <field name="model">custom.department</field>
    <field name="arch" type="xml">
        <tree string="Department List">
            <field name="name"/>
            <field name="code"/>
            <field name="description"/>
        </tree>
    </field>
</record>
```

```xml: 部員一覧ビュー
<record id="view_member_tree" model="ir.ui.view">
    <field name="name">custom.member.tree</field>
    <field name="model">custom.member</field>
    <field name="arch" type="xml">
        <tree string="Member List">
            <field name="name"/>
            <field name="code"/>
            <field name="email"/>
        </tree>
    </field>
</record>
```

## メニュー定義

```xml: メニュー
<menuitem id="menu_department" name="Departments"
    parent="menu_root"
    action="action_department"/>
<menuitem id="menu_member" name="Members"
    parent="menu_root"
    action="action_member"/>

<record id="action_department" model="ir.actions.act_window">
    <field name="name">Departments</field>
    <field name="res_model">custom.department</field>
    <field name="view_mode">tree,form</field>
</record>

<record id="action_member" model="ir.actions.act_window">
    <field name="name">Members</field>
    <field name="res_model">custom.member</field>
    <field name="view_mode">tree,form</field>
</record>
```

## データのインポート

```text : 部署マスタ
code,name,description
A001,部署A,
B001,部署B,
B002,部署B2,
C001,部署C,
```

```text: 部員マスタ
code,name,email,department_ids/code
M001,鈴木,ichi@example.com,A001
M002,安藤,num2@example.com,B001
M003,多田,many@example.com,C001
,,,B001
,,,B002


## 名称表示の実装

TODO:

## 名称検索の実装