details:   https://code.tryton.org/tryton/commit/815409359e6a
branch:    default
user:      Cédric Krier <[email protected]>
date:      Thu Jun 25 16:50:42 2026 +0200
description:
        Add search attribute to XML record tag

        Closes #13247
diffstat:

 trytond/CHANGELOG                    |   1 +
 trytond/doc/topics/modules/index.rst |   3 ++
 trytond/trytond/convert.py           |  27 ++++++++++++++++++--
 trytond/trytond/ir/ir.xml            |   2 +-
 trytond/trytond/ir/lang.xml          |  48 ++++++++++++++++++------------------
 trytond/trytond/tryton.rnc           |   1 +
 6 files changed, 54 insertions(+), 28 deletions(-)

diffs (328 lines):

diff -r 7ccbc1b89620 -r 815409359e6a trytond/CHANGELOG
--- a/trytond/CHANGELOG Mon Jul 13 15:56:31 2026 +0200
+++ b/trytond/CHANGELOG Thu Jun 25 16:50:42 2026 +0200
@@ -1,3 +1,4 @@
+* Add search attribute to XML record tag
 * Enforce access right on the email template record (issue14907)
 * Add ModelAccessProxy (issue14907)
 * Restrict Genshi evaluation (issue14869, issue5160)
diff -r 7ccbc1b89620 -r 815409359e6a trytond/doc/topics/modules/index.rst
--- a/trytond/doc/topics/modules/index.rst      Mon Jul 13 15:56:31 2026 +0200
+++ b/trytond/doc/topics/modules/index.rst      Thu Jun 25 16:50:42 2026 +0200
@@ -184,6 +184,9 @@
    database.
    The ``id`` attribute can be used to refer to the record later in any XML
    file.
+   The ``search`` attribute may be set as a domain which is used to search for
+   existing record instead of creating a new one when the ``id`` is not yet
+   known.
 
 ``field``
    Set the value of the field with the name defined by the attribute ``name``.
diff -r 7ccbc1b89620 -r 815409359e6a trytond/trytond/convert.py
--- a/trytond/trytond/convert.py        Mon Jul 13 15:56:31 2026 +0200
+++ b/trytond/trytond/convert.py        Thu Jun 25 16:50:42 2026 +0200
@@ -190,6 +190,7 @@
         self.xml_ids = []
         self.model = None
         self.xml_id = None
+        self.search_domain = None
         self.update = None
         self.values = None
         self.current_field = None
@@ -206,6 +207,7 @@
             except KeyError:
                 self.xml_id = None
                 raise ParsingError("missing 'id' attribute")
+            self.search_domain = attributes.get('search', None)
 
             self.model = self.mh.pool.get(attributes["model"])
 
@@ -324,7 +326,8 @@
             if self.xml_id in self.xml_ids and not self.update:
                 raise ParsingError("duplicate id: %s" % self.xml_id)
             self.mh.import_record(
-                self.model.__name__, self.values, self.xml_id)
+                self.model.__name__, self.values, self.xml_id,
+                self.search_domain)
             self.xml_ids.append(self.xml_id)
             return None
         else:
@@ -534,7 +537,7 @@
                 ], order=[('id', 'DESC')])
         return set(rec.fs_id for rec in module_data)
 
-    def import_record(self, model, values, fs_id):
+    def import_record(self, model, values, fs_id, domain=None):
         module = self.module
 
         if not fs_id:
@@ -549,7 +552,25 @@
         # This means that the corresponding record have been found.
         self.to_delete.discard(fs_id)
 
-        if self.fs2db.exists(module, fs_id):
+        exists = self.fs2db.exists(module, fs_id)
+        if not exists and domain:
+            Model = self.pool.get(model)
+            records = Model.search(eval(domain), limit=1)
+            if records:
+                record, = records
+                mdata = self.ModelData(
+                    fs_id=fs_id,
+                    model=model,
+                    module=module,
+                    db_id=record.id,
+                    field_names=(),
+                    noupdate=self.noupdate,
+                    )
+                self.fs2db.set(module, fs_id, mdata)
+                self.grouped_model_data.add(mdata)
+                exists = True
+
+        if exists:
             if self.noupdate and self.module_state != 'to activate':
                 return
             mdata = self.fs2db.get(module, fs_id)
