Browse Source

[IMP] check travis failure

14.0
Fábio Oliveira 4 years ago
committed by Jacob Oldfield
parent
commit
9b5831446e
  1. 3
      partner_contact_in_several_companies/__init__.py
  2. 15
      partner_contact_in_several_companies/__manifest__.py
  3. 10
      partner_contact_in_several_companies/demo/res_partner.xml
  4. 25
      partner_contact_in_several_companies/models/ir_actions.py
  5. 102
      partner_contact_in_several_companies/models/res_partner.py
  6. 196
      partner_contact_in_several_companies/tests/test_partner_contact_in_several_companies.py
  7. 282
      partner_contact_in_several_companies/views/res_partner.xml

3
partner_contact_in_several_companies/__init__.py

@ -1,2 +1,3 @@
# -*- coding: utf-8 -*-
from . import models
from . import models

15
partner_contact_in_several_companies/__manifest__.py

@ -8,18 +8,9 @@
"website": "https://github.com/OCA/partner-contact",
"author": "Nicolas JEUDY, Odoo Community Association (OCA),Odoo SA",
"license": "AGPL-3",
"depends": [
"base",
"contacts",
"partner_contact_personal_information_page",
],
"data": [
"views/res_partner.xml",
],
"demo": [
"demo/res_partner.xml",
"demo/ir_actions.xml",
],
"depends": ["base", "contacts", "partner_contact_personal_information_page"],
"data": ["views/res_partner.xml"],
"demo": ["demo/res_partner.xml", "demo/ir_actions.xml"],
"application": False,
"installable": True,
"auto_install": False,

10
partner_contact_in_several_companies/demo/res_partner.xml

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="res_partner_main2_position_consultant" model="res.partner">
<field name="name">Roger Scott</field>
<field name="function">Consultant</field>
<field name="parent_id" ref="base.res_partner_4"/>
<field name="contact_id" ref="base.res_partner_main2"/>
<field name="parent_id" ref="base.res_partner_4" />
<field name="contact_id" ref="base.res_partner_main2" />
</record>
<record id="res_partner_contact1" model="res.partner">
@ -16,7 +16,7 @@
<field name="name">Bob Egnops</field>
<field name="function">Technician</field>
<field name="email">bob@yourcompany.com</field>
<field name="parent_id" ref="base.main_partner"/>
<field name="contact_id" ref="res_partner_contact1"/>
<field name="parent_id" ref="base.main_partner" />
<field name="contact_id" ref="res_partner_contact1" />
</record>
</odoo>

25
partner_contact_in_several_companies/models/ir_actions.py

@ -1,21 +1,24 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import api, models
from odoo import models
class IRActionsWindow(models.Model):
_inherit = 'ir.actions.act_window'
_inherit = "ir.actions.act_window"
def read(self, fields=None, context=None, load='_classic_read'):
def read(self, fields=None, context=None, load="_classic_read"):
actions = super(IRActionsWindow, self).read(fields=fields, load=load)
for action in actions:
if action.get('res_model', '') == 'res.partner':
if action.get("res_model", "") == "res.partner":
# By default, only show standalone contact
action_context = action.get('context', '{}')
if 'search_show_all_positions' not in action_context:
action['context'] = action_context.replace(
'{',
("{'search_show_all_positions': "
"{'is_set': True, 'set_value': False},"),
1)
action_context = action.get("context", "{}")
if "search_show_all_positions" not in action_context:
action["context"] = action_context.replace(
"{",
(
"{'search_show_all_positions': "
"{'is_set': True, 'set_value': False},"
),
1,
)
return actions

102
partner_contact_in_several_companies/models/res_partner.py

