portal fieldと画面項目

フィールドメタ情報の取り出し方。


-- ★ ここの 'res.partner' を取り出したいモデルに置き換えてください
WITH params AS (
  SELECT 'res.partner'::text AS target_model
),
base AS (
  SELECT
    m.model                                     AS model,
    replace(m.model, '.', '_')                  AS model_table,
    f.id                                        AS field_id,
    f.name                                      AS field_name,
    f.ttype                                     AS ttype,
    CASE WHEN f.ttype IN ('many2one','one2many','many2many')
         THEN f.relation ELSE NULL END          AS relation_model,
    COALESCE(f.translate, FALSE)                AS translate,
    CASE f.state WHEN 'base' THEN 'code'
                 WHEN 'manual' THEN 'studio'
                 ELSE 'code' END                AS origin,
    f.required                                  AS required,
    f.field_description                         AS label_en,  -- 英語原文そのまま
    f.help                                      AS help_en    -- 英語原文そのまま
  FROM ir_model m
  JOIN ir_model_fields f ON f.model_id = m.id
  JOIN params p          ON m.model = p.target_model
  -- 一時モデルを除外するなら下行を有効化
  -- WHERE COALESCE(m.transient, FALSE) = FALSE
),
grp AS (
  -- 可視グループの XMLID 配列(必要なければこのCTEと最終SELECTの列を削ってOK)
  SELECT
    b.field_id,
    ARRAY_AGG(DISTINCT (imd.module || '.' || imd.name))
      FILTER (WHERE imd.id IS NOT NULL) AS groups_xml_ids
  FROM base b
  LEFT JOIN ir_model_fields_group_rel rel ON rel.field_id = b.field_id
  LEFT JOIN res_groups g                  ON g.id = rel.group_id
  LEFT JOIN ir_model_data imd             ON imd.model = 'res.groups' AND imd.res_id = g.id
  GROUP BY b.field_id
)
SELECT
  b.model,
  b.model_table,
  b.field_name,
  b.ttype,
  b.relation_model,
  b.translate,
  b.required,
  b.origin,
  b.label_en,
  b.help_en,
  COALESCE(g.groups_xml_ids, ARRAY[]::text[]) AS groups_xml_ids
FROM base b
LEFT JOIN grp g ON g.field_id = b.field_id
ORDER BY b.field_name;
スキーマ追加

ALTER TABLE portal_fields
  ADD COLUMN visibility TEXT NOT NULL DEFAULT 'visible',
  ADD CONSTRAINT ck_visibility CHECK (visibility IN ('visible','invisible'));

画面項目とテーブルマッピング

埋められる項目

