イントロダクション
Odooで小数点を伴うデータを扱うとき、もっとも頻繁に使われるのがFloat(小数)フィールドです。単価、製品の重量、割引率、税率、製造の換算係数といった値は、多くの場合Floatとしてモデル上に保存されます。
見た目は単純な数値入力ですが、実際には表示桁数、丸め処理、レポート集計での振る舞いなど、知っておくべきポイントがいくつかあります。状況によっては別のフィールド種別を選ぶべきこともあります。
本ガイドでは、Floatフィールドが何を保存するのか、Odooの内部でどのように扱われるか、Odoo StudioやPythonコードでの作成方法、そして営業や在庫、会計などの実務での活用例を紹介します。
OdooにおけるFloatフィールドとは何か
OdooのORM上ではFloatフィールドは小数を保持し、PostgreSQLのdouble precision列にマップされます。これは概ね15桁程度の有効数字を確保でき、通常の業務用途では十分な精度を提供します。
ユーザー画面ではFloatは数値入力欄として表示され、表示桁数はフィールド定義時のdigitsパラメータで制御されます。リストでは右寄せ表示が標準で、ピボットやグラフでは合計・平均などの集計対象として扱われます。
以下はPythonのモデル定義における例です。
from odoo import fields, models
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
custom_margin = fields.Float(
string='Custom Margin',
digits=(5, 2),
default=0.0,
)
digitsはタプルで、最初の数が有効桁数、2番目が小数点以下桁数を指します。たとえば(5, 2)は5桁中小数2桁までという意味になります。
digitsの代わりに名前付きの精度グループを参照する方法もあります。
price_premium = fields.Float(
string='Price Premium',
digits='Product Price',
)
Odooには「Decimal Accuracy(小数精度)」として設定可能な精度グループがあり、Product PriceやProduct Unit of Measure、Discount、Stock Weightなどが用意されています。精度グループを使うと管理画面から桁数を調整でき、コードを触らずに全体の精度を統一できます。
Odoo StudioではFloatフィールドは「Decimal Number」という名前で追加できます。Studio経由で作ると既定の精度が適用され、プロパティパネルで必要な設定を変更すれば開発者なしでフォーム拡張が可能です。
Floatフィールドの仕組み
フィールドを定義すると、モジュールのインストールやアップグレード時にOdooが自動的にデータベース列を作成します。手動でSQLを書いたり移行スクリプトを用意したりする必要は基本的にありません。
digitsパラメータは表示桁数だけでなく保存時の丸めにも影響します。たとえばdigits=(6,2)でユーザーが3.14159を入れると、ORMレベルで3.14に丸められて保存されます。表示だけの処理ではなく保存時にも適用される点が重要です。
主なフィールド属性
OdooでFloatフィールドに設定できる重要なプロパティは次の通りです。
- digits: (6,2)のようなタプルか、名前付きの精度グループを指定します。表示と保存の精度を決めます。
- required: 必須設定にできます。注意点として、値が0.0だと必須チェックを通ってしまうため、意図を確認して使う必要があります。
- default: 新規作成時の初期値です。default=0.0を設定するとFalse(空)ではなく数値が常に入るため、計算時のエラーを避けられます。
- compute: Pythonメソッドで動的に計算するフィールドに使います。マージンや換算結果など派生値に便利です。
- store: computeと併用して計算結果をDBに保存すると、検索や集計が可能になります。
- group_operator: ピボットやグラフでの集計方法を指定します。'sum'、'avg'、'min'、'max'など。デフォルトは'sum'です。
- copy: レコード複製時に値をコピーするかどうか。デフォルトはTrueです。
ビューでの表示
フォームでは数値入力、リストでは右寄せ、検索では比較演算子でフィルタできます。ユーザーのロケールに応じて小数点の区切り文字も自動で反映されます。
ビューにウィジェットを付けることも可能です。たとえばpercentageウィジェットは表示時に値を100倍して%記号を付けるため、0〜1で保存する率をユーザーに0〜100で見せたい場合に有用です。
ORMとのやり取り
読み取り時はPythonのfloatを返し、未設定でデフォルトもない場合はFalseになります。書き込みは整数・浮動小数・Falseを受け付け、保存時にdigitsで定めた精度で丸めが行われます。
注意点としてFloatの比較に==を使ってはいけません。ハードウェアの浮動小数点演算の性質上、一見同じ値でも等しくない場合があります。odoo.tools.float_utilsのfloat_compareやfloat_is_zeroを使い、モデルで定義した精度を踏まえた比較を行ってください。
業務での利用シーン
Floatフィールドはほぼすべてのモジュールに登場します。以下に実務でよく使われる具体例を挙げます。
営業:受注行の割引率
sales.order.lineのdiscountはFloatです。営業担当が15%の割引を入力するとOdooは15.0として保持し、単価計算や見積書、請求書、マージン集計へ反映されます。割引の扱いは顧客への表示と利益管理の双方で重要です。
在庫:製品の重量や容積
製品にはweightやvolumeといったFloatフィールドがあり、2.5kgや0.003m3といった小数が必要になります。これらは配送コスト計算や配送業者APIとの連携に直接影響します。精度が低いと送料見積もりが狂います。
会計:税率
account.taxの税率はFloatで管理されます。たとえば標準VATは21.0、軽減税率は6.0や5.5といった表現になります。税計算は大量の取引に影響するため、丸め誤差が積み重なると報告値に差異が生じることがあります。
製造:部品表の数量
製造モジュールではBOMの各部品数量がFloatです。0.75リットルや2.5kgといった分量を扱うため、小数が自然に必要になります。整数フィールドでは不正確さが生じ、生産上のミスにつながることがあります。
購買:価格係数や仕入れマージン
ベンダープライスリストやマークアップの係数はFloatで表現されます。1.25の掛け率(25%増)や0.85の割引係数は購買価格の自動計算に使われ、ベンダー間での価格整合性に寄与します。
Floatフィールドの作成とカスタマイズ方法
Floatフィールドを追加する方法は主に3つあります。技術的な状況や運用方針に応じて選んでください。
Odoo Studioを使う(ノーコード)
Odoo Studioは内蔵のローコードツールです。コードを書かずにFloatフィールドを追加する手順は次の通りです。
- メインメニューからOdoo Studioを起動します。
- フィールドを追加したいフォームを開きます。
- フィールドピッカーからDecimal Numberをフォームへドラッグします。
- ラベル、初期値、表示桁数をプロパティパネルで設定します。
- 保存してStudioを閉じます。
Studioはフィールドにx_studio_プレフィックスを付けてフォームに追加します。データベース側の作業は不要で、非開発者でも簡単にカスタマイズできます。
Pythonでカスタムモジュールを作る場合
開発者がモジュールを作るならPython内で直接Floatを定義します。バージョン管理や複数環境への展開を考えるとこちらが推奨される方法です。
from odoo import fields, models
class ResPartner(models.Model):
_inherit = 'res.partner'
x_credit_limit = fields.Float(
string='Credit Limit',
digits=(12, 2),
default=0.0,
help='Maximum outstanding balance allowed for this customer.',
)
モデルにフィールドを追加したら、ビューのXMLに組み込んで画面表示を行います。モジュールのインストール・アップグレード時にOdooが自動でDB列を作成します。これは本格的なカスタマイズでの標準的な手順です。
XML-RPC APIを使う方法
デプロイ自動化やリモート設定スクリプト経由で管理する場合、XML-RPC APIでフィールドを作成することもできます。
field_id = models.execute_kw(
ODOO_DB, uid, ODOO_API_KEY,
'ir.model.fields', 'create',
[{
'name': 'x_custom_coefficient',
'field_description': 'Custom Coefficient',
'model_id': model_id,
'ttype': 'float',
'state': 'manual',
}]
)
state:'manual'は手動生成フィールドであることを示し、StudioやAPIで作成したフィールドに適した設定です。APIで作成したFloatの精度はTechnicalのDecimal Accuracyで管理します。
推奨される運用ルール
1. 標準値には名前付き精度グループを使う
digits=(6,2)のように固定せず、'Product Price'や'Product Unit of Measure'のような精度グループを参照すると、管理画面から一括で桁数を調整でき、ネイティブのフィールドと精度を揃えられます。
2. 通貨金額はFloatではなくMonetaryを使う
最重要ポイントのひとつです。Monetaryフィールドは同一モデル上の通貨フィールドと紐づき、通貨ごとの丸め規則に従います。請求金額や販売価格をFloatで扱うと多通貨環境で集計が狂うため、必ずMonetary型を使ってください。
3. 常にデフォルト値を設定する
numericフィールドはdefault=0.0を設定しておく習慣をつけましょう。未設定だと値がFalseになり、計算ロジックでTypeErrorを引き起こす原因になります。
4. レポート用にgroup_operatorを設定する
数量や金額を集計するならgroup_operator='sum'、割合や率なら'avg'を設定するなど、分析用途に合わせた集計方法を定義しておくとピボットやグラフが期待通りに動きます。
5. パーセンテージの表現ルールを明確にする
パーセンテージを保存する際、0〜100のレンジ(例:15.0 = 15%)なのか0〜1のレンジ(例:0.15 = 15%)なのかをチームで統一し、仕様としてドキュメント化しておきましょう。混在すると計算エラーが見つけにくくなります。
よくある落とし穴
通貨金額にFloatを使う問題点
Floatには通貨情報が含まれないため、1500という値がユーロなのかドルなのか判別できません。多通貨環境では合計が正しくならないため、通貨を伴う金額は必ずMonetary型で管理してください。
digitsを設定しないリスク
digitsを指定しないとデフォルトで小数2桁になります。価格なら問題ない場合もありますが、為替レートや換算係数のように4〜6桁が必要な場合に丸めが入り、取引ごとに誤差が蓄積する恐れがあります。
Pythonで==によるFloat比較をする危険性
浮動小数点の性質上、0.1 + 0.2 == 0.3がFalseになるような事象が発生します。精度を踏まえた比較はodoo.tools.float_utilsのfloat_compareやfloat_is_zeroを使って行ってください。
整数がふさわしい場面でFloatを使う問題
件数やパッケージ数、シーケンス番号のように必ず整数になる値はIntegerフィールドを使うべきです。Floatを使うとユーザーが小数を入力してしまい、業務上の混乱を招くことがあります。
computeメソッドでFalse値を扱わない問題
デフォルトがないFloatは未設定時にFalseを返します。算術処理前にはFalseチェックを入れるか、あらかじめdefault=0.0を設定しておきましょう。さもないと実運用でTypeErrorが発生します。
まとめ
まとめとして、FloatフィールドはOdooモデルの基礎的な要素であり、価格・数量・率・寸法など幅広い小数データを扱います。適切な精度と初期値を設定すれば信頼性高く運用できます。
覚えておくべき要点は、標準値には名前付き精度グループを使うこと、通貨はMonetaryで管理すること、デフォルト値を必ず設定すること、そしてパーセンテージの表現ルールを明文化することです。これらの習慣がデータ品質の問題を未然に防ぎます。
Odoo Studioでの追加、カスタムモジュールでの定義、あるいはORM/API経由での管理、どの方法でもFloatフィールドを最初から正しく設計しておくことが、保守しやすく信頼できる実装につながります。
Dasoloでは、企業のOdoo導入・カスタマイズ・最適化を部門横断で支援しています。データモデル設計、フォームへのカスタムフィールド追加、モジュール開発まで幅広くサポート可能です。 お問い合わせはこちら ぜひご相談ください。あなたのOdooプロジェクトについてお話しましょう。