@ -5,45 +5,41 @@ from odoo.osv import expression
class ResPartner(models.Model):
_inherit = 'res.partner'
_inherit = "res.partner"
contact_type = fields.Selection(
[('standalone', 'Standalone Contact'),
('attached', 'Attached to existing Contact'),
],
compute='_compute_contact_type',
[
("standalone", "Standalone Contact"),
("attached", "Attached to existing Contact"),
],
compute="_compute_contact_type",
store=True,
index=True,
default='standalone')
default="standalone")
contact_id = fields.Many2one(
'res.partner',
string='Main Contact',
domain=[('is_company', '=', False),
('contact_type', '=', 'standalone'),
],
"res.partner",
string="Main Contact",
domain=[("is_company", "=", False), ("contact_type", "=", "standalone"), ],
)
other_contact_ids = fields.One2many(
'res.partner', 'contact_id',
string='Others Positions',
"res.partner", "contact_id", string="Others Positions",
)
@api.depends('contact_id')
@api.depends("contact_id")
def _compute_contact_type(self):
for rec in self:
rec.contact_type = 'attached' if rec.contact_id else 'standalone'
rec.contact_type = "attached" if rec.contact_id else "standalone"
def _basecontact_check_context(self, mode):
""" Remove 'search_show_all_positions' for non-search mode.
""" Remove "search_show_all_positions" for non-search mode.
Keeping it in context can result in unexpected behaviour (ex: reading
one2many might return wrong result - i.e with "attached contact"
removed even if it's directly linked to a company).
removed even if it"s directly linked to a company).
Actually, is easier to override a dictionary value to indicate it
should be ignored...
"""
if (mode != 'search' and
'search_show_all_positions' in self.env.context):
result = self.with_context(
search_show_all_positions={'is_set': False})
if mode != "search" and "search_show_all_positions" in self.env.context:
result = self.with_context(search_show_all_positions={"is_set": False})
else:
result = self
return result
@ -53,21 +49,24 @@ class ResPartner(models.Model):
""" Display only standalone contact matching ``args`` or having
attached contact matching ``args`` """
ctx = self.env.context
if (ctx.get('search_show_all_positions', {}).get('is_set') and
not ctx['search_show_all_positions']['set_value']):
if (
ctx.get("search_show_all_positions", {}).get("is_set")
and not ctx["search_show_all_positions"]["set_value"]
):
args = expression.normalize_domain(args)
attached_contact_args = expression.AND(
(args, [('contact_type', '=', 'attached')])
(args, [("contact_type", "=", "attached")])
)
attached_contacts = super(ResPartner, self).search(
attached_contact_args)
args = expression.OR((expression.AND((
[('contact_type', '=', 'standalone')], args)),
[('other_contact_ids', 'in', attached_contacts.ids)],
))
return super(ResPartner, self).search(args, offset=offset,
limit=limit, order=order,
count=count)
attached_contacts = super(ResPartner, self).search(attached_contact_args)
args = expression.OR(
(
expression.AND(([("contact_type", "=", "standalone")], args)),
[("other_contact_ids", "in", attached_contacts.ids)],
)
)
return super(ResPartner, self).search(
args, offset=offset, limit=limit, order=order, count=count
)
@api.model
def create(self, vals):
@ -75,21 +74,21 @@ class ResPartner(models.Model):
comment in _basecontact_check_context). Also, we need to ensure
that the name on an attached contact is the same as the name on the
contact it is attached to."""
modified_self = self._basecontact_check_context('create')
if not vals.get('name') and vals.get('contact_id'):
vals['name'] = modified_self.browse(vals['contact_id']).name
modified_self = self._basecontact_check_context("create")
if not vals.get("name") and vals.get("contact_id"):
vals["name"] = modified_self.browse(vals["contact_id"]).name
return super(ResPartner, modified_self).create(vals)
def read(self, fields=None, load='_classic_read'):
modified_self = self._basecontact_check_context('read')
def read(self, fields=None, load="_classic_read"):
modified_self = self._basecontact_check_context("read")
return super(ResPartner, modified_self).read(fields=fields, load=load)
def write(self, vals):
modified_self = self._basecontact_check_context('write')
modified_self = self._basecontact_check_context("write")
return super(ResPartner, modified_self).write(vals)
def unlink(self):
modified_self = self._basecontact_check_context('unlink')
modified_self = self._basecontact_check_context("unlink")
return super(ResPartner, modified_self).unlink()
def _compute_commercial_partner(self):
@ -98,14 +97,14 @@ class ResPartner(models.Model):
for all commercial fields (see :py:meth:`~_commercial_fields`) """
result = super(ResPartner, self)._compute_commercial_partner()
for partner in self:
if partner.contact_type == 'attached' and not partner.parent_id:
if partner.contact_type == "attached" and not partner.parent_id:
partner.commercial_partner_id = partner.contact_id
return result
def _contact_fields(self):
""" Returns the list of contact fields that are synced from the parent
when a partner is attached to him. """
return ['name', 'title']
return ["name", "title"]
def _contact_sync_from_parent(self):
""" Handle sync of contact fields when a new parent contact entity
@ -118,12 +117,12 @@ class ResPartner(models.Model):
self.write(sync_vals)
def update_contact(self, vals):
if self.env.context.get('__update_contact_lock'):
if self.env.context.get("__update_contact_lock"):
return
contact_fields = self._contact_fields()
contact_vals = dict(
(field, vals[field]) for field in contact_fields if field in vals
)
contact_vals = {
field: vals[field] for field in contact_fields if field in vals
}
if contact_vals:
self.with_context(__update_contact_lock=True).write(contact_vals)
@ -137,22 +136,21 @@ class ResPartner(models.Model):
super(ResPartner, self)._fields_sync(update_values)
contact_fields = self._contact_fields()
# 1. From UPSTREAM: sync from parent contact
if update_values.get('contact_id'):
if update_values.get("contact_id"):
self._contact_sync_from_parent()
# 2. To DOWNSTREAM: sync contact fields to parent or related
elif any(field in contact_fields for field in update_values):
update_ids = self.other_contact_ids.filtered(
lambda p: not p.is_company)
update_ids = self.other_contact_ids.filtered(lambda p: not p.is_company)
if self.contact_id:
update_ids |= self.contact_id
update_ids.update_contact(update_values)
@api.onchange('contact_id')
@api.onchange("contact_id")
def _onchange_contact_id(self):
if self.contact_id:
self.name = self.contact_id.name
@api.onchange('contact_type')
@api.onchange("contact_type")
def _onchange_contact_type(self):
if self.contact_type == 'standalone':
if self.contact_type == "standalone":
self.contact_id = False

196
partner_contact_in_several_companies/tests/test_partner_contact_in_several_companies.py

@ -7,26 +7,21 @@ class PartnerContactInSeveralCompaniesCase(common.TransactionCase):
def setUp(self):
"""*****setUp*****"""
super(PartnerContactInSeveralCompaniesCase, self).setUp()
self.partner = self.env['res.partner']
self.action = self.env['ir.actions.act_window']
current_module = 'partner_contact_in_several_companies'
self.partner = self.env["res.partner"]
self.action = self.env["ir.actions.act_window"]
current_module = "partner_contact_in_several_companies"
# Get test records reference
self.main_partner = self.env.ref('base.main_partner')
self.bob_contact = self.env.ref(
'%s.res_partner_contact1' % current_module)
self.bob_job1 = self.env.ref(
'%s.res_partner_contact1_work_position1' % current_module)
self.roger_contact = self.env.ref('base.res_partner_main2')
self.roger_job2 = self.env.ref(
'%s.res_partner_main2_position_consultant' % current_module)
self.main_partner = self.env.ref("base.main_partner")
self.bob_contact = self.env.ref("%s.res_partner_contact1" % current_module)
self.bob_job1 = self.env.ref("%s.res_partner_contact1_work_position1" % current_module)
self.roger_contact = self.env.ref("base.res_partner_main2")
self.roger_job2 = self.env.ref("%s.res_partner_main2_position_consultant" % current_module)
def test_00_show_only_standalone_contact(self):
"""Check that only standalone contact are shown if context
explicitly state to not display all positions
"""
ctx = {'search_show_all_positions': {'is_set': True,
'set_value': False
}}
ctx = {"search_show_all_positions": {"is_set": True, "set_value": False}}
partner_ids = self.partner.with_context(ctx).search([])
self.assertTrue(self.bob_job1 not in partner_ids)
self.assertTrue(self.roger_job2 not in partner_ids)
@ -41,14 +36,12 @@ class PartnerContactInSeveralCompaniesCase(common.TransactionCase):
self.assertTrue(self.bob_job1 in partner_ids)
self.assertTrue(self.roger_job2 in partner_ids)
ctx = {'search_show_all_positions': {'is_set': False}}
ctx = {"search_show_all_positions": {"is_set": False}}
partner_ids = self.partner.with_context(ctx).search([])
self.assertTrue(self.bob_job1 in partner_ids)
self.assertTrue(self.roger_job2 in partner_ids)
ctx = {'search_show_all_positions': {'is_set': True,
'set_value': True
}}
ctx = {"search_show_all_positions": {"is_set": True, "set_value": True}}
partner_ids = self.partner.with_context(ctx).search([])
self.assertTrue(self.bob_job1 in partner_ids)
self.assertTrue(self.roger_job2 in partner_ids)
@ -59,49 +52,22 @@ class PartnerContactInSeveralCompaniesCase(common.TransactionCase):
"""
ctx = {}
self.assertEqual(
self.bob_job1, self.bob_contact.with_context(ctx).other_contact_ids
)
ctx = {'search_show_all_positions': {'is_set': False}}
self.assertEqual(
self.bob_job1, self.bob_contact.with_context(ctx).other_contact_ids
)
ctx = {'search_show_all_positions': {'is_set': True,
'set_value': False,
}}
self.assertEqual(
self.bob_job1, self.bob_contact.with_context(ctx).other_contact_ids
)
ctx = {'search_show_all_positions': {'is_set': True,
'set_value': True,
}}
self.assertEqual(
self.bob_job1, self.bob_contact.with_context(ctx).other_contact_ids
)
self.assertEqual(self.bob_job1, self.bob_contact.with_context(ctx).other_contact_ids)
ctx = {"search_show_all_positions": {"is_set": False}}
self.assertEqual(self.bob_job1, self.bob_contact.with_context(ctx).other_contact_ids)
ctx = {"search_show_all_positions": {"is_set": True, "set_value": False}}
self.assertEqual(self.bob_job1, self.bob_contact.with_context(ctx).other_contact_ids)
ctx = {"search_show_all_positions": {"is_set": True, "set_value": True}}
self.assertEqual(self.bob_job1, self.bob_contact.with_context(ctx).other_contact_ids)
ctx = {}
self.assertIn(
self.bob_job1,
self.main_partner.with_context(ctx).child_ids)
ctx = {'search_show_all_positions': {'is_set': False}}
self.assertIn(
self.bob_job1,
self.main_partner.with_context(ctx).child_ids)
ctx = {'search_show_all_positions': {'is_set': True,
'set_value': False,
}}
self.assertIn(
self.bob_job1,
self.main_partner.with_context(ctx).child_ids)
ctx = {'search_show_all_positions': {'is_set': True,
'set_value': True,
}}
self.assertIn(
self.bob_job1,
self.main_partner.with_context(ctx).child_ids)
self.assertIn(self.bob_job1, self.main_partner.with_context(ctx).child_ids)
ctx = {"search_show_all_positions": {"is_set": False}}
self.assertIn(self.bob_job1, self.main_partner.with_context(ctx).child_ids)
ctx = {"search_show_all_positions": {"is_set": True, "set_value": False}}
self.assertIn(self.bob_job1, self.main_partner.with_context(ctx).child_ids)
ctx = {"search_show_all_positions": {"is_set": True, "set_value": True}}
self.assertIn(self.bob_job1, self.main_partner.with_context(ctx).child_ids)
def test_03_search_match_attached_contacts(self):
"""Check that searching partner also return partners having
@ -111,62 +77,42 @@ class PartnerContactInSeveralCompaniesCase(common.TransactionCase):
# 'YourCompany'
# so search for all contacts working for 'YourCompany'
# should contain Bob position.
partner_ids = self.partner.search(
[('parent_id', 'ilike', 'YourCompany')])
partner_ids = self.partner.search([("parent_id", "ilike", "YourCompany")])
self.assertTrue(self.bob_job1 in partner_ids)
# but when searching without 'all positions',
# we should get the position standalone contact instead.
ctx = {'search_show_all_positions': {'is_set': True,
'set_value': False,
}}
partner_ids = self.partner.with_context(ctx).search(
[('parent_id', 'ilike', 'YourCompany')])
ctx = {"search_show_all_positions": {"is_set": True, "set_value": False}}
partner_ids = self.partner.with_context(ctx).search([("parent_id", "ilike", "YourCompany")])
self.assertTrue(self.bob_contact in partner_ids)
def test_04_contact_creation(self):
"""Check that we're begin to create a contact"""
# Create a contact using only name
new_contact = self.partner.create({'name': 'Bob Egnops'})
self.assertEqual(
new_contact.contact_type,
'standalone',
)
new_contact = self.partner.create({"name": "Bob Egnops"})
self.assertEqual(new_contact.contact_type, "standalone")
# Create a contact with only contact_id
new_contact = self.partner.create(
{'contact_id': self.bob_contact.id}
)
self.assertEqual(new_contact.name, 'Bob Egnops')
self.assertEqual(new_contact.contact_type, 'attached')
new_contact = self.partner.create({"contact_id": self.bob_contact.id})
self.assertEqual(new_contact.name, "Bob Egnops")
self.assertEqual(new_contact.contact_type, "attached")
# Create a contact with both contact_id and name;
# contact's name should override provided value in that case
new_contact = self.partner.create(
{'contact_id': self.bob_contact.id, 'name': 'Rob Egnops'}
)
self.assertEqual(
new_contact.name,
'Bob Egnops'
)
new_contact = self.partner.create({"contact_id": self.bob_contact.id, "name": "Rob Egnops"})
self.assertEqual(new_contact.name, "Bob Egnops")
# Reset contact to standalone
new_contact.write({'contact_id': False})
self.assertEqual(
new_contact.contact_type,
'standalone',
)
new_contact.write({"contact_id": False})
self.assertEqual(new_contact.contact_type, "standalone",)
# Reset contact to attached, and ensure only it is unlinked (i.e.
# context is ignored).
new_contact.write({'contact_id': self.bob_contact.id})
ctx = {'search_show_all_positions': {'is_set': True,
'set_value': True
}}
new_contact.write({"contact_id": self.bob_contact.id})
ctx = {"search_show_all_positions": {"is_set": True, "set_value": True}}
new_contact.with_context(ctx).unlink()
partner_ids = self.partner.with_context(ctx).search(
[('id', 'in', [new_contact.id, self.bob_contact.id])])
partner_ids = self.partner.with_context(ctx).search([("id", "in", [new_contact.id, self.bob_contact.id])])
self.assertIn(self.bob_contact, partner_ids)
self.assertNotIn(new_contact, partner_ids)
@ -176,72 +122,62 @@ class PartnerContactInSeveralCompaniesCase(common.TransactionCase):
"""
# Test DOWNSTREAM sync
self.bob_contact.write(
{'name': 'Rob Egnops'}
)
self.assertEqual(
self.bob_job1.name,
'Rob Egnops',
)
self.bob_contact.write({"name": "Rob Egnops"})
self.assertEqual(self.bob_job1.name, "Rob Egnops",)
# Test UPSTREAM sync
self.bob_job1.write({'name': 'Bob Egnops'})
self.assertEqual(
self.bob_contact.name,
'Bob Egnops',
)
self.bob_job1.write({"name": "Bob Egnops"})
self.assertEqual(self.bob_contact.name, "Bob Egnops",)
def test_06_ir_action(self):
"""Check ir_action context is auto updated.
"""
new_context_val = "'search_show_all_positions': " \
"{'is_set': True, 'set_value': False}"
details = self.env['ir.actions.act_window'].for_xml_id(
'base',
'action_partner_form')
new_context_val = (
"'search_show_all_positions': " "{'is_set': True, 'set_value': False}"
)
details = self.env["ir.actions.act_window"].for_xml_id(
"base", "action_partner_form"
)
self.assertIn(
new_context_val,
details['context'],
msg='Default actions not updated with new context'
details["context"],
msg="Default actions not updated with new context"
)
details = self.env['ir.actions.act_window'].for_xml_id(
'partner_contact_in_several_companies',
'action_partner_form')
details = self.env["ir.actions.act_window"].for_xml_id(
"partner_contact_in_several_companies", "action_partner_form"
)
self.assertNotIn(
new_context_val,
details['context'],
msg='Custom actions incorrectly updated with new context'
details["context"],
msg="Custom actions incorrectly updated with new context"
)
def test_07_onchange(self):
"""Check onchange method
"""
new_contact = self.partner.create({'name': 'Bob before onchange'})
new_contact.write({'contact_id': self.bob_contact.id})
new_contact = self.partner.create({"name": "Bob before onchange"})
new_contact.write({"contact_id": self.bob_contact.id})
new_contact._onchange_contact_id()
self.assertEqual(
new_contact.name,
'Bob Egnops',
new_contact.name, "Bob Egnops"
)
new_contact.write({'contact_type': 'standalone'})
new_contact.write({"contact_type": "standalone"})
new_contact._onchange_contact_type()
self.assertEqual(
new_contact.contact_id,
self.partner,
new_contact.contact_id, self.partner
)
def test_08_commercial_partner_compute(self):
new_contact = self.partner.create({'name': 'Bob before onchange'})
new_contact.write({'contact_id': self.bob_contact.id,
'parent_id': False})
new_contact = self.partner.create({"name": "Bob before onchange"})
new_contact.write({"contact_id": self.bob_contact.id, "parent_id": False})
new_contact._compute_commercial_partner()
self.assertEqual(
new_contact.commercial_partner_id,
self.bob_contact,
new_contact.commercial_partner_id, self.bob_contact,
)

282
partner_contact_in_several_companies/views/res_partner.xml

@ -3,16 +3,23 @@
<record id="view_res_partner_filter_contact" model="ir.ui.view">
<field name="name">res.partner.select.contact</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_res_partner_filter"/>
<field name="inherit_id" ref="base.view_res_partner_filter" />
<field name="arch" type="xml">
<filter name="type_company" position="after">
<separator/>
<filter string="All positions" name="type_otherpositions"
context="{'search_show_all_positions': {'is_set': True, 'set_value': True}}"
help="All partner positions"/>
<separator />
<filter
string="All positions"
name="type_otherpositions"
context="{'search_show_all_positions': {'is_set': True, 'set_value': True}}"
help="All partner positions"
/>
</filter>
<xpath expr="/search/group[@name='group_by']" position="inside">
<filter string="Person" name="group_person" context="{'group_by': 'contact_id'}"/>
<filter
string="Person"
name="group_person"
context="{'group_by': 'contact_id'}"
/>
</xpath>
</field>
</record>
@ -20,10 +27,10 @@
<record id="view_res_partner_tree_contact" model="ir.ui.view">
<field name="name">res.partner.tree.contact</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_tree"/>
<field name="inherit_id" ref="base.view_partner_tree" />
<field name="arch" type="xml">
<field name="parent_id" position="after">
<field name="contact_id" invisible="1"/>
<field name="contact_id" invisible="1" />
</field>
</field>
</record>
@ -31,74 +38,107 @@
<record model="ir.ui.view" id="view_partner_form_inherit">
<field name="name">res.partner.form.contact</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="inherit_id" ref="base.view_partner_form" />
<field name="type">form</field>
<field name="arch" type="xml">
<field name="parent_id" position="after">
<field name="contact_id" invisible="1"/>
<field name="contact_id" invisible="1" />
</field>
<xpath expr="//field[@name='child_ids']/form//field[@name='name']" position="before">
<xpath
expr="//field[@name='child_ids']/form//field[@name='name']"
position="before"
>
<field name='contact_type' readonly='0'/>
<field name="contact_id" string="Contact"
attrs="{'invisible': [('contact_type','!=','attached')], 'required': [('contact_type','=','attached')]}"/>
<field name="contact_id"
string="Contact"
attrs="{'invisible': [('contact_type','!=','attached')], 'required': [('contact_type','=','attached')]}"
/>
</xpath>
<xpath expr="//field[@name='child_ids']/form//field[@name='name']" position="attributes">
<xpath
expr="//field[@name='child_ids']/form//field[@name='name']"
position="attributes"
>
<attribute name="attrs">{'invisible': [('contact_type','=','attached')]}</attribute>
</xpath>
<field name="is_company" position="after">
<field name="contact_type" invisible="1"/>
<field name="contact_type" invisible="1" />
</field>
<page name='internal_notes' position="before">
<page name="other_position" string="Other Positions"
attrs="{'invisible': ['|',('is_company','=',True),('contact_id','!=',False)]}">
<field name="other_contact_ids"
context="{'default_contact_id': active_id, 'default_name': name, 'default_street': street, 'default_street2': street2, 'default_city': city, 'default_state_id': state_id, 'default_zip': zip, 'default_country_id': country_id}"
mode="kanban">
<page
name="other_position"
string="Other Positions"
attrs="{'invisible': ['|',('is_company','=',True),('contact_id','!=',False)]}"
>
<field
name="other_contact_ids"
context="{'default_contact_id': active_id, 'default_name': name, 'default_street': street, 'default_street2': street2, 'default_city': city, 'default_state_id': state_id, 'default_zip': zip, 'default_country_id': country_id}"
mode="kanban"
>
<kanban create="false">
<field name="color"/>
<field name="name"/>
<field name="title"/>
<field name="email"/>
<field name="parent_id"/>
<field name="is_company"/>
<field name="function"/>
<field name="phone"/>
<field name="street"/>
<field name="street2"/>
<field name="zip"/>
<field name="city"/>
<field name="country_id"/>
<field name="mobile"/>
<field name="state_id"/>
<field name="image_128"/>
<field name="lang"/>
<field name="color" />
<field name="name" />
<field name="title" />
<field name="email" />
<field name="parent_id" />
<field name="is_company" />
<field name="function" />
<field name="phone" />
<field name="street" />
<field name="street2" />
<field name="zip" />
<field name="city" />
<field name="country_id" />
<field name="mobile" />
<field name="state_id" />
<field name="image_128" />
<field name="lang" />
<templates>
<t t-name="kanban-box">
<t t-set="color" t-value="kanban_color(record.color.raw_value)"/>
<div t-att-class="color + (record.title.raw_value == 1 ? ' oe_kanban_color_alert' : '') + ' oe_kanban_global_click'">
<a t-if="!read_only_mode" type="delete" class="fa fa-times pull-right"/>
<t
t-set="color"
t-value="kanban_color(record.color.raw_value)"
/>
<div
t-att-class="color + (record.title.raw_value == 1 ? ' oe_kanban_color_alert' : '') + ' oe_kanban_global_click'"
>
<a
t-if="!read_only_mode"
type="delete"
class="fa fa-times pull-right"
/>
<div class="o_kanban_image">
<img t-if="record.image_128.raw_value" t-att-src="'data:image/png;base64,' + record.image_128.raw_value"/>
<img
t-if="record.image_128.raw_value"
t-att-src="'data:image/png;base64,' + record.image_128.raw_value"
/>
<t t-if="!record.image_128.raw_value">
<img alt="Logo" t-if="record.is_company.raw_value === true" t-att-src='_s + "/base/static/img/company_image.png"'/>
<img alt="Avatar" t-if="record.is_company.raw_value === false" t-att-src='_s + "/base/static/img/avatar_grey.png"'/>
<img
alt="Logo"
t-if="record.is_company.raw_value === true"
t-att-src='_s + "/base/static/img/company_image.png"'
/>
<img
alt="Avatar"
t-if="record.is_company.raw_value === false"
t-att-src='_s + "/base/static/img/avatar_grey.png"'
/>
</t>
</div>
<div class="oe_kanban_details">
<field name="name"/>
<field name="name" />
<div t-if="record.function.raw_value">
<field name="function"/>
<field name="function" />
at
<field name="parent_id"/>
<field name="parent_id" />
</div>
<div t-if="record.email.raw_value">
<field name="email"/>
<field name="email" />
</div>
<div t-if="record.phone.raw_value">Phone:
<field name="phone"/>
<field name="phone" />
</div>
<div t-if="record.mobile.raw_value">Mobile:
<field name="mobile"/>
<field name="mobile" />
</div>
</div>
</div>
@ -107,40 +147,82 @@
</kanban>
<form string="Contact">
<sheet>
<field name="type" required="1" widget="radio" options="{'horizontal': true}"/>
<hr/>
<field
name="type"
required="1"
widget="radio"
options="{'horizontal': true}"
/>
<hr />
<group>
<group attrs="{'invisible': [('type','=', 'contact')]}">
<label for="street" string="Address"/>
<group
attrs="{'invisible': [('type','=', 'contact')]}"
>
<label for="street" string="Address" />
<div>
<div class="o_address_format" name="div_address">
<field name="street" placeholder="Street..." class="o_address_street"/>
<field name="street2" placeholder="Street 2..."
class="o_address_street"/>
<field name="city" placeholder="City" class="o_address_city"/>
<field name="state_id" class="o_address_state" placeholder="State"
options='{"no_open": True}'
context="{'country_id': country_id, 'zip': zip}"/>
<field name="zip" placeholder="ZIP" class="o_address_zip"/>
<field name="country_id" placeholder="Country" class="o_address_country"
options='{"no_open": True, "no_create": True}'/>
<div
class="o_address_format"
name="div_address"
>
<field
name="street"
placeholder="Street..."
class="o_address_street"
/>
<field
name="street2"
placeholder="Street 2..."
class="o_address_street"
/>
<field
name="city"
placeholder="City"
class="o_address_city"
/>
<field
name="state_id"
class="o_address_state"
placeholder="State"
options='{"no_open": True}'
context="{'country_id': country_id, 'zip': zip}"
/>
<field
name="zip"
placeholder="ZIP"
class="o_address_zip"
/>
<field
name="country_id"
placeholder="Country"
class="o_address_country"
options='{"no_open": True, "no_create": True}'
/>
</div>
</div>
</group>
<group>
<field name="name" string="Contact Name"
attrs="{'required' : [('type', '=', 'contact')]}"/>
<field name="title" placeholder="e.g. Mr."
attrs="{'invisible': [('type','&lt;&gt;', 'contact')]}"/>
<field name="function" placeholder="e.g. Sales Director"
attrs="{'invisible': [('type','&lt;&gt;', 'contact')]}"/>
<field name="email"/>
<field name="phone" widget="phone"/>
<field name="mobile" widget="phone"/>
<field name="comment" placeholder="internal note..."/>
<field
name="name"
string="Contact Name"
attrs="{'required' : [('type', '=', 'contact')]}"
/>
<field
name="title"
placeholder="e.g. Mr."
attrs="{'invisible': [('type','&lt;&gt;', 'contact')]}"
/>
<field
name="function"
placeholder="e.g. Sales Director"
attrs="{'invisible': [('type','&lt;&gt;', 'contact')]}"
/>
<field name="email" />
<field name="phone" widget="phone" />
<field name="mobile" widget="phone" />
<field name="comment" placeholder="internal note..." />
</group>
</group>
<field name="lang" invisible="True"/>
<field name="lang" invisible="True" />
</sheet>
</form>
</field>
@ -152,21 +234,30 @@
<record id="personal_contact_information" model="ir.ui.view">
<field name="name">Contacts in several partners: personal info</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="partner_contact_personal_information_page.personal_information"/>
<field name="inherit_id" ref="partner_contact_personal_information_page.personal_information" />
<field name="arch" type="xml">
<xpath expr="//page[@name='personal_information_page']/group[@name='personal_information_group']"
position='attributes'>
<attribute name='attrs'>{'invisible': [('contact_id','!=',False)]}</attribute>
<xpath
expr="//page[@name='personal_information_page']/group[@name='personal_information_group']"
position='attributes'
>
<attribute
name='attrs'
>{'invisible': [('contact_id','!=',False)]}</attribute>
</xpath>
<xpath expr="//page[@name='personal_information_page']/group[@name='personal_information_group']"
position='after'>
<xpath
expr="//page[@name='personal_information_page']/group[@name='personal_information_group']"
position='after'
>
<p attrs="{'invisible': [('contact_id','=',False)]}">
To see personal information about this contact, please
go to to the this person form:
<field name="contact_id" class="oe_inline"
domain="[('contact_type','!=','attached')]"
context="{'show_address': 1}"
options="{'always_reload': True}"/>
<field
name="contact_id"
class="oe_inline"
domain="[('contact_type','!=','attached')]"
context="{'show_address': 1}"
options="{'always_reload': True}"
/>
</p>
</xpath>
</field>
@ -175,22 +266,29 @@
<record model="ir.ui.view" id="view_res_partner_kanban_contact">
<field name="name">res.partner.kanban.contact</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.res_partner_kanban_view"/>
<field name="inherit_id" ref="base.res_partner_kanban_view" />
<field name="arch" type="xml">
<field name="is_company" position="after">
<field name="other_contact_ids">
<tree>
<field name="parent_id"/>
<field name="function"/>
<field name="parent_id" />
<field name="function" />
</tree>
</field>
</field>
<xpath expr="//t[@t-name='kanban-box']//div[hasclass('oe_kanban_details')]/ul/li[3]" position="after">
<xpath
expr="//t[@t-name='kanban-box']//div[hasclass('oe_kanban_details')]/ul/li[3]"
position="after"
>
<t t-if="record.other_contact_ids.raw_value.length &gt; 0">
<li>+
<t t-esc="record.other_contact_ids.raw_value.length"/>
<t t-if="record.other_contact_ids.raw_value.length == 1">other position</t>
<t t-if="record.other_contact_ids.raw_value.length &gt; 1">other positions</t>
<t t-esc="record.other_contact_ids.raw_value.length" />
<t
t-if="record.other_contact_ids.raw_value.length == 1"
>other position</t>
<t
t-if="record.other_contact_ids.raw_value.length &gt; 1"
>other positions</t>
</li>
</t>
</xpath>

Loading…
Cancel
Save