diff -r 7ccbc1b89620 -r 815409359e6a trytond/trytond/ir/ir.xml
--- a/trytond/trytond/ir/ir.xml Mon Jul 13 15:56:31 2026 +0200
+++ b/trytond/trytond/ir/ir.xml Thu Jun 25 16:50:42 2026 +0200
@@ -6,7 +6,7 @@
         <!--
         lang_en is defined here to be in translation lang selection
         -->
-        <record model="ir.lang" id="lang_en">
+        <record model="ir.lang" id="lang_en" search="[('code', '=', 'en')]">
             <field name="code">en</field>
             <field name="name">English</field>
             <field name="nplurals" eval="2"/>
diff -r 7ccbc1b89620 -r 815409359e6a trytond/trytond/ir/lang.xml
--- a/trytond/trytond/ir/lang.xml       Mon Jul 13 15:56:31 2026 +0200
+++ b/trytond/trytond/ir/lang.xml       Thu Jun 25 16:50:42 2026 +0200
@@ -10,7 +10,7 @@
             id="menu_localization"/>
     </data>
     <data grouped="1" noupdate="1">
-         <record model="ir.lang" id="lang_bg">
+         <record model="ir.lang" id="lang_bg" search="[('code', '=', 'bg')]">
             <field name="code">bg</field>
             <field name="name">Bulgarian</field>
             <field name="nplurals" eval="2"/>
@@ -33,7 +33,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_ca">
+        <record model="ir.lang" id="lang_ca" search="[('code', '=', 'ca')]">
             <field name="code">ca</field>
             <field name="name">Català</field>
             <field name="nplurals" eval="2"/>
@@ -56,7 +56,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_cs">
+        <record model="ir.lang" id="lang_cs" search="[('code', '=', 'cs')]">
             <field name="code">cs</field>
             <field name="name">Czech</field>
             <field name="nplurals" eval="3"/>
@@ -79,7 +79,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_de">
+        <record model="ir.lang" id="lang_de" search="[('code', '=', 'de')]">
             <field name="code">de</field>
             <field name="name">German</field>
             <field name="nplurals" eval="2"/>
@@ -105,7 +105,7 @@
         <!--
         lang_en is defined in ir.xml
         -->
-        <record model="ir.lang" id="lang_es">
+        <record model="ir.lang" id="lang_es" search="[('code', '=', 'es')]">
             <field name="code">es</field>
             <field name="name">Spanish</field>
             <field name="nplurals" eval="2"/>
@@ -128,7 +128,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_es_419">
+        <record model="ir.lang" id="lang_es_419" search="[('code', '=', 
'es_419')]">
             <field name="code">es_419</field>
             <field name="name">Spanish (Latin American)</field>
             <field name="nplurals" eval="2"/>
@@ -151,7 +151,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_et">
+        <record model="ir.lang" id="lang_et" search="[('code', '=', 'et')]">
             <field name="code">et</field>
             <field name="name">Estonian</field>
             <field name="nplurals" eval="2"/>
@@ -172,7 +172,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_fa">
+        <record model="ir.lang" id="lang_fa" search="[('code', '=', 'fa')]">
             <field name="code">fa</field>
             <field name="name">Persian</field>
             <field name="nplurals" eval="2"/>
@@ -196,7 +196,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_fi">
+        <record model="ir.lang" id="lang_fi" search="[('code', '=', 'fi')]">
             <field name="code">fi</field>
             <field name="name">Finnish</field>
             <field name="nplurals" eval="2"/>
@@ -217,7 +217,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_fr">
+        <record model="ir.lang" id="lang_fr" search="[('code', '=', 'fr')]">
             <field name="code">fr</field>
             <field name="name">French</field>
             <field name="nplurals" eval="2"/>
@@ -240,7 +240,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_hu">
+        <record model="ir.lang" id="lang_hu" search="[('code', '=', 'hu')]">
             <field name="code">hu</field>
             <field name="name">Hungarian</field>
             <field name="nplurals" eval="2"/>
@@ -263,7 +263,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_id">
+        <record model="ir.lang" id="lang_id" search="[('code', '=', 'id')]">
             <field name="code">id</field>
             <field name="name">Indonesian</field>
             <field name="nplurals" eval="1"/>
