报表
This commit is contained in:
@@ -225,107 +225,90 @@ class AiReportTemplate(models.Model):
|
||||
if self.model_id:
|
||||
self.model_name = self.model_id.model
|
||||
|
||||
# ===== onchange: field_ids 变化时联动更新 =====
|
||||
@api.onchange('field_ids')
|
||||
def _onchange_field_ids(self):
|
||||
"""显示字段变化 → 自动同步 字段列表 + 字段标签 + 列定义"""
|
||||
if self.field_ids:
|
||||
self.field_list = json.dumps([f.name for f in self.field_ids], ensure_ascii=False)
|
||||
self.field_list = json.dumps(
|
||||
[f.name for f in self.field_ids], ensure_ascii=False)
|
||||
self.field_labels = json.dumps(
|
||||
{f.name: f.field_description for f in self.field_ids},
|
||||
ensure_ascii=False
|
||||
)
|
||||
# 同步 column_ids:去重 + 删不在的 + 补缺失的 + 修复空字段
|
||||
if self.column_ids or self.field_ids:
|
||||
new_field_ids = set(self.field_ids.ids)
|
||||
cmds = []
|
||||
# 1) 收集 column_ids,按 field_id 分组,重复的只保留第一个
|
||||
kept = {}
|
||||
for col in self.column_ids:
|
||||
fid = col.field_id.id if col.field_id else None
|
||||
if not fid:
|
||||
cmds.append((2, col.id))
|
||||
elif fid not in kept:
|
||||
kept[fid] = col
|
||||
else:
|
||||
cmds.append((2, col.id)) # 重复的删掉
|
||||
# 2) 修复 kept 列中 field_name 为空的列
|
||||
for fid, col in kept.items():
|
||||
if not col.field_name:
|
||||
f = self.field_ids.filtered(lambda r: r.id == fid)
|
||||
fname = f.name if f else col.field_id.name
|
||||
cmds.append((1, col.id, {'field_name': fname}))
|
||||
# 3) 删掉不在 field_ids 里的
|
||||
for fid, col in kept.items():
|
||||
if fid not in new_field_ids:
|
||||
cmds.append((2, col.id))
|
||||
# 4) 补充 field_ids 里有但 column_ids 里没有的
|
||||
seq = max((col.sequence for col in self.column_ids), default=0) + 10
|
||||
for f in self.field_ids:
|
||||
if f.id not in kept:
|
||||
cmds.append((0, 0, {
|
||||
'field_id': f.id,
|
||||
'field_name': f.name,
|
||||
'label': f.field_description,
|
||||
'sequence': seq,
|
||||
}))
|
||||
seq += 10
|
||||
if cmds:
|
||||
self.column_ids = cmds
|
||||
ensure_ascii=False)
|
||||
else:
|
||||
self.field_list = '[]'
|
||||
self.field_labels = '{}'
|
||||
# 同步列定义(onchange 和 write 共用同一套逻辑)
|
||||
self._sync_columns()
|
||||
|
||||
# ===== create / write 同步 =====
|
||||
# ===== create / write: 保存时联动同步 =====
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('model_id') and not vals.get('model_name'):
|
||||
model = self.env['ir.model'].browse(vals['model_id'])
|
||||
vals['model_name'] = model.model
|
||||
if vals.get('field_ids'):
|
||||
if 'field_ids' in vals:
|
||||
self._sync_field_list_from_ids(vals)
|
||||
records = super().create(vals_list)
|
||||
for record in records:
|
||||
if record.field_ids:
|
||||
record._sync_column_ids_from_field_ids()
|
||||
record._sync_columns()
|
||||
return records
|
||||
|
||||
def write(self, vals):
|
||||
if vals.get('model_id') and 'model_name' not in vals:
|
||||
model = self.env['ir.model'].browse(vals['model_id'])
|
||||
vals['model_name'] = model.model
|
||||
if vals.get('field_ids'):
|
||||
field_ids_changed = 'field_ids' in vals
|
||||
if field_ids_changed:
|
||||
self._sync_field_list_from_ids(vals)
|
||||
result = super().write(vals)
|
||||
# 任何 write 都触发 column 去重 + 同步(清理历史重复数据 + 确保一致性)
|
||||
for record in self:
|
||||
if record.field_ids:
|
||||
record._sync_column_ids_from_field_ids()
|
||||
if field_ids_changed:
|
||||
for record in self:
|
||||
record._sync_columns()
|
||||
return result
|
||||
|
||||
def _sync_column_ids_from_field_ids(self):
|
||||
"""根据 field_ids 同步 column_ids:去重 + 删不在的 + 补缺失的 + 修复空字段"""
|
||||
# ===== 核心:列定义同步 =====
|
||||
def _sync_columns(self):
|
||||
"""根据 field_ids 同步 column_ids,保证:
|
||||
① 列定义 = 显示字段(一对一对应)
|
||||
② 不重复 → 同一 field_id 只保留一条
|
||||
③ 不遗漏 → field_ids 有的必须建列
|
||||
④ 不多余 → field_ids 没的必须删列
|
||||
⑤ 可修复 → field_name 为空的自动补全"""
|
||||
self.ensure_one()
|
||||
new_field_ids = set(self.field_ids.ids)
|
||||
target_fids = set(self.field_ids.ids)
|
||||
cmds = []
|
||||
# 1) 收集 column_ids,按 field_id 分组,重复的只保留第一个
|
||||
kept = {}
|
||||
kept = {} # fid → col(去重后唯一保留的列)
|
||||
|
||||
# ---- 步骤 1:遍历现有 column_ids,去重 + 清理无 field_id 的脏数据 ----
|
||||
for col in self.column_ids:
|
||||
fid = col.field_id.id if col.field_id else None
|
||||
if not fid:
|
||||
cmds.append((2, col.id)) # 没有 field_id 的脏数据直接删
|
||||
elif fid not in kept:
|
||||
kept[fid] = col
|
||||
cmds.append((3, col.id)) # 脏数据:无关联 field → 删除
|
||||
elif fid in kept:
|
||||
cmds.append((3, col.id)) # 重复:同一 field_id 第二条 → 删除
|
||||
else:
|
||||
cmds.append((2, col.id)) # 重复的删掉
|
||||
# 2) 修复 kept 列中 field_name 为空的列(required=True 约束)
|
||||
kept[fid] = col # 首条 → 保留
|
||||
|
||||
# ---- 步骤 2:删除 field 已不在 field_ids 中的列 ----
|
||||
for fid, col in list(kept.items()):
|
||||
if fid not in target_fids:
|
||||
cmds.append((3, col.id))
|
||||
del kept[fid] # 从 kept 清除,避免步骤 4 误判
|
||||
|
||||
# ---- 步骤 3:修复保留列中 field_name 为空的 ----
|
||||
for fid, col in kept.items():
|
||||
if not col.field_name:
|
||||
f = self.field_ids.filtered(lambda r: r.id == fid)
|
||||
fname = f.name if f else col.field_id.name
|
||||
field = self.field_ids.filtered(lambda r: r.id == fid)
|
||||
fname = field.name if field else col.field_id.name
|
||||
cmds.append((1, col.id, {'field_name': fname}))
|
||||
# 3) 删掉不在 field_ids 里的
|
||||
for fid, col in kept.items():
|
||||
if fid not in new_field_ids:
|
||||
cmds.append((2, col.id))
|
||||
# 4) 补充 field_ids 里有但 column_ids 里没有的
|
||||
seq = max((col.sequence for col in self.column_ids), default=0) + 10
|
||||
|
||||
# ---- 步骤 4:field_ids 中有、但 column_ids 中没有的 → 新建 ----
|
||||
seq = max(
|
||||
(c.sequence for c in self.column_ids if c.sequence),
|
||||
default=0
|
||||
) + 10
|
||||
for f in self.field_ids:
|
||||
if f.id not in kept:
|
||||
cmds.append((0, 0, {
|
||||
@@ -335,28 +318,35 @@ class AiReportTemplate(models.Model):
|
||||
'sequence': seq,
|
||||
}))
|
||||
seq += 10
|
||||
|
||||
if cmds:
|
||||
self.column_ids = cmds
|
||||
|
||||
# ===== 辅助:从 vals 命令中提取 field_ids 并填充 field_list / field_labels =====
|
||||
@api.model
|
||||
def _sync_field_list_from_ids(self, vals):
|
||||
import json
|
||||
"""从 vals['field_ids'](Many2many 命令格式)提取 ID 集合,
|
||||
无条件覆盖 field_list 和 field_labels(因为 field_ids 变了)"""
|
||||
ids = []
|
||||
field_cmds = vals['field_ids']
|
||||
if isinstance(field_cmds, list):
|
||||
for cmd in field_cmds:
|
||||
if isinstance(cmd, (list, tuple)):
|
||||
if cmd[0] == 6:
|
||||
ids = cmd[2]
|
||||
if cmd[0] == 6: # (6, 0, ids) → 全量替换
|
||||
ids = list(cmd[2]) if cmd[2] else []
|
||||
break
|
||||
elif cmd[0] == 4:
|
||||
elif cmd[0] == 4: # (4, id) → 追加
|
||||
ids.append(cmd[1])
|
||||
elif cmd[0] == 5: # (5,) → 清空所有
|
||||
ids = []
|
||||
break
|
||||
if ids:
|
||||
fields_records = self.env['ir.model.fields'].browse(ids)
|
||||
if not vals.get('field_list'):
|
||||
vals['field_list'] = json.dumps([f.name for f in fields_records], ensure_ascii=False)
|
||||
if not vals.get('field_labels'):
|
||||
vals['field_labels'] = json.dumps(
|
||||
{f.name: f.field_description for f in fields_records},
|
||||
ensure_ascii=False
|
||||
)
|
||||
vals['field_list'] = json.dumps(
|
||||
[f.name for f in fields_records], ensure_ascii=False)
|
||||
vals['field_labels'] = json.dumps(
|
||||
{f.name: f.field_description for f in fields_records},
|
||||
ensure_ascii=False)
|
||||
else:
|
||||
vals['field_list'] = '[]'
|
||||
vals['field_labels'] = '{}'
|
||||
|
||||
Reference in New Issue
Block a user