From f147c9411851580160ea3c8335c143c8a30a6b57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 19 Sep 2024 13:31:59 +0200 Subject: [PATCH] Fill the source value of fmany2one in create and write methods We can not rely on the Function field setter to set the value because it may be too late if the source field is required and for composite key, a partial update may not be a valid foreign key. Closes #13522 --- trytond/trytond/model/fields/fmany2one.py | 33 ++++++++++++++++++----- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/trytond/trytond/model/fields/fmany2one.py b/trytond/trytond/model/fields/fmany2one.py index f54772e374..a730e3e9d8 100644 --- a/trytond/trytond/model/fields/fmany2one.py +++ b/trytond/trytond/model/fields/fmany2one.py @@ -17,6 +17,12 @@ def fmany2one( target_fields = target_fields.split(',') assert len(sources) == len(target_fields) + def convert_value(value): + pool = Pool() + Target = pool.get(target_model) + if isinstance(value, int): + return getattr(Target(value), target_fields[0]) + class Mixin: __slots__ = () @@ -30,6 +36,25 @@ def fmany2one( sources, Target._table, target_fields, on_delete=getattr(cls, name).ondelete) + @classmethod + def create(cls, vlist): + vlist = [v.copy() for v in vlist] + for values in vlist: + if name in values: + values[sources[0]] = convert_value(values.pop(name)) + return super().create(vlist) + + @classmethod + def write(cls, *args): + actions = iter(args) + args = [] + for records, values in zip(actions, actions): + if name in values: + values = values.copy() + values[sources[0]] = convert_value(values.pop(name)) + args.extend((records, values)) + super().write(*args) + @classmethod def getter(cls, records, name): pool = Pool() @@ -51,13 +76,7 @@ def fmany2one( @classmethod def setter(cls, records, name, value): - pool = Pool() - Target = pool.get(target_model) - if value: - value = getattr(Target(value), target_fields[0]) - else: - value = None - cls.write(records, {sources[0]: value}) + cls.write(records, {sources[0]: convert_value(value)}) @classmethod def searcher(cls, clause, tables):