odooの商品モデル（productモジュール）

# productモジュールにおけるデータベースモデル

odooでは、productモジュールで商品モデルを管理しています。
商品モデルは、主に、テンプレートマスタと商品マスタとで構成されています。
価格表マスタと仕入先価格表マスタで、有効期限を設けた価格設定が可能です。

商品マスタの`default_code`で自社の商品番号を管理します。
※ `default_code`, `Internal Reference`, `SKU`, `code`と呼ばれています。
仕入先の商品番号は、仕入価格表のproduct_codeで管理します。

```plantuml

@startuml
' Define entities for the product module

entity product_template {
    * id : integer
    --
    name : string
    type : string
    standard_price : float
    categ_id : integer
}

entity product_product {
    * id : integer
    --
    default_code : string
    barcode : string
    standard_price : float
    product_tmpl_id : integer
}

entity product_pricelist {
    * id : integer
    --
    name : string
    currency_id : integer
}

entity product_pricelist_item {
    * id : integer
    --
    pricelist_id : integer
    product_tmpl_id : integer
    product_id : integer
    fixed_price : float
    date_start : date
    date_end : date
}

entity product_supplierinfo {
    * id : integer
    --
    partner_id : integer
    product_tmpl_id : integer
    product_id : integer
    price : float
    date_start : date
    date_end : date
    product_code : string
}

entity product_category {
    * id : integer
    --
    name : string
    parent_id : integer
    complete_name : string
}

entity res_partner {
    * id : integer
    --
    name : string
}

' Define relationships
product_product }o-u-|| product_template : "product_tmpl_id"
product_template ||-u-o{ product_category : "categ_id"
product_supplierinfo ||-l-|| product_template : "product_tmpl_id"
product_supplierinfo ||--|| product_product : "product_id"
product_supplierinfo ||-u-|| res_partner : "partner_id"
product_pricelist ||--o{ product_pricelist_item : "pricelist_id"
product_pricelist_item ||-r-|| product_template : "product_tmpl_id"
product_pricelist_item ||-r-|| product_product : "product_id"

@enduml

```

| # | 名称 | model name | 説明 | 備考 |
|:-:|:--|:--|:--|:--|
| 1 | テンプレートマスタ | product.template        | 商品の基本情報  |  |
| 2 | 商品マスタ        | product.product         | 商品のバリエーション | defaut_codeを保持 |
| 3 | 価格表(詳細)      | product.pricelist.item  | 販売価格  | 価格表で管理される |
| 4 | 仕入価格表        | product.supplierinfo    | 仕入価格  | 仕入先のproduct_codeあり  |

# 指定日における販売価格と仕入価格の取得

販売価格や仕入価格は、有効期限を設けた価格設定が可能ですが、次のように指定日の価格をそれぞれ取得することが可能です。

## 販売価格

価格表を取得し（例では１件目を取得）、その価格表から価格を計算取得する。
価格計算は、`product.pricelist`モデルの`_get_product_price()`メソッドが行う。

```py: 販売価格 - product_price

    # 価格表と販売価格の取得
    product_pricelist = request.env["product.pricelist"].sudo()
    pricelist = product_pricelist.search([], limit=1)  # １件目の価格表
    product_price = pricelist._get_product_price(
        product=product, quantity=1.0, date=target_date
    )

```


## 仕入価格

`product.supplierinfo`モデルを検索する。

```py: 仕入価格 - purchase_price

    # 仕入れ価格の取得（テンプレートで管理）
    product_supplierinfo = request.env["product.supplierinfo"].sudo()
    query = (
        "SELECT id FROM product_supplierinfo"
        + " WHERE product_tmpl_id = %s"
        + "   AND min_qty = %s"
        + "   AND (date_start <= %s or date_start is null)"
        + "   AND (date_end >= %s or date_end is null)"
        + " ORDER BY date_start desc nulls last, date_end asc nulls last"
    )
    params = (
        product.product_tmpl_id.id, # product_tmpl_id
        1.0,                        # min_qty (quantity)
        target_date,                # date_start
        target_date,                # date_end
    )
    product_supplierinfo.env.cr.execute(query, params)
    supplierinfo_id = product_supplierinfo.env.cr.fetchone()[0]
    supplierinfo = product_supplierinfo.browse(supplierinfo_id)
    purchase_price = supplierinfo.price if supplierinfo else 0.0
    
```