@@ -786,3 +786,85 @@ def test_uri_updates_on_code_change(self):
786786 # URI should be recomputed
787787 self .assertEqual (code .uri , "urn:test:user#CHANGED" )
788788 self .assertNotEqual (code .uri , original_uri )
789+
790+ # Import name_search scoping tests
791+ def _create_shared_display_codes (self , display = "Active" ):
792+ """Helper: create a code with the same display in two different vocabularies."""
793+ code_user = self .VocabularyCode .create (
794+ {"vocabulary_id" : self .vocab_user .id , "code" : "NS_ACT1" , "display" : display }
795+ )
796+ code_system = self .VocabularyCode .with_context (_test_bypass_system_protection = True ).create (
797+ {"vocabulary_id" : self .vocab_system .id , "code" : "NS_ACT2" , "display" : display }
798+ )
799+ return code_user , code_system
800+
801+ def test_name_search_without_context_returns_all_matches (self ):
802+ """Without context domain, name_search returns codes from all vocabularies."""
803+ code_user , code_system = self ._create_shared_display_codes ("SharedDisplay" )
804+ results = self .VocabularyCode .name_search ("SharedDisplay" , operator = "=" )
805+ result_ids = [r [0 ] for r in results ]
806+ self .assertIn (code_user .id , result_ids )
807+ self .assertIn (code_system .id , result_ids )
808+
809+ def test_name_search_with_context_domain_scopes_to_vocabulary (self ):
810+ """With _import_name_search_domain in context, name_search is restricted to that vocabulary."""
811+ code_user , code_system = self ._create_shared_display_codes ("ScopedDisplay" )
812+ domain = [("vocabulary_id" , "=" , self .vocab_user .id )]
813+ results = self .VocabularyCode .with_context (_import_name_search_domain = domain ).name_search (
814+ "ScopedDisplay" , operator = "="
815+ )
816+ result_ids = [r [0 ] for r in results ]
817+ self .assertIn (code_user .id , result_ids )
818+ self .assertNotIn (code_system .id , result_ids )
819+
820+ def test_name_search_context_domain_does_not_affect_other_vocabulary (self ):
821+ """Context domain scoped to system vocab excludes user vocab codes."""
822+ code_user , code_system = self ._create_shared_display_codes ("OtherScopeDisplay" )
823+ domain = [("vocabulary_id" , "=" , self .vocab_system .id )]
824+ results = self .VocabularyCode .with_context (_import_name_search_domain = domain ).name_search (
825+ "OtherScopeDisplay" , operator = "="
826+ )
827+ result_ids = [r [0 ] for r in results ]
828+ self .assertIn (code_system .id , result_ids )
829+ self .assertNotIn (code_user .id , result_ids )
830+
831+ def test_db_id_for_list_domain_scopes_name_search (self ):
832+ """db_id_for passes a list field domain to name_search, avoiding cross-vocab matches."""
833+ code_user , code_system = self ._create_shared_display_codes ("DbIdDisplay" )
834+ field = SimpleNamespace (
835+ domain = [("vocabulary_id" , "=" , self .vocab_user .id )],
836+ comodel_name = "spp.vocabulary.code" ,
837+ )
838+ savepoint = MagicMock ()
839+ converter = self .env ["ir.fields.converter" ]
840+ result_id , warnings = converter .db_id_for (None , field , None , "DbIdDisplay" , savepoint )
841+ self .assertEqual (result_id , code_user .id )
842+ self .assertEqual (warnings , [])
843+
844+ def test_db_id_for_string_domain_scopes_name_search (self ):
845+ """db_id_for evaluates a static string domain and applies it to name_search."""
846+ code_user , code_system = self ._create_shared_display_codes ("StrDomainDisplay" )
847+ domain_str = f"[('vocabulary_id', '=', { self .vocab_user .id } )]"
848+ field = SimpleNamespace (
849+ domain = domain_str ,
850+ comodel_name = "spp.vocabulary.code" ,
851+ )
852+ savepoint = MagicMock ()
853+ converter = self .env ["ir.fields.converter" ]
854+ result_id , warnings = converter .db_id_for (None , field , None , "StrDomainDisplay" , savepoint )
855+ self .assertEqual (result_id , code_user .id )
856+ self .assertEqual (warnings , [])
857+
858+ def test_db_id_for_no_domain_returns_multiple_match_warning (self ):
859+ """db_id_for with no field domain falls back to unscoped search, producing a multiple-match warning."""
860+ code_user , code_system = self ._create_shared_display_codes ("NoDomainDisplay" )
861+ field = SimpleNamespace (
862+ domain = [],
863+ comodel_name = "spp.vocabulary.code" ,
864+ )
865+ savepoint = MagicMock ()
866+ converter = self .env ["ir.fields.converter" ]
867+ result_id , warnings = converter .db_id_for (None , field , None , "NoDomainDisplay" , savepoint )
868+ # Still resolves (picks first), but warns about multiple matches
869+ self .assertIsNotNone (result_id )
870+ self .assertTrue (len (warnings ) > 0 )
0 commit comments