Commit 1836b334 authored by Arthur Emynon's avatar Arthur Emynon
Browse files

Added address formatting for contact and partner

parent a2c255b3
# -*- coding: utf-8 -*-
from odoo import models, fields, api
from odoo.exceptions import ValidationError
class Contact(models.Model):
_name = "customer.contact"
......@@ -19,10 +20,13 @@ class Contact(models.Model):
street2 = fields.Char(string="Rue 2")
city = fields.Char(string="Ville")
zip = fields.Char(string="Code postal")
country_id = fields.Many2one("res.country", string="Pays")
country_id = fields.Many2one("res.country", string="Pays", default=lambda self: self._default_country())
state_id = fields.Many2one("res.country.state", string="Région")
department_id = fields.Many2one("res.country.department", string="Département")
# Sites
site_ids = fields.One2many("customer.site", "contact_id", string="Sites")
# ========================
# Computations and actions
# ========================
......@@ -37,3 +41,89 @@ class Contact(models.Model):
name = contact.name
res.append((contact.id, name))
return res
# Address
# There is a inclusion relation that allows to deduce other fields from the completion of some of them:
# zip < department < state < country
# TODO: Check if onchanges are called recursively. If so, check: - When?; - Can this generate loops of some sort?
# TODO: This does not allow exceptions. See e.g. https://fr.wikipedia.org/wiki/Code_postal_en_France#Cas_particuliers
# TODO: This only works for France (and it assumes that a country called "France" is France)
# TODO: It should probably be an option to disable auto-completion by zipcode for France...
# TODO: Add cities to these?
# TODO: Not very smart when changing the country...
@api.onchange('zip')
def _onchange_zip(record):
if record.country_id.name == "France" and record.zip and len(record.zip) == 5:
department_code = record.zip[:2]
if not record.department_id or record.department_id.code != department_code:
departments = record.env['res.country.department'].search([
('code', '=', department_code),
('country_id', '=', record.country_id.id)],
limit=2)
if len(departments) == 1:
record.department_id = departments[0]
elif record.department_id:
record.department_id = False
@api.onchange('department_id')
def _onchange_department_id(record):
if record.department_id and record.department_id.state_id != record.state_id:
record.state_id = record.department_id.state_id
if record.country_id.name == "France" and record.zip and len(record.zip) == 5 and (not record.department_id or record.zip[:2] != record.department_id.code):
record.zip = False
@api.onchange('state_id')
def _onchange_state_id(record):
if record.state_id and record.state_id.country_id != record.country_id:
record.country_id = record.state_id.country_id
if record.department_id and record.department_id.state_id != record.state_id:
record.department_id = False
@api.onchange('country_id')
def _onchange_country_id(record):
if record.state_id and record.state_id.country_id != record.country_id:
record.state_id = False
# TODO: Add an option to manage default country?
def _default_country(self):
france_ids = self.env['res.country'].name_search('France', operator='=', limit=2)
print(france_ids)
if len(france_ids) != 1:
# Default exit if France does not exists or there are too many Frances.. (should not happen?)
return None
else:
print(france_ids[0])
print(france_ids[0][0])
return france_ids[0][0]
# Address copying
def _copy_address_from(self, source):
"""
Copy address from the source. Copied fields are:
- street (Char)
- street2 (Char)
- city (Char)
- zip (Char)
- country_id (Many2one -- res.country)
- state_id (Many2one -- res.state)
- department_id (Many2one -- res.department)
The fields mentionned above must exist in the source.
(Hence, the source should be a customer.site, a customer.partner or a customer.contact.)
Both `source` is an individual records (i.e. a "singleton" recordset), while `self` may be a recordset.
"""
for record in self:
record.country_id = source.country_id
record.state_id = source.state_id
record.department_id = source.department_id
record.zip = source.zip
record.city = source.city
record.street2 = source.street2
record.street = source.street
def action_copy_address_from_partner(self):
for record in self:
record._copy_address_from(record.partner_id)
return True
# -*- coding: utf-8 -*-
from odoo import models, fields
from odoo import models, fields, api
from odoo.exceptions import ValidationError
class Partner(models.Model):
_name = "customer.partner"
......@@ -18,10 +19,69 @@ class Partner(models.Model):
street2 = fields.Char(string="Rue 2")
city = fields.Char(string="Ville")
zip = fields.Char(string="Code postal")
country_id = fields.Many2one("res.country", string="Pays")
country_id = fields.Many2one("res.country", string="Pays", default=lambda self: self._default_country())
state_id = fields.Many2one("res.country.state", string="Région")
department_id = fields.Many2one("res.country.department", string="Département")
# Contacts
contact_ids = fields.One2many("customer.contact", "partner_id", string="Contacts")
site_ids = fields.One2many("customer.site", "partner_id", string="Sites")
# ========================
# Computations and actions
# ========================
# Address
# There is a inclusion relation that allows to deduce other fields from the completion of some of them:
# zip < department < state < country
# TODO: Check if onchanges are called recursively. If so, check: - When?; - Can this generate loops of some sort?
# TODO: This does not allow exceptions. See e.g. https://fr.wikipedia.org/wiki/Code_postal_en_France#Cas_particuliers
# TODO: This only works for France (and it assumes that a country called "France" is France)
# TODO: It should probably be an option to disable auto-completion by zipcode for France...
# TODO: Add cities to these?
# TODO: Not very smart when changing the country...
@api.onchange('zip')
def _onchange_zip(record):
if record.country_id.name == "France" and record.zip and len(record.zip) == 5:
department_code = record.zip[:2]
if not record.department_id or record.department_id.code != department_code:
departments = record.env['res.country.department'].search([
('code', '=', department_code),
('country_id', '=', record.country_id.id)],
limit=2)
if len(departments) == 1:
record.department_id = departments[0]
elif record.department_id:
record.department_id = False
@api.onchange('department_id')
def _onchange_department_id(record):
if record.department_id and record.department_id.state_id != record.state_id:
record.state_id = record.department_id.state_id
if record.country_id.name == "France" and record.zip and len(record.zip) == 5 and (not record.department_id or record.zip[:2] != record.department_id.code):
record.zip = False
@api.onchange('state_id')
def _onchange_state_id(record):
if record.state_id and record.state_id.country_id != record.country_id:
record.country_id = record.state_id.country_id
if record.department_id and record.department_id.state_id != record.state_id:
record.department_id = False
@api.onchange('country_id')
def _onchange_country_id(record):
if record.state_id and record.state_id.country_id != record.country_id:
record.state_id = False
# TODO: Add an option to manage default country?
def _default_country(self):
france_ids = self.env['res.country'].name_search('France', operator='=', limit=2)
print(france_ids)
if len(france_ids) != 1:
# Default exit if France does not exists or there are too many Frances.. (should not happen?)
return None
else:
print(france_ids[0])
print(france_ids[0][0])
return france_ids[0][0]
......@@ -72,37 +72,37 @@ class CustomerSite(models.Model):
# TODO: Not very smart when changing the country...
@api.onchange('zip')
def _onchange_zip(site):
if site.country_id.name == "France" and site.zip and len(site.zip) == 5:
department_code = site.zip[:2]
if not site.department_id or site.department_id.code != department_code:
departments = site.env['res.country.department'].search([
def _onchange_zip(record):
if record.country_id.name == "France" and record.zip and len(record.zip) == 5:
department_code = record.zip[:2]
if not record.department_id or record.department_id.code != department_code:
departments = record.env['res.country.department'].search([
('code', '=', department_code),
('country_id', '=', site.country_id.id)],
('country_id', '=', record.country_id.id)],
limit=2)
if len(departments) == 1:
site.department_id = departments[0]
elif site.department_id:
site.department_id = False
record.department_id = departments[0]
elif record.department_id:
record.department_id = False
@api.onchange('department_id')
def _onchange_department_id(site):
if site.department_id and site.department_id.state_id != site.state_id:
site.state_id = site.department_id.state_id
if site.country_id.name == "France" and site.zip and len(site.zip) == 5 and (not site.department_id or site.zip[:2] != site.department_id.code):
site.zip = False
def _onchange_department_id(record):
if record.department_id and record.department_id.state_id != record.state_id:
record.state_id = record.department_id.state_id
if record.country_id.name == "France" and record.zip and len(record.zip) == 5 and (not record.department_id or record.zip[:2] != record.department_id.code):
record.zip = False
@api.onchange('state_id')
def _onchange_state_id(site):
if site.state_id and site.state_id.country_id != site.country_id:
site.country_id = site.state_id.country_id
if site.department_id and site.department_id.state_id != site.state_id:
site.department_id = False
def _onchange_state_id(record):
if record.state_id and record.state_id.country_id != record.country_id:
record.country_id = record.state_id.country_id
if record.department_id and record.department_id.state_id != record.state_id:
record.department_id = False
@api.onchange('country_id')
def _onchange_country_id(site):
if site.state_id and site.state_id.country_id != site.country_id:
site.state_id = False
def _onchange_country_id(record):
if record.state_id and record.state_id.country_id != record.country_id:
record.state_id = False
# TODO: Add an option to manage default country?
def _default_country(self):
......@@ -133,23 +133,23 @@ class CustomerSite(models.Model):
Both `source` is an individual records (i.e. a "singleton" recordset), while `self` may be a recordset.
"""
for site in self:
site.country_id = source.country_id
site.state_id = source.state_id
site.department_id = source.department_id
site.zip = source.zip
site.city = source.city
site.street2 = source.street2
site.street = source.street
for record in self:
record.country_id = source.country_id
record.state_id = source.state_id
record.department_id = source.department_id
record.zip = source.zip
record.city = source.city
record.street2 = source.street2
record.street = source.street
def action_copy_address_from_partner(self):
for site in self:
site._copy_address_from(site.partner_id)
for record in self:
record._copy_address_from(record.partner_id)
return True
def action_copy_address_from_contact(self):
for site in self:
site._copy_address_from(site.contact_id)
for record in self:
record._copy_address_from(record.contact_id)
return True
......
<?xml version="1.0"?>
<odoo>
<record id="customer_contact_view_form" model="ir.ui.view">
<field name="name">customer.contact.form</field>
<field name="model">customer.contact</field>
<field name="arch" type="xml">
<form>
<sheet>
<h1>
<field name="name"/>
</h1>
<group string="Contact et Adresse">
<group name="partner">
<label for="partner_id"/>
<div name="partner" class="copiable_address">
<field name="partner_id" class="copiable_field"/>
<button string="Copier adresse" class="copy_button"
name="action_copy_address_from_partner" type="object"/>
</div>
</group>
<group name="address">
<label for="street" string="Adresse"/>
<div class="o_address_format o_city_zip_department o_state_country">
<field name="street" placeholder="Rue" class="o_address_street"/>
<field name="street2" placeholder="Rue 2" class="o_address_street"/>
<field name="city" placeholder="Ville" class="o_address_city"/>
<field name="zip" placeholder="Code postal" class="o_address_zip"/>
<field name="department_id" placeholder="Département" class="o_address_department"
options="{'no_create': True, 'no_open': True}"
context="{'state_id': state_id, 'country_id': country_id}"/>
<field name="state_id" placeholder="Région" class="o_address_state"
options="{'no_create': True, 'no_open': True}"
context="{'country_id': country_id}"/>
<field name="country_id" placeholder="Pays" class="o_address_country"
options="{'no_create': True, 'no_open': True}"/>
</div>
</group>
</group>
<group string="Sites">
<field name="site_ids"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="customer_contact_action" model="ir.actions.act_window">
<field name="name">Contact</field>
<field name="res_model">customer.contact</field>
......
<?xml version="1.0"?>
<odoo>
<record id="customer_partner_view_form" model="ir.ui.view">
<field name="name">customer.partner.form</field>
<field name="model">customer.partner</field>
<field name="arch" type="xml">
<form>
<sheet>
<h1>
<field name="name"/>
</h1>
<group string="Contact et Adresse">
<group name="address">
<label for="street" string="Adresse"/>
<div class="o_address_format o_city_zip_department o_state_country">
<field name="street" placeholder="Rue" class="o_address_street"/>
<field name="street2" placeholder="Rue 2" class="o_address_street"/>
<field name="city" placeholder="Ville" class="o_address_city"/>
<field name="zip" placeholder="Code postal" class="o_address_zip"/>
<field name="department_id" placeholder="Département" class="o_address_department"
options="{'no_create': True, 'no_open': True}"
context="{'state_id': state_id, 'country_id': country_id}"/>
<field name="state_id" placeholder="Région" class="o_address_state"
options="{'no_create': True, 'no_open': True}"
context="{'country_id': country_id}"/>
<field name="country_id" placeholder="Pays" class="o_address_country"
options="{'no_create': True, 'no_open': True}"/>
</div>
</group>
</group>
<group string="Contacts">
<field name="contact_ids"/>
</group>
<group string="Sites">
<field name="site_ids"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="customer_partner_action" model="ir.actions.act_window">
<field name="name">Compte</field>
<field name="res_model">customer.partner</field>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment