Hi everyone,
I'm currently developing a module for the management of lost object. And for this module, i've created another module that list all the french region, departments, municipalities and postal codes.
I'm using a docker-compose file with the version 18 of Odoo to develop.
What i am trying to do, is that when a user selects a zip code when registering a lost item, a list of cities with the same zip code is displayed (and vice versa when the user enters a city), and i'm trying to achieve this by changing the domain.
I've also added the ability to auto-populate the field if there is only one zip code associated to a city.
When i choose a city that has only one postal code, the postal code is automatically filled (and vice versa for the city).
But when there's more than one city attached to a postal code, i got the good informations, but the list is not filtered when i try to select a city.
This is what is displayed with the UserError :
City associated with zip code 64110 : ['Gelos', 'Jurançon', 'Laroin', 'Mazères-Lezons', 'Rontignon', 'Saint-Faust', 'Uzos'].
Here is what is contained in 'communes' : [27049, 27094, 27127, 27184, 27280, 27291, 27361]
The numbers correspond to the Id assigned by Odoo to the city. I checked and the ID 27049 does indeed correspond to the city of Gelos
Here's the code of my two models from my "Postal" module, representing municipalities and postal code :
class Commune(models.Model):
_name = 'postal.commune'
_description = 'Communes de France'
name = fields.Char("Nom de la commune",required=True)
type_commune = fields.Selection([
('ARM','Arrondissement municipal'),
('COM','Commune'),
('COMA','Commune associée'),
('COMD','Commune déléguée')
],string="Type de commune")
code_insee = fields.Char("Code INSEE de la commune",required=True,size=5)
departement_id = fields.Many2one("postal.departement",string="Département de la commune",required=True)
# Relation hiérarchique si une commune fait partie d'une commune (par exemple : Arbigneu et Arboys en Bugey (01015) )
parent_ids = fields.Many2one("postal.commune",string='Commune parent',ondelete='restrict')
child_ids = fields.One2many("postal.commune","parent_ids",string="Commune enfant")
codepostal_ids = fields.Many2many("postal.codepostal",string="Codes postaux de la commune")
class Codepostal(models.Model):
_name = 'postal.codepostal'
_description = 'Codes postaux de France'
name = fields.Char("Code postal",required=True,size=5)
commune_ids = fields.Many2many("postal.commune",string="Communes liées au code postal",required=True)
And here is the model from my module for management of lost object :
class Annonce(models.Model):
# Champs obligatoires utilisée par Odoo
_name = 'objetperdu.annonce'
_description = 'Annonce d\'un objet perdu ou trouvé'
# Champs propre à l'objet
state = fields.Selection([('perdu','Perdu'),('trouve','Trouvé')],string="État de l'objet",default="perdu")
date_depot = fields.Date('Date de l\'annonce',required=True)
category_id = fields.Many2one('objetperdu.categorie',required=True,string="Catégorie de l'objet")
# Champs relatifs à l'endroit où l'objet a été trouvé
adresse = fields.Char('Adresse d\'où l\'objet a été trouvé/perdu',required=True)
cp = fields.Many2one('postal.codepostal',string='Code postal',size=5,required=True)
ville = fields.Many2one('postal.commune',string='Ville',required=True)
# Champs relatifs à la description de l'objet
marque = fields.Char("Marque")
description = fields.Text("Description de l'objet")
contient_objet = fields.Boolean("Contient des objets ?")
description_contenu = fields.Text("Description du contenu")
@api.onchange('cp')
# Affiche les villes du code postal saisie, et pré-remplit le champ ville si le code postal n'appartient qu'à une seule commune
def _onchange_cp(self):
if self.cp:
communes = self.cp.commune_ids
#raise UserError(f"Communes associées au code postal {self.cp.name} : {communes.mapped('name')}. Voici ce que contient 'communes' : {communes.ids}")
if len(communes) == 1:
self.ville = communes[0]
return {'domain': {'ville': [('id', 'in', communes.ids)]}}
else:
return {'domain': {'ville': []}}
@api.onchange('ville')
# Affiche les codes postaux de la ville saisie, et pré-remplit le code postal s'il n'y en a qu'un
def _onchange_ville(self):
if self.ville:
codes = self.ville.codepostal_ids
#raise UserError(f"Codes postaux associés à la ville {self.ville.name} : {codes.mapped('name')}")
if len(codes) == 1:
self.cp = codes[0]
return {'domain': {'cp': [('id', 'in', codes.ids)]}}
else:
return {'domain': {'cp': []}}
And here is the view for the "Annonce" model :
<odoo>
<!-- Création de la vue de formulaire -->
<record id="view_form_annonce" model="ir.ui.view">
<field name="name">Formulaire d'annonce</field>
<field name="model">objetperdu.annonce</field>
<field name="arch" type="xml">
<form string="annonce">
<header>
<field name="state" widget="statusbar" statusbar_visible="perdu,trouve"/>
</header>
<sheet>
<notebook>
<!-- Onglet pour les informations générales -->
<page name="general" string="Général">
<group name="general_line1">
<h2>État actuel de l'objet</h2>
<field name="state"/>
<field name="date_depot"/>
<field name="category_id"/>
</group>
</page>
<!-- Onglet pour le lieu de trouvaille-->
<page name="lieu" string="Lieu de la perte">
<group>
<h2>Adresse de l'endroit où l'objet a été trouvé</h2>
<field name="adresse"/>
<field name="cp" onchange="1"/>
<field name="ville" onchange="1"/>
</group>
</page>
<!-- Onglet pour la description de l'objet -->
<page name="description" string="Description de l'objet">
<group>
<h2>Détails sur l'objet</h2>
<field name="marque"/>
<field name="description"/>
<field name="contient_objet"/>
<field name="description_contenu" invisible="not contient_objet" required="contient_objet"/>
</group>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<!-- Création de la vue de liste -->
<record id="view_list_annonce" model="ir.ui.view">
<field name="name">Liste des annonces</field>
<field name="model">objetperdu.annonce</field>
<field name="arch" type="xml">
<list>
<field name="state"/>
<field name="date_depot"/>
<field name="adresse"/>
</list>
</field>
</record>
<!-- Création de la barre de recherche -->
<record id="view_search_annonce" model="ir.ui.view">
<field name="name">Filtre des annonces</field>
<field name="model">objetperdu.annonce</field>
<field name="arch" type="xml">
<search>
<field name="category_id"/>
<group expand="0" string="Filtres avancés">
<filter name="perdu" string="Perdu" domain="[('state','=','perdu')]"/>
<filter name="trouve" string="Trouvé" domain="[('state','=','trouve')]"/>
</group>
</search>
</field>
</record>
</odoo>
Thank you in advance for your help.