details:   https://code.tryton.org/tryton/commit/6af5c937a3ce
branch:    default
user:      Cédric Krier <[email protected]>
date:      Tue Feb 24 11:34:42 2026 +0100
description:
        Support fmany2one based on Function fields
diffstat:

 trytond/CHANGELOG                         |   1 +
 trytond/trytond/model/fields/fmany2one.py |  25 ++++++++++++++++++++-----
 2 files changed, 21 insertions(+), 5 deletions(-)

diffs (51 lines):

diff -r 975bcdbbc785 -r 6af5c937a3ce trytond/CHANGELOG
--- a/trytond/CHANGELOG Tue Feb 24 09:19:37 2026 +0100
+++ b/trytond/CHANGELOG Tue Feb 24 11:34:42 2026 +0100
@@ -1,3 +1,4 @@
+* Support fmany2one based on Function fields
 * Add timestamp field on ModelSQL for last modified
 * Support Function field without getter but SQL expression
 * Add support for column_<field name> method
diff -r 975bcdbbc785 -r 6af5c937a3ce trytond/trytond/model/fields/fmany2one.py
--- a/trytond/trytond/model/fields/fmany2one.py Tue Feb 24 09:19:37 2026 +0100
+++ b/trytond/trytond/model/fields/fmany2one.py Tue Feb 24 11:34:42 2026 +0100
@@ -31,10 +31,22 @@
             pool = Pool()
             Target = pool.get(target_model)
             table_h = cls.__table_handler__(module)
+            target_h = Target.__table_handler__(module)
             super().__register__(module)
-            table_h.add_fk(
-                sources, Target._table, target_fields,
-                on_delete=getattr(cls, name).ondelete)
+            if (all(table_h.column_exist(s) for s in sources)
+                    and all(target_h.column_exist(t) for t in target_fields)):
+                table_h.add_fk(
+                    sources, Target._table, target_fields,
+                    on_delete=getattr(cls, name).ondelete)
+
+        @classmethod
+        def __setup__(cls):
+            super().__setup__()
+            if any(isinstance(getattr(cls, s), Function) for s in sources):
+                try:
+                    delattr(Mixin, f'domain_{name}')
+                except AttributeError:
+                    pass
 
         @classmethod
         def preprocess_values(cls, mode, values):
@@ -92,8 +104,11 @@
 
     setattr(Mixin, name, Function(
             Many2One(target_model, string, ondelete=ondelete, **kwargs),
-            f'get_{name}', setter=f'set_{name}'))
+            f'get_{name}',
+            setter=f'set_{name}'
+            if not kwargs.get('readonly', False) else None))
     setattr(Mixin, f'get_{name}', getter)
-    setattr(Mixin, f'set_{name}', setter)
+    if not kwargs.get('readonly', False):
+        setattr(Mixin, f'set_{name}', setter)
     setattr(Mixin, f'domain_{name}', searcher)
     return Mixin

Reply via email to