portal_fields画面表示名(日本語)取得元 / 算出方法補足
modelモデル技術名ir_model.model例: res.partner
model_tableモデル物理名(テーブル)replace(ir_model.model,'.','_')例: res_partner
field_nameフィールド技術名ir_model_fields.name例: x_customer_rank
ttypeデータ型ir_model_fields.ttypechar,integer,many2one
relation_model関連モデルCASE WHEN ttype IN (...) THEN ir_model_fields.relationリレーション型のみ値あり
translate値の多言語フラグir_model_fields.translateTRUE=値が多言語(JSON等)
label_i18n表示ラベル(多言語){'en_US': ir_model_fields.field_description}まず英語のみ投入(後段で翻訳補完)
help_i18nヘルプ(多言語){'en_US': ir_model_fields.help}同上
ui_control(必須のみ)UI制御(必須)jsonb_build_object('required', ir_model_fields.required)required以外は未取得
groups_xml_ids権限グループ(XMLID)ir_model_fields_group_rel → res_groups → ir_model_data(module.name)例: ['base.group_user', …]
origin由来CASE ir_model_fields.state WHEN 'base'→'code'/'manual'→'studio' ELSE 'code'既存=code、Studio=studio
code_status実装状態固定(例: 'planned'初期値として投入
notes備考手入力/運用で設定任意
(オプション)visibility表示可否ルールで決定(origin='studio' or x_%visible、他invisibleスキーマ追加時に有効

埋められない項目

portal_fields画面表示名(日本語)理由 / 代替手段
placeholder_i18nプレースホルダ(多言語)DB保持が原則なし。ir_ui_view.arch_db のXML解析やポータル側設定で補完
unit_i18n単位(多言語)同上(ビュー/業務定義依存)
selection_items選択肢リスト(多言語)多くはPythonコード定義。DBのみでは不可。→ RPC/コード参照 or ビューXMLから導出
default_value既定値ir.defaultや計算式起点。現行クエリ未参照 → 対応テーブル/モデルを別参照 or RPC
widgetウィジェットビューXML依存<field widget="...">)。→ ir_ui_view.arch_db をXPath解析
ui_control の細部UI制御(不可視/読取専用/ドメイン等)ビューXMLの attrs/modifiers に依存。→ XML解析 or RPCでレンダ後属性を取得

画面項目 create

-- 既存テーブルを削除(存在すれば)
DROP TABLE IF EXISTS portal_fields CASCADE;
DROP TABLE IF EXISTS portal_field CASCADE;

-- 日本語カラム版 portal_fields を新規作成
CREATE TABLE portal_fields (
  "ID"                         BIGSERIAL PRIMARY KEY,

  -- モデル識別
  "モデル技術名"               TEXT NOT NULL,          -- 例: 'res.partner'
  "モデル物理名"               TEXT NOT NULL,          -- 例: 'res_partner'

  -- フィールド識別
  "フィールド技術名"           TEXT NOT NULL,          -- 例: 'x_customer_rank'
  "データ型"                   TEXT NOT NULL,          -- char/text/html/integer/float/boolean/selection/many2one/one2many/many2many/date/datetime/monetary/binary
  "関連モデル"                 TEXT,                   -- many2one/m2m/o2m の相手モデル(不要ならNULL)

  -- 多言語UI(ポータル表示用)
  "表示ラベル_i18n"            JSONB,                  -- {"ja_JP":"顧客ランク","en_US":"Customer Rank"}
  "ヘルプ_i18n"                JSONB,                  -- {"ja_JP":"説明...","en_US":"..."}
  "プレースホルダ_i18n"        JSONB,                  -- {"ja_JP":"入力してください", ...}
  "単位_i18n"                  JSONB,                  -- {"ja_JP":"kg","en_US":"kg"}
  "備考_i18n"                  JSONB,                  -- 任意:備考も多言語で保持したい場合

  -- 値の仕様
  "値多言語フラグ"             BOOLEAN NOT NULL DEFAULT FALSE,  -- 値が多言語(JSON)か
  "選択肢"                     JSONB,                  -- selection の場合: [{"key":"bronze","label_i18n":{...}}, ...]
  "既定値"                     JSONB,                  -- 型に応じて

  -- UI/制御(将来ビュー生成のヒント)
  "ウィジェット"               TEXT,                   -- 例: 'radio','many2one','html'
  "UI制御"                     JSONB,                  -- {"required":true, "invisible":false, ...}

  -- 権限
  "権限グループ_xmlid配列"     TEXT[],                 -- 例: ARRAY['base.group_sale_manager', ...]

  -- 運用メタ
  "由来"                       TEXT NOT NULL DEFAULT 'portal',   -- 'studio' | 'code' | 'portal'
  "実装状態"                   TEXT NOT NULL DEFAULT 'planned',  -- 'generated' | 'needs_manual' | 'not_implemented' | 'planned'
  "備考"                       TEXT,

  -- 監査
  "作成日時"                   TIMESTAMP NOT NULL DEFAULT now(),
  "更新日時"                   TIMESTAMP NOT NULL DEFAULT now(),

  -- 表示可否
  "表示"                       TEXT NOT NULL DEFAULT 'visible',

  -- 一意&妥当性
  CONSTRAINT uq_portal_fields_jp UNIQUE ("モデル技術名","フィールド技術名"),
  CONSTRAINT ck_ttype_jp CHECK (
    "データ型" IN ('char','text','html','integer','float','boolean',
                   'selection','many2one','one2many','many2many',
                   'date','datetime','monetary','binary')
  ),
  CONSTRAINT ck_relation_required_jp CHECK (
    ("データ型" IN ('many2one','one2many','many2many') AND "関連モデル" IS NOT NULL)
    OR ("データ型" NOT IN ('many2one','one2many','many2many'))
  ),
  CONSTRAINT ck_visibility_jp CHECK ("表示" IN ('visible','invisible'))
);

-- よく使う項目に索引
CREATE INDEX idx_pf_model_jp      ON portal_fields ("モデル技術名");
CREATE INDEX idx_pf_status_jp     ON portal_fields ("実装状態");
CREATE INDEX idx_pf_groups_gin_jp ON portal_fields USING GIN ("権限グループ_xmlid配列");
CREATE INDEX idx_pf_label_gin_jp  ON portal_fields USING GIN ("表示ラベル_i18n");
CREATE INDEX idx_pf_ui_gin_jp     ON portal_fields USING GIN ("UI制御");

-- 更新日時の自動更新トリガ(任意)
CREATE OR REPLACE FUNCTION set_portal_fields_updated_at()
RETURNS trigger AS $$
BEGIN
  NEW."更新日時" = now();
  RETURN NEW;
END$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trg_portal_fields_updated_at ON portal_fields;
CREATE TRIGGER trg_portal_fields_updated_at
BEFORE UPDATE ON portal_fields
FOR EACH ROW EXECUTE FUNCTION set_portal_fields_updated_at();

✅ 推奨:英語カラムビュー(SELECT用)

DROP VIEW IF EXISTS portal_fields_en;

CREATE VIEW portal_fields_en AS
SELECT
  "ID"                           AS id,
  "モデル技術名"                 AS model,
  "モデル物理名"                 AS model_table,
  "フィールド技術名"             AS field_name,
  "データ型"                     AS ttype,
  "関連モデル"                   AS relation_model,
  "表示ラベル_i18n"              AS label_i18n,
  "ヘルプ_i18n"                  AS help_i18n,
  "プレースホルダ_i18n"          AS placeholder_i18n,
  "単位_i18n"                    AS unit_i18n,
  "備考_i18n"                    AS notes_i18n,
  "値多言語フラグ"               AS translate,
  "選択肢"                       AS selection_items,
  "既定値"                       AS default_value,
  "ウィジェット"                 AS widget,
  "UI制御"                       AS ui_control,
  "権限グループ_xmlid配列"       AS groups_xml_ids,
  "由来"                         AS origin,
  "実装状態"                     AS code_status,
  "備考"                         AS notes,
  "作成日時"                     AS created_at,
  "更新日時"                     AS updated_at,
  "表示"                         AS visibility
FROM portal_fields;

Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です