@@ -286,7 +286,7 @@
             <field name="p_sep_by_space" eval="False"/>
             <field name="n_sep_by_space" eval="False"/>
         </record>
-        <record model="ir.lang" id="lang_it">
+        <record model="ir.lang" id="lang_it" search="[('code', '=', 'it')]">
             <field name="code">it</field>
             <field name="name">Italian</field>
             <field name="nplurals" eval="2"/>
@@ -309,7 +309,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_lo">
+        <record model="ir.lang" id="lang_lo" search="[('code', '=', 'lo')]">
             <field name="code">lo</field>
             <field name="name">Lao</field>
             <field name="nplurals" eval="1"/>
@@ -332,7 +332,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_lt">
+        <record model="ir.lang" id="lang_lt" search="[('code', '=', 'lt')]">
             <field name="code">lt</field>
             <field name="name">Lithuanian</field>
             <field name="nplurals" eval="3"/>
@@ -355,7 +355,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_nl">
+        <record model="ir.lang" id="lang_nl" search="[('code', '=', 'nl')]">
             <field name="code">nl</field>
             <field name="name">Dutch</field>
             <field name="nplurals" eval="2"/>
@@ -378,7 +378,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_pl">
+        <record model="ir.lang" id="lang_pl" search="[('code', '=', 'pl')]">
             <field name="code">pl</field>
             <field name="name">Polish</field>
             <field name="nplurals" eval="3"/>
@@ -401,7 +401,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_pt">
+        <record model="ir.lang" id="lang_pt" search="[('code', '=', 'pt')]">
             <field name="code">pt</field>
             <field name="name">Portuguese</field>
             <field name="nplurals" eval="2"/>
@@ -424,7 +424,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_ro">
+        <record model="ir.lang" id="lang_ro" search="[('code', '=', 'ro')]">
             <field name="code">ro</field>
             <field name="name">Romanian</field>
             <field name="nplurals" eval="3"/>
@@ -447,7 +447,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_ru">
+        <record model="ir.lang" id="lang_ru" search="[('code', '=', 'ru')]">
             <field name="code">ru</field>
             <field name="name">Russian</field>
             <field name="nplurals" eval="3"/>
@@ -470,7 +470,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_sl">
+        <record model="ir.lang" id="lang_sl" search="[('code', '=', 'sl')]">
             <field name="code">sl</field>
             <field name="name">Slovenian</field>
             <field name="nplurals" eval="4"/>
@@ -493,7 +493,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_tr">
+        <record model="ir.lang" id="lang_tr" search="[('code', '=', 'tr')]">
             <field name="code">tr</field>
             <field name="name">Turkish</field>
             <field name="nplurals" eval="2"/>
@@ -514,7 +514,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_uk">
+        <record model="ir.lang" id="lang_uk" search="[('code', '=', 'uk')]">
             <field name="code">uk</field>
             <field name="name">Ukrainian</field>
             <field name="nplurals" eval="3"/>
@@ -535,7 +535,7 @@
             <field name="p_sep_by_space" eval="True"/>
             <field name="n_sep_by_space" eval="True"/>
         </record>
-        <record model="ir.lang" id="lang_zh_CN">
+        <record model="ir.lang" id="lang_zh_CN" search="[('code', '=', 
'zh_CN')]">
             <field name="code">zh_CN</field>
             <field name="name">Chinese Simplified</field>
             <field name="nplurals" eval="1"/>
diff -r 7ccbc1b89620 -r 815409359e6a trytond/trytond/tryton.rnc
--- a/trytond/trytond/tryton.rnc        Mon Jul 13 15:56:31 2026 +0200
+++ b/trytond/trytond/tryton.rnc        Thu Jun 25 16:50:42 2026 +0200
@@ -12,6 +12,7 @@
 record = element record { attlist.record, field* }
 attlist.record &= attribute model { text }
 attlist.record &= attribute id { text }
+attlist.record &= attribute search { text }?
 attlist.record &=
   [ a:defaultValue = "0" ] attribute update { "0" | "1" }?
 field = element field { attlist.field, text }

Reply via email to