Merge lp:~savoirfairelinux-openerp/openobject-addons/base_contact into lp:openobject-addons/7.0
- base_contact
- Merge into 7.0
Proposed by
El Hadji Dem (http://www.savoirfairelinux.com)
Status: | Needs review |
---|---|
Proposed branch: | lp:~savoirfairelinux-openerp/openobject-addons/base_contact |
Merge into: | lp:openobject-addons/7.0 |
Diff against target: |
1079 lines (+1030/-0) 9 files modified
base_contact/__init__.py (+22/-0) base_contact/__openerp__.py (+52/-0) base_contact/base_contact.py (+193/-0) base_contact/base_contact_demo.xml (+29/-0) base_contact/base_contact_view.xml (+202/-0) base_contact/i18n/base_contact.pot (+184/-0) base_contact/i18n/fr.po (+186/-0) base_contact/tests/__init__.py (+26/-0) base_contact/tests/test_base_contact.py (+136/-0) |
To merge this branch: | bzr merge lp:~savoirfairelinux-openerp/openobject-addons/base_contact |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
OpenERP Core Team | Pending | ||
Review via email: mp+198634@code.launchpad.net |
Commit message
Description of the change
[ADD] add base_contact and pep8
To post a comment you must log in.
Unmerged revisions
- 9539. By El Hadji Dem (http://www.savoirfairelinux.com)
-
[IMP] pep8, add i18n files
- 9538. By El Hadji Dem (http://www.savoirfairelinux.com)
-
[ADD] add base_contact_
by_functions module - 9537. By Xavier ALT
-
[IMP] base_contact: add contact fields (name + title) sync between partner attached to the same contact
- 9536. By Xavier ALT
-
[FIX] base_contact: missing .name
- 9535. By Xavier ALT
-
[FIX] base_contact: fix contact staying attached after settings it's type to standalone
- 9534. By Xavier ALT
-
[+] base_contact module
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory 'base_contact' |
2 | === added file 'base_contact/__init__.py' |
3 | --- base_contact/__init__.py 1970-01-01 00:00:00 +0000 |
4 | +++ base_contact/__init__.py 2013-12-11 19:37:11 +0000 |
5 | @@ -0,0 +1,22 @@ |
6 | +# -*- coding: utf-8 -*- |
7 | +############################################################################## |
8 | +# |
9 | +# OpenERP, Open Source Management Solution |
10 | +# Copyright (C) 2013-TODAY OpenERP SA (<http://www.openerp.com>). |
11 | +# |
12 | +# This program is free software: you can redistribute it and/or modify |
13 | +# it under the terms of the GNU Affero General Public License as |
14 | +# published by the Free Software Foundation, either version 3 of the |
15 | +# License, or (at your option) any later version. |
16 | +# |
17 | +# This program is distributed in the hope that it will be useful, |
18 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
20 | +# GNU Affero General Public License for more details. |
21 | +# |
22 | +# You should have received a copy of the GNU Affero General Public License |
23 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
24 | +# |
25 | +############################################################################## |
26 | + |
27 | +import base_contact |
28 | |
29 | === added file 'base_contact/__openerp__.py' |
30 | --- base_contact/__openerp__.py 1970-01-01 00:00:00 +0000 |
31 | +++ base_contact/__openerp__.py 2013-12-11 19:37:11 +0000 |
32 | @@ -0,0 +1,52 @@ |
33 | +# -*- coding: utf-8 -*- |
34 | +############################################################################## |
35 | +# |
36 | +# OpenERP, Open Source Business Applications |
37 | +# Copyright (C) 2013-TODAY OpenERP S.A. (<http://openerp.com>). |
38 | +# |
39 | +# This program is free software: you can redistribute it and/or modify |
40 | +# it under the terms of the GNU Affero General Public License as |
41 | +# published by the Free Software Foundation, either version 3 of the |
42 | +# License, or (at your option) any later version. |
43 | +# |
44 | +# This program is distributed in the hope that it will be useful, |
45 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
46 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
47 | +# GNU Affero General Public License for more details. |
48 | +# |
49 | +# You should have received a copy of the GNU Affero General Public License |
50 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
51 | +# |
52 | +############################################################################## |
53 | + |
54 | +{ |
55 | + 'name': 'Contacts Management', |
56 | + 'version': '1.0', |
57 | + 'category': 'Customer Relationship Management', |
58 | + 'complexity': "expert", |
59 | + 'description': """ |
60 | +This module allows you to manage your contacts |
61 | +============================================== |
62 | + |
63 | +It lets you define groups of contacts sharing some common information, like: |
64 | + * Birthdate |
65 | + * Nationality |
66 | + * Native Language |
67 | + |
68 | + """, |
69 | + 'author': 'OpenERP SA', |
70 | + 'website': 'http://www.openerp.com', |
71 | + 'depends': ['base', 'process', 'contacts'], |
72 | + 'init_xml': [], |
73 | + 'update_xml': [ |
74 | + 'base_contact_view.xml', |
75 | + ], |
76 | + 'demo_xml': [ |
77 | + 'base_contact_demo.xml', |
78 | + ], |
79 | + 'installable': True, |
80 | + 'auto_install': False, |
81 | + #'certificate': '0031287885469', |
82 | + 'images': [], |
83 | +} |
84 | +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
85 | |
86 | === added file 'base_contact/base_contact.py' |
87 | --- base_contact/base_contact.py 1970-01-01 00:00:00 +0000 |
88 | +++ base_contact/base_contact.py 2013-12-11 19:37:11 +0000 |
89 | @@ -0,0 +1,193 @@ |
90 | +# -*- coding: utf-8 -*- |
91 | +############################################################################## |
92 | +# |
93 | +# OpenERP, Open Source Management Solution |
94 | +# Copyright (C) 2013-TODAY OpenERP SA (<http://www.openerp.com>). |
95 | +# |
96 | +# This program is free software: you can redistribute it and/or modify |
97 | +# it under the terms of the GNU Affero General Public License as |
98 | +# published by the Free Software Foundation, either version 3 of the |
99 | +# License, or (at your option) any later version. |
100 | +# |
101 | +# This program is distributed in the hope that it will be useful, |
102 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
103 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
104 | +# GNU Affero General Public License for more details. |
105 | +# |
106 | +# You should have received a copy of the GNU Affero General Public License |
107 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
108 | +# |
109 | +############################################################################## |
110 | + |
111 | +from openerp.osv import fields, osv, expression |
112 | + |
113 | + |
114 | +class res_partner(osv.osv): |
115 | + _inherit = 'res.partner' |
116 | + |
117 | + _contact_type = [ |
118 | + ('standalone', 'Standalone Contact'), |
119 | + ('attached', 'Attached to existing Contact'), |
120 | + ] |
121 | + |
122 | + def _get_contact_type(self, cr, uid, ids, field_name, args, context=None): |
123 | + result = dict.fromkeys(ids, 'standalone') |
124 | + for partner in self.browse(cr, uid, ids, context=context): |
125 | + if partner.contact_id: |
126 | + result[partner.id] = 'attached' |
127 | + return result |
128 | + |
129 | + _columns = { |
130 | + 'contact_type': fields.function(_get_contact_type, type='selection', |
131 | + selection=_contact_type, |
132 | + string='Contact Type', |
133 | + required=True, |
134 | + select=1, |
135 | + store=True), |
136 | + 'contact_id': fields.many2one('res.partner', 'Main Contact', |
137 | + domain=[('is_company', '=', False), |
138 | + ('contact_type', '=', 'standalone')]), |
139 | + 'other_contact_ids': fields.one2many('res.partner', |
140 | + 'contact_id', |
141 | + 'Others Positions'), |
142 | + |
143 | + # Person specific fields |
144 | + # add a 'birthdate' as date field, i.e different from char 'birthdate' introduced v6.1! |
145 | + 'birthdate_date': fields.date('Birthdate'), |
146 | + 'nationality_id': fields.many2one('res.country', 'Nationality'), |
147 | + } |
148 | + |
149 | + _defaults = { |
150 | + 'contact_type': 'standalone', |
151 | + } |
152 | + |
153 | + def _basecontact_check_context(self, cr, user, mode, context=None): |
154 | + if context is None: |
155 | + context = {} |
156 | + # Remove 'search_show_all_positions' for non-search mode. |
157 | + # Keeping it in context can result in unexpected behaviour (ex: reading |
158 | + # one2many might return wrong result - i.e with "attached contact" removed |
159 | + # even if it's directly linked to a company). |
160 | + if mode != 'search': |
161 | + context.pop('search_show_all_positions', None) |
162 | + return context |
163 | + |
164 | + def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False): |
165 | + if context is None: |
166 | + context = {} |
167 | + if context.get('search_show_all_positions') is False: |
168 | + # display only standalone contact matching ``args`` or having |
169 | + # attached contact matching ``args`` |
170 | + args = expression.normalize_domain(args) |
171 | + attached_contact_args = expression.AND((args, [('contact_type', '=', 'attached')])) |
172 | + attached_contact_ids = super(res_partner, self).search(cr, user, attached_contact_args, |
173 | + context=context) |
174 | + args = expression.OR(( |
175 | + expression.AND(([('contact_type', '=', 'standalone')], args)), |
176 | + [('other_contact_ids', 'in', attached_contact_ids)], |
177 | + )) |
178 | + return super(res_partner, self).search(cr, user, args, offset=offset, limit=limit, |
179 | + order=order, context=context, count=count) |
180 | + |
181 | + def create(self, cr, user, vals, context=None): |
182 | + context = self._basecontact_check_context(cr, user, 'create', context) |
183 | + if not vals.get('name') and vals.get('contact_id'): |
184 | + vals['name'] = self.browse(cr, user, vals['contact_id'], context=context).name |
185 | + return super(res_partner, self).create(cr, user, vals, context=context) |
186 | + |
187 | + def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'): |
188 | + context = self._basecontact_check_context(cr, user, 'read', context) |
189 | + return super(res_partner, self).read(cr, user, ids, fields=fields, context=context, load=load) |
190 | + |
191 | + def write(self, cr, user, ids, vals, context=None): |
192 | + context = self._basecontact_check_context(cr, user, 'write', context) |
193 | + return super(res_partner, self).write(cr, user, ids, vals, context=context) |
194 | + |
195 | + def unlink(self, cr, user, ids, context=None): |
196 | + context = self._basecontact_check_context(cr, user, 'unlink', context) |
197 | + return super(res_partner, self).unlink(cr, user, ids, context=context) |
198 | + |
199 | + def _commercial_partner_compute(self, cr, uid, ids, name, args, context=None): |
200 | + """ Returns the partner that is considered the commercial |
201 | + entity of this partner. The commercial entity holds the master data |
202 | + for all commercial fields (see :py:meth:`~_commercial_fields`) """ |
203 | + result = super(res_partner, self)._commercial_partner_compute(cr, uid, ids, name, args, context=context) |
204 | + for partner in self.browse(cr, uid, ids, context=context): |
205 | + if partner.contact_type == 'attached' and not partner.parent_id: |
206 | + result[partner.id] = partner.contact_id.id |
207 | + return result |
208 | + |
209 | + def _contact_fields(self, cr, uid, context=None): |
210 | + """ Returns the list of contact fields that are synced from the parent |
211 | + when a partner is attached to him. """ |
212 | + return ['name', 'title'] |
213 | + |
214 | + def _contact_sync_from_parent(self, cr, uid, partner, context=None): |
215 | + """ Handle sync of contact fields when a new parent contact entity is set, |
216 | + as if they were related fields """ |
217 | + if partner.contact_id: |
218 | + contact_fields = self._contact_fields(cr, uid, context=context) |
219 | + sync_vals = self._update_fields_values(cr, uid, partner.contact_id, |
220 | + contact_fields, context=context) |
221 | + partner.write(sync_vals) |
222 | + |
223 | + def update_contact(self, cr, uid, ids, vals, context=None): |
224 | + if context is None: |
225 | + context = {} |
226 | + if context.get('__update_contact_lock'): |
227 | + return |
228 | + contact_fields = self._contact_fields(cr, uid, context=context) |
229 | + contact_vals = dict((field, vals[field]) for field in contact_fields if field in vals) |
230 | + if contact_vals: |
231 | + ctx = dict(context, __update_contact_lock=True) |
232 | + self.write(cr, uid, ids, contact_vals, context=ctx) |
233 | + |
234 | + def _fields_sync(self, cr, uid, partner, update_values, context=None): |
235 | + """ Sync commercial fields and address fields from company and to children, |
236 | + contact fields from contact and to attached contact after create/update, |
237 | + just as if those were all modeled as fields.related to the parent """ |
238 | + super(res_partner, self)._fields_sync(cr, uid, partner, update_values, context=context) |
239 | + contact_fields = self._contact_fields(cr, uid, context=context) |
240 | + # 1. From UPSTREAM: sync from parent contact |
241 | + if update_values.get('contact_id'): |
242 | + self._contact_sync_from_parent(cr, uid, partner, context=context) |
243 | + # 2. To DOWNSTREAM: sync contact fields to parent or related |
244 | + elif any(field in contact_fields for field in update_values): |
245 | + update_ids = [c.id for c in partner.other_contact_ids if not c.is_company] |
246 | + if partner.contact_id: |
247 | + update_ids.append(partner.contact_id.id) |
248 | + self.update_contact(cr, uid, update_ids, update_values, context=context) |
249 | + |
250 | + def onchange_contact_id(self, cr, uid, ids, contact_id, context=None): |
251 | + values = {} |
252 | + if contact_id: |
253 | + values['name'] = self.browse(cr, uid, contact_id, context=context).name |
254 | + return {'value': values} |
255 | + |
256 | + def onchange_contact_type(self, cr, uid, ids, contact_type, context=None): |
257 | + values = {} |
258 | + if contact_type == 'standalone': |
259 | + values['contact_id'] = False |
260 | + return {'value': values} |
261 | + |
262 | + |
263 | +class ir_actions_window(osv.osv): |
264 | + _inherit = 'ir.actions.act_window' |
265 | + |
266 | + def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'): |
267 | + action_ids = ids |
268 | + if isinstance(ids, (int, long)): |
269 | + action_ids = [ids] |
270 | + actions = super(ir_actions_window, self).read(cr, user, action_ids, fields=fields, context=context, load=load) |
271 | + for action in actions: |
272 | + if action.get('res_model', '') == 'res.partner': |
273 | + # By default, only show standalone contact |
274 | + action_context = action.get('context', '{}') or '{}' |
275 | + if 'search_show_all_positions' not in action_context: |
276 | + action['context'] = action_context.replace('{', |
277 | + "{'search_show_all_positions': False,", 1) |
278 | + if isinstance(ids, (int, long)): |
279 | + if actions: |
280 | + return actions[0] |
281 | + return False |
282 | + return actions |
283 | |
284 | === added file 'base_contact/base_contact_demo.xml' |
285 | --- base_contact/base_contact_demo.xml 1970-01-01 00:00:00 +0000 |
286 | +++ base_contact/base_contact_demo.xml 2013-12-11 19:37:11 +0000 |
287 | @@ -0,0 +1,29 @@ |
288 | +<?xml version="1.0" encoding="UTF-8"?> |
289 | +<openerp> |
290 | + <data> |
291 | + |
292 | + <record id="res_partner_main2_position_consultant" model="res.partner"> |
293 | + <field name="name">Roger Scott</field> |
294 | + <field name="function">Consultant</field> |
295 | + <field name="parent_id" ref="base.res_partner_11"/> |
296 | + <field name="contact_id" ref="base.res_partner_main2"/> |
297 | + <field name="use_parent_address" eval="True"/> |
298 | + </record> |
299 | + |
300 | + <record id="res_partner_contact1" model="res.partner"> |
301 | + <field name="name">Bob Egnops</field> |
302 | + <field name="birthdate_date">1984-01-01</field> |
303 | + <field name="email">bob@hillenburg-oceaninstitute.com</field> |
304 | + </record> |
305 | + |
306 | + <record id="res_partner_contact1_work_position1" model="res.partner"> |
307 | + <field name="name">Bob Egnops</field> |
308 | + <field name="function">Technician</field> |
309 | + <field name="email">bob@yourcompany.com</field> |
310 | + <field name="parent_id" ref="base.main_partner"/> |
311 | + <field name="contact_id" ref="res_partner_contact1"/> |
312 | + <field name="use_parent_address" eval="True"/> |
313 | + </record> |
314 | + |
315 | + </data> |
316 | +</openerp> |
317 | \ No newline at end of file |
318 | |
319 | === added file 'base_contact/base_contact_view.xml' |
320 | --- base_contact/base_contact_view.xml 1970-01-01 00:00:00 +0000 |
321 | +++ base_contact/base_contact_view.xml 2013-12-11 19:37:11 +0000 |
322 | @@ -0,0 +1,202 @@ |
323 | +<?xml version="1.0" encoding="utf-8"?> |
324 | +<openerp> |
325 | +<data> |
326 | + |
327 | + <record id="view_res_partner_filter_contact" model="ir.ui.view"> |
328 | + <field name="name">res.partner.select.contact</field> |
329 | + <field name="model">res.partner</field> |
330 | + <field name="inherit_id" ref="base.view_res_partner_filter"/> |
331 | + <field name="arch" type="xml"> |
332 | + <filter name="type_company" position="after"> |
333 | + <separator/> |
334 | + <filter string="All positions" name="type_otherpositions" |
335 | + context="{'search_show_all_positions': True}" |
336 | + help="All partner positions"/> |
337 | + </filter> |
338 | + <xpath expr="/search/group/filter[@string='Company']" position="before"> |
339 | + <filter string="Person" name="group_person" context="{'group_by': 'contact_id'}"/> |
340 | + </xpath> |
341 | + </field> |
342 | + </record> |
343 | + |
344 | + <record id="view_res_partner_tree_contact" model="ir.ui.view"> |
345 | + <field name="name">res.partner.tree.contact</field> |
346 | + <field name="model">res.partner</field> |
347 | + <field name="inherit_id" ref="base.view_partner_tree"/> |
348 | + <field name="arch" type="xml"> |
349 | + <field name="parent_id" position="after"> |
350 | + <field name="contact_id" invisible="1"/> |
351 | + </field> |
352 | + </field> |
353 | + </record> |
354 | + |
355 | + <record model="ir.ui.view" id="view_partner_form_inherit"> |
356 | + <field name="name">res.partner.form.contact</field> |
357 | + <field name="model">res.partner</field> |
358 | + <field name="inherit_id" ref="base.view_partner_form"/> |
359 | + <field name="type">form</field> |
360 | + <field name="arch" type="xml"> |
361 | + <field name="is_company" position="after"> |
362 | + <field name="contact_type" invisible="1"/> |
363 | + </field> |
364 | + <page string="Contacts" position="after"> |
365 | + <page string="Other Positions" attrs="{'invisible': ['|',('is_company','=',True),('contact_id','!=',False)]}"> |
366 | + <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, 'default_supplier': supplier}}" mode="kanban"> |
367 | + <kanban> |
368 | + <field name="color"/> |
369 | + <field name="name"/> |
370 | + <field name="title"/> |
371 | + <field name="email"/> |
372 | + <field name="parent_id"/> |
373 | + <field name="is_company"/> |
374 | + <field name="function"/> |
375 | + <field name="phone"/> |
376 | + <field name="street"/> |
377 | + <field name="street2"/> |
378 | + <field name="zip"/> |
379 | + <field name="city"/> |
380 | + <field name="country_id"/> |
381 | + <field name="mobile"/> |
382 | + <field name="fax"/> |
383 | + <field name="state_id"/> |
384 | + <field name="has_image"/> |
385 | + <templates> |
386 | + <t t-name="kanban-box"> |
387 | + <t t-set="color" t-value="kanban_color(record.color.raw_value)"/> |
388 | + <div t-att-class="color + (record.title.raw_value == 1 ? ' oe_kanban_color_alert' : '')" style="position: relative"> |
389 | + <a t-if="! read_only_mode" type="delete" style="position: absolute; right: 0; padding: 4px; diplay: inline-block">X</a> |
390 | + <div class="oe_module_vignette"> |
391 | + <a type="open"> |
392 | + <t t-if="record.has_image.raw_value === true"> |
393 | + <img t-att-src="kanban_image('res.partner', 'image', record.id.value, {'preview_image': 'image_small'})" class="oe_avatar oe_kanban_avatar_smallbox"/> |
394 | + </t> |
395 | + <t t-if="record.image and record.image.raw_value !== false"> |
396 | + <img t-att-src="'data:image/png;base64,'+record.image.raw_value" class="oe_avatar oe_kanban_avatar_smallbox"/> |
397 | + </t> |
398 | + <t t-if="record.has_image.raw_value === false and (!record.image or record.image.raw_value === false)"> |
399 | + <t t-if="record.is_company.raw_value === true"> |
400 | + <img t-att-src='_s + "/base/static/src/img/company_image.png"' class="oe_kanban_image oe_kanban_avatar_smallbox"/> |
401 | + </t> |
402 | + <t t-if="record.is_company.raw_value === false"> |
403 | + <img t-att-src='_s + "/base/static/src/img/avatar.png"' class="oe_kanban_image oe_kanban_avatar_smallbox"/> |
404 | + </t> |
405 | + </t> |
406 | + </a> |
407 | + <div class="oe_module_desc"> |
408 | + <div class="oe_kanban_box_content oe_kanban_color_bglight oe_kanban_color_border"> |
409 | + <table class="oe_kanban_table"> |
410 | + <tr> |
411 | + <td class="oe_kanban_title1" align="left" valign="middle"> |
412 | + <h4><a type="open"><field name="name"/></a></h4> |
413 | + <i> |
414 | + <t t-if="record.parent_id.raw_value and !record.function.raw_value"><field name="parent_id"/></t> |
415 | + <t t-if="!record.parent_id.raw_value and record.function.raw_value"><field name="function"/></t> |
416 | + <t t-if="record.parent_id.raw_value and record.function.raw_value"><field name="function"/> at <field name="parent_id"/></t> |
417 | + </i> |
418 | + <div><a t-if="record.email.raw_value" title="Mail" t-att-href="'mailto:'+record.email.value"> |
419 | + <field name="email"/> |
420 | + </a></div> |
421 | + <div t-if="record.phone.raw_value">Phone: <field name="phone"/></div> |
422 | + <div t-if="record.mobile.raw_value">Mobile: <field name="mobile"/></div> |
423 | + <div t-if="record.fax.raw_value">Fax: <field name="fax"/></div> |
424 | + </td> |
425 | + </tr> |
426 | + </table> |
427 | + </div> |
428 | + </div> |
429 | + </div> |
430 | + </div> |
431 | + </t> |
432 | + </templates> |
433 | + </kanban> |
434 | + <form string="Contact" version="7.0"> |
435 | + <sheet> |
436 | + <field name="image" widget='image' class="oe_avatar oe_left" options='{"preview_image": "image_medium"}'/> |
437 | + <div class="oe_title"> |
438 | + <label for="name" class="oe_edit_only"/> |
439 | + <h1><field name="name" style="width: 70%%"/></h1> |
440 | + </div> |
441 | + <group> |
442 | + <!-- inherited part --> |
443 | + <field name="category_id" widget="many2many_tags" placeholder="Tags..." style="width: 70%%"/> |
444 | + <field name="parent_id" placeholder="Company" domain="[('is_company','=',True)]"/> |
445 | + <!-- inherited part end --> |
446 | + <field name="function" placeholder="e.g. Sales Director"/> |
447 | + <field name="email"/> |
448 | + <field name="phone"/> |
449 | + <field name="mobile"/> |
450 | + </group> |
451 | + <div> |
452 | + <field name="use_parent_address"/><label for="use_parent_address"/> |
453 | + </div> |
454 | + <group> |
455 | + <label for="type"/> |
456 | + <div name="div_type"> |
457 | + <field class="oe_inline" name="type"/> |
458 | + </div> |
459 | + <label for="street" string="Address" attrs="{'invisible': [('use_parent_address','=', True)]}"/> |
460 | + <div attrs="{'invisible': [('use_parent_address','=', True)]}" name="div_address"> |
461 | + <field name="street" placeholder="Street..."/> |
462 | + <field name="street2"/> |
463 | + <div class="address_format"> |
464 | + <field name="city" placeholder="City" style="width: 40%%"/> |
465 | + <field name="state_id" class="oe_no_button" placeholder="State" style="width: 37%%" options='{"no_open": True}' on_change="onchange_state(state_id)"/> |
466 | + <field name="zip" placeholder="ZIP" style="width: 20%%"/> |
467 | + </div> |
468 | + <field name="country_id" placeholder="Country" class="oe_no_button" options='{"no_open": True}'/> |
469 | + </div> |
470 | + </group> |
471 | + <field name="supplier" invisible="True"/> |
472 | + </sheet> |
473 | + </form> |
474 | + </field> |
475 | + </page> |
476 | + <page name="personal-info" string="Personal Information" attrs="{'invisible': ['|',('is_company','=',True)]}"> |
477 | + <p attrs="{'invisible': [('contact_id','=',False)]}"> |
478 | + To see personal information about this contact, please go to to the his person form: <field name="contact_id" class="oe_inline" domain="[('contact_type','!=','attached')]" context="{'show_address': 1}" |
479 | + on_change="onchange_contact_id(contact_id)" options="{'always_reload': True}"/> |
480 | + </p> |
481 | + <group attrs="{'invisible': [('contact_id','!=',False)]}"> |
482 | + <field name="birthdate_date"/> |
483 | + <field name="nationality_id"/> |
484 | + </group> |
485 | + </page> |
486 | + </page> |
487 | + <xpath expr="//field[@name='child_ids']/form//field[@name='name']/.." position="before"> |
488 | + <field name="contact_type" readonly="0" on_change="onchange_contact_type(contact_type)"/> |
489 | + </xpath> |
490 | + <xpath expr="//field[@name='child_ids']/form//field[@name='name']" position="after"> |
491 | + <field name="contact_id" on_change="onchange_contact_id(contact_id)" string="Contact" |
492 | + attrs="{'invisible': [('contact_type','!=','attached')], 'required': [('contact_type','=','attached')]}"/> |
493 | + </xpath> |
494 | + <xpath expr="//field[@name='child_ids']/form//field[@name='name']" position="attributes"> |
495 | + <attribute name="attrs">{'invisible': [('contact_type','=','attached')]}</attribute> |
496 | + </xpath> |
497 | + </field> |
498 | + </record> |
499 | + |
500 | + <record model="ir.ui.view" id="view_res_partner_kanban_contact"> |
501 | + <field name="name">res.partner.kanban.contact</field> |
502 | + <field name="model">res.partner</field> |
503 | + <field name="inherit_id" ref="base.res_partner_kanban_view"/> |
504 | + <field name="arch" type="xml"> |
505 | + <field name="is_company" position="after"> |
506 | + <field name="other_contact_ids"> |
507 | + <tree> |
508 | + <field name="parent_id"/> |
509 | + <field name="function"/> |
510 | + </tree> |
511 | + </field> |
512 | + </field> |
513 | + <xpath expr="//t[@t-name='kanban-box']//div[@class='oe_kanban_details']/ul/li[3]" position="after"> |
514 | + <t t-if="record.other_contact_ids.raw_value.length > 0"> |
515 | + <li>+<t t-esc="record.other_contact_ids.raw_value.length"/> |
516 | + <t t-if="record.other_contact_ids.raw_value.length == 1">other position</t> |
517 | + <t t-if="record.other_contact_ids.raw_value.length > 1">other positions</t></li> |
518 | + </t> |
519 | + </xpath> |
520 | + </field> |
521 | + </record> |
522 | + |
523 | +</data> |
524 | +</openerp> |
525 | |
526 | === added directory 'base_contact/i18n' |
527 | === added file 'base_contact/i18n/base_contact.pot' |
528 | --- base_contact/i18n/base_contact.pot 1970-01-01 00:00:00 +0000 |
529 | +++ base_contact/i18n/base_contact.pot 2013-12-11 19:37:11 +0000 |
530 | @@ -0,0 +1,184 @@ |
531 | +# Translation of OpenERP Server. |
532 | +# This file contains the translation of the following modules: |
533 | +# * base_contact |
534 | +# |
535 | +msgid "" |
536 | +msgstr "" |
537 | +"Project-Id-Version: OpenERP Server 7.0\n" |
538 | +"Report-Msgid-Bugs-To: \n" |
539 | +"POT-Creation-Date: 2013-12-10 16:08+0000\n" |
540 | +"PO-Revision-Date: 2013-12-10 11:08-0500\n" |
541 | +"Last-Translator: \n" |
542 | +"Language-Team: \n" |
543 | +"MIME-Version: 1.0\n" |
544 | +"Content-Type: text/plain; charset=UTF-8\n" |
545 | +"Content-Transfer-Encoding: 8bit\n" |
546 | +"Plural-Forms: \n" |
547 | +"X-Generator: Poedit 1.5.4\n" |
548 | + |
549 | +#. module: base_contact |
550 | +#: view:res.partner:0 |
551 | +msgid "City" |
552 | +msgstr "" |
553 | + |
554 | +#. module: base_contact |
555 | +#: view:res.partner:0 |
556 | +msgid "other position" |
557 | +msgstr "" |
558 | + |
559 | +#. module: base_contact |
560 | +#: view:res.partner:0 |
561 | +msgid "Contacts" |
562 | +msgstr "" |
563 | + |
564 | +#. module: base_contact |
565 | +#: view:res.partner:0 |
566 | +msgid "" |
567 | +"To see personal information about this contact, please go to to the his " |
568 | +"person form:" |
569 | +msgstr "" |
570 | + |
571 | +#. module: base_contact |
572 | +#: view:res.partner:0 |
573 | +msgid "Street..." |
574 | +msgstr "" |
575 | + |
576 | +#. module: base_contact |
577 | +#: view:res.partner:0 |
578 | +msgid "State" |
579 | +msgstr "" |
580 | + |
581 | +#. module: base_contact |
582 | +#: view:res.partner:0 |
583 | +msgid "at" |
584 | +msgstr "" |
585 | + |
586 | +#. module: base_contact |
587 | +#: view:res.partner:0 |
588 | +msgid "Tags..." |
589 | +msgstr "" |
590 | + |
591 | +#. module: base_contact |
592 | +#: view:res.partner:0 |
593 | +msgid "Other Positions" |
594 | +msgstr "" |
595 | + |
596 | +#. module: base_contact |
597 | +#: view:res.partner:0 |
598 | +msgid "Phone:" |
599 | +msgstr "" |
600 | + |
601 | +#. module: base_contact |
602 | +#: view:res.partner:0 |
603 | +msgid "Company" |
604 | +msgstr "" |
605 | + |
606 | +#. module: base_contact |
607 | +#: field:res.partner,contact_id:0 |
608 | +msgid "Main Contact" |
609 | +msgstr "" |
610 | + |
611 | +#. module: base_contact |
612 | +#: view:res.partner:0 |
613 | +msgid "Fax:" |
614 | +msgstr "" |
615 | + |
616 | +#. module: base_contact |
617 | +#: selection:res.partner,contact_type:0 |
618 | +msgid "Standalone Contact" |
619 | +msgstr "" |
620 | + |
621 | +#. module: base_contact |
622 | +#: view:res.partner:0 |
623 | +msgid "Address" |
624 | +msgstr "" |
625 | + |
626 | +#. module: base_contact |
627 | +#: field:res.partner,nationality_id:0 |
628 | +msgid "Nationality" |
629 | +msgstr "" |
630 | + |
631 | +#. module: base_contact |
632 | +#: selection:res.partner,contact_type:0 |
633 | +msgid "Attached to existing Contact" |
634 | +msgstr "" |
635 | + |
636 | +#. module: base_contact |
637 | +#: view:res.partner:0 |
638 | +msgid "ZIP" |
639 | +msgstr "" |
640 | + |
641 | +#. module: base_contact |
642 | +#: view:res.partner:0 |
643 | +msgid "Country" |
644 | +msgstr "" |
645 | + |
646 | +#. module: base_contact |
647 | +#: field:res.partner,birthdate_date:0 |
648 | +msgid "Birthdate" |
649 | +msgstr "" |
650 | + |
651 | +#. module: base_contact |
652 | +#: view:res.partner:0 |
653 | +msgid "Person" |
654 | +msgstr "" |
655 | + |
656 | +#. module: base_contact |
657 | +#: view:res.partner:0 |
658 | +msgid "Contact" |
659 | +msgstr "" |
660 | + |
661 | +#. module: base_contact |
662 | +#: view:res.partner:0 |
663 | +msgid "Mobile:" |
664 | +msgstr "" |
665 | + |
666 | +#. module: base_contact |
667 | +#: view:res.partner:0 |
668 | +msgid "All partner positions" |
669 | +msgstr "" |
670 | + |
671 | +#. module: base_contact |
672 | +#: view:res.partner:0 |
673 | +msgid "{'invisible': [('contact_type','=','attached')]}" |
674 | +msgstr "" |
675 | + |
676 | +#. module: base_contact |
677 | +#: view:res.partner:0 |
678 | +msgid "All positions" |
679 | +msgstr "" |
680 | + |
681 | +#. module: base_contact |
682 | +#: model:ir.model,name:base_contact.model_ir_actions_act_window |
683 | +msgid "ir.actions.act_window" |
684 | +msgstr "" |
685 | + |
686 | +#. module: base_contact |
687 | +#: view:res.partner:0 |
688 | +msgid "other positions" |
689 | +msgstr "" |
690 | + |
691 | +#. module: base_contact |
692 | +#: field:res.partner,contact_type:0 |
693 | +msgid "Contact Type" |
694 | +msgstr "" |
695 | + |
696 | +#. module: base_contact |
697 | +#: model:ir.model,name:base_contact.model_res_partner |
698 | +msgid "Partner" |
699 | +msgstr "" |
700 | + |
701 | +#. module: base_contact |
702 | +#: field:res.partner,other_contact_ids:0 |
703 | +msgid "Others Positions" |
704 | +msgstr "" |
705 | + |
706 | +#. module: base_contact |
707 | +#: view:res.partner:0 |
708 | +msgid "Personal Information" |
709 | +msgstr "" |
710 | + |
711 | +#. module: base_contact |
712 | +#: view:res.partner:0 |
713 | +msgid "e.g. Sales Director" |
714 | +msgstr "" |
715 | |
716 | === added file 'base_contact/i18n/fr.po' |
717 | --- base_contact/i18n/fr.po 1970-01-01 00:00:00 +0000 |
718 | +++ base_contact/i18n/fr.po 2013-12-11 19:37:11 +0000 |
719 | @@ -0,0 +1,186 @@ |
720 | +# Translation of OpenERP Server. |
721 | +# This file contains the translation of the following modules: |
722 | +# * base_contact |
723 | +# |
724 | +msgid "" |
725 | +msgstr "" |
726 | +"Project-Id-Version: OpenERP Server 7.0\n" |
727 | +"Report-Msgid-Bugs-To: \n" |
728 | +"POT-Creation-Date: 2013-12-10 16:09+0000\n" |
729 | +"PO-Revision-Date: 2013-12-10 11:15-0500\n" |
730 | +"Last-Translator: \n" |
731 | +"Language-Team: \n" |
732 | +"MIME-Version: 1.0\n" |
733 | +"Content-Type: text/plain; charset=UTF-8\n" |
734 | +"Content-Transfer-Encoding: 8bit\n" |
735 | +"Plural-Forms: \n" |
736 | +"X-Generator: Poedit 1.5.4\n" |
737 | + |
738 | +#. module: base_contact |
739 | +#: view:res.partner:0 |
740 | +msgid "City" |
741 | +msgstr "Ville" |
742 | + |
743 | +#. module: base_contact |
744 | +#: view:res.partner:0 |
745 | +msgid "other position" |
746 | +msgstr "Autre fonction" |
747 | + |
748 | +#. module: base_contact |
749 | +#: view:res.partner:0 |
750 | +msgid "Contacts" |
751 | +msgstr "Contacts" |
752 | + |
753 | +#. module: base_contact |
754 | +#: view:res.partner:0 |
755 | +msgid "" |
756 | +"To see personal information about this contact, please go to to the his " |
757 | +"person form:" |
758 | +msgstr "" |
759 | +"Pour voir des informations personnelles sur ce contact, s'il vous plaît " |
760 | +"aller à la sa forme de personne:" |
761 | + |
762 | +#. module: base_contact |
763 | +#: view:res.partner:0 |
764 | +msgid "Street..." |
765 | +msgstr "Rue..." |
766 | + |
767 | +#. module: base_contact |
768 | +#: view:res.partner:0 |
769 | +msgid "State" |
770 | +msgstr "État" |
771 | + |
772 | +#. module: base_contact |
773 | +#: view:res.partner:0 |
774 | +msgid "at" |
775 | +msgstr "à" |
776 | + |
777 | +#. module: base_contact |
778 | +#: view:res.partner:0 |
779 | +msgid "Tags..." |
780 | +msgstr "Étiquettes..." |
781 | + |
782 | +#. module: base_contact |
783 | +#: view:res.partner:0 |
784 | +msgid "Other Positions" |
785 | +msgstr "Autres Fonctions" |
786 | + |
787 | +#. module: base_contact |
788 | +#: view:res.partner:0 |
789 | +msgid "Phone:" |
790 | +msgstr "Téléphone:" |
791 | + |
792 | +#. module: base_contact |
793 | +#: view:res.partner:0 |
794 | +msgid "Company" |
795 | +msgstr "Organisme" |
796 | + |
797 | +#. module: base_contact |
798 | +#: field:res.partner,contact_id:0 |
799 | +msgid "Main Contact" |
800 | +msgstr "Contact principal" |
801 | + |
802 | +#. module: base_contact |
803 | +#: view:res.partner:0 |
804 | +msgid "Fax:" |
805 | +msgstr "Fax :" |
806 | + |
807 | +#. module: base_contact |
808 | +#: selection:res.partner,contact_type:0 |
809 | +msgid "Standalone Contact" |
810 | +msgstr "Contact simple" |
811 | + |
812 | +#. module: base_contact |
813 | +#: view:res.partner:0 |
814 | +msgid "Address" |
815 | +msgstr "Adresse" |
816 | + |
817 | +#. module: base_contact |
818 | +#: field:res.partner,nationality_id:0 |
819 | +msgid "Nationality" |
820 | +msgstr "Nationalité" |
821 | + |
822 | +#. module: base_contact |
823 | +#: selection:res.partner,contact_type:0 |
824 | +msgid "Attached to existing Contact" |
825 | +msgstr "Attaché à contacter existante" |
826 | + |
827 | +#. module: base_contact |
828 | +#: view:res.partner:0 |
829 | +msgid "ZIP" |
830 | +msgstr "Code postal" |
831 | + |
832 | +#. module: base_contact |
833 | +#: view:res.partner:0 |
834 | +msgid "Country" |
835 | +msgstr "Pays" |
836 | + |
837 | +#. module: base_contact |
838 | +#: field:res.partner,birthdate_date:0 |
839 | +msgid "Birthdate" |
840 | +msgstr "Date de naissance" |
841 | + |
842 | +#. module: base_contact |
843 | +#: view:res.partner:0 |
844 | +msgid "Person" |
845 | +msgstr "Personne" |
846 | + |
847 | +#. module: base_contact |
848 | +#: view:res.partner:0 |
849 | +msgid "Contact" |
850 | +msgstr "Contact" |
851 | + |
852 | +#. module: base_contact |
853 | +#: view:res.partner:0 |
854 | +msgid "Mobile:" |
855 | +msgstr "Portable :" |
856 | + |
857 | +#. module: base_contact |
858 | +#: view:res.partner:0 |
859 | +msgid "All partner positions" |
860 | +msgstr "Toutes les fonctions" |
861 | + |
862 | +#. module: base_contact |
863 | +#: view:res.partner:0 |
864 | +msgid "{'invisible': [('contact_type','=','attached')]}" |
865 | +msgstr "{'invisible': [('contact_type','=','attached')]}" |
866 | + |
867 | +#. module: base_contact |
868 | +#: view:res.partner:0 |
869 | +msgid "All positions" |
870 | +msgstr "Toutes les positions" |
871 | + |
872 | +#. module: base_contact |
873 | +#: model:ir.model,name:base_contact.model_ir_actions_act_window |
874 | +msgid "ir.actions.act_window" |
875 | +msgstr "ir.actions.act_window" |
876 | + |
877 | +#. module: base_contact |
878 | +#: view:res.partner:0 |
879 | +msgid "other positions" |
880 | +msgstr "Autres fonctions" |
881 | + |
882 | +#. module: base_contact |
883 | +#: field:res.partner,contact_type:0 |
884 | +msgid "Contact Type" |
885 | +msgstr "Type de contact" |
886 | + |
887 | +#. module: base_contact |
888 | +#: model:ir.model,name:base_contact.model_res_partner |
889 | +msgid "Partner" |
890 | +msgstr "Partenaire" |
891 | + |
892 | +#. module: base_contact |
893 | +#: field:res.partner,other_contact_ids:0 |
894 | +msgid "Others Positions" |
895 | +msgstr "Autres fonctions" |
896 | + |
897 | +#. module: base_contact |
898 | +#: view:res.partner:0 |
899 | +msgid "Personal Information" |
900 | +msgstr "Informations personnelles" |
901 | + |
902 | +#. module: base_contact |
903 | +#: view:res.partner:0 |
904 | +msgid "e.g. Sales Director" |
905 | +msgstr "e.g. Directeur" |
906 | |
907 | === added directory 'base_contact/images' |
908 | === added directory 'base_contact/tests' |
909 | === added file 'base_contact/tests/__init__.py' |
910 | --- base_contact/tests/__init__.py 1970-01-01 00:00:00 +0000 |
911 | +++ base_contact/tests/__init__.py 2013-12-11 19:37:11 +0000 |
912 | @@ -0,0 +1,26 @@ |
913 | +# -*- coding: utf-8 ⁻*- |
914 | +############################################################################## |
915 | +# |
916 | +# OpenERP, Open Source Business Applications |
917 | +# Copyright (C) 2013-TODAY OpenERP S.A. (<http://openerp.com>). |
918 | +# |
919 | +# This program is free software: you can redistribute it and/or modify |
920 | +# it under the terms of the GNU Affero General Public License as |
921 | +# published by the Free Software Foundation, either version 3 of the |
922 | +# License, or (at your option) any later version. |
923 | +# |
924 | +# This program is distributed in the hope that it will be useful, |
925 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
926 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
927 | +# GNU Affero General Public License for more details. |
928 | +# |
929 | +# You should have received a copy of the GNU Affero General Public License |
930 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
931 | +# |
932 | +############################################################################## |
933 | + |
934 | +from . import test_base_contact |
935 | + |
936 | +checks = [ |
937 | + test_base_contact, |
938 | +] |
939 | |
940 | === added file 'base_contact/tests/test_base_contact.py' |
941 | --- base_contact/tests/test_base_contact.py 1970-01-01 00:00:00 +0000 |
942 | +++ base_contact/tests/test_base_contact.py 2013-12-11 19:37:11 +0000 |
943 | @@ -0,0 +1,136 @@ |
944 | +# -*- coding: utf-8 ⁻*- |
945 | +############################################################################## |
946 | +# |
947 | +# OpenERP, Open Source Business Applications |
948 | +# Copyright (C) 2013-TODAY OpenERP S.A. (<http://openerp.com>). |
949 | +# |
950 | +# This program is free software: you can redistribute it and/or modify |
951 | +# it under the terms of the GNU Affero General Public License as |
952 | +# published by the Free Software Foundation, either version 3 of the |
953 | +# License, or (at your option) any later version. |
954 | +# |
955 | +# This program is distributed in the hope that it will be useful, |
956 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
957 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
958 | +# GNU Affero General Public License for more details. |
959 | +# |
960 | +# You should have received a copy of the GNU Affero General Public License |
961 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
962 | +# |
963 | +############################################################################## |
964 | + |
965 | +from openerp.tests import common |
966 | + |
967 | + |
968 | +class Test_Base_Contact(common.TransactionCase): |
969 | + |
970 | + def setUp(self): |
971 | + """*****setUp*****""" |
972 | + super(Test_Base_Contact, self).setUp() |
973 | + cr, uid = self.cr, self.uid |
974 | + ModelData = self.registry('ir.model.data') |
975 | + self.partner = self.registry('res.partner') |
976 | + |
977 | + # Get test records reference |
978 | + for attr, module, name in [ |
979 | + ('main_partner_id', 'base', 'main_partner'), |
980 | + ('bob_contact_id', 'base_contact', 'res_partner_contact1'), |
981 | + ('bob_job1_id', 'base_contact', 'res_partner_contact1_work_position1'), |
982 | + ('roger_contact_id', 'base', 'res_partner_main2'), |
983 | + ('roger_job2_id', 'base_contact', 'res_partner_main2_position_consultant')]: |
984 | + r = ModelData.get_object_reference(cr, uid, module, name) |
985 | + setattr(self, attr, r[1] if r else False) |
986 | + |
987 | + def test_00_show_only_standalone_contact(self): |
988 | + """Check that only standalone contact are shown if context explicitly state to not display all positions""" |
989 | + cr, uid = self.cr, self.uid |
990 | + ctx = {'search_show_all_positions': False} |
991 | + partner_ids = self.partner.search(cr, uid, [], context=ctx) |
992 | + partner_ids.sort() |
993 | + self.assertTrue(self.bob_job1_id not in partner_ids) |
994 | + self.assertTrue(self.roger_job2_id not in partner_ids) |
995 | + |
996 | + def test_01_show_all_positions(self): |
997 | + """Check that all contact are show if context is empty or explicitly state to display all positions""" |
998 | + cr, uid = self.cr, self.uid |
999 | + |
1000 | + partner_ids = self.partner.search(cr, uid, [], context=None) |
1001 | + self.assertTrue(self.bob_job1_id in partner_ids) |
1002 | + self.assertTrue(self.roger_job2_id in partner_ids) |
1003 | + |
1004 | + ctx = {'search_show_all_positions': True} |
1005 | + partner_ids = self.partner.search(cr, uid, [], context=ctx) |
1006 | + self.assertTrue(self.bob_job1_id in partner_ids) |
1007 | + self.assertTrue(self.roger_job2_id in partner_ids) |
1008 | + |
1009 | + def test_02_reading_other_contact_one2many_show_all_positions(self): |
1010 | + """Check that readonly partner's ``other_contact_ids`` return all values whatever the context""" |
1011 | + cr, uid = self.cr, self.uid |
1012 | + |
1013 | + def read_other_contacts(pid, context=None): |
1014 | + return self.partner.read(cr, uid, [pid], ['other_contact_ids'], context=context)[0]['other_contact_ids'] |
1015 | + |
1016 | + def read_contacts(pid, context=None): |
1017 | + return self.partner.read(cr, uid, [pid], ['child_ids'], context=context)[0]['child_ids'] |
1018 | + |
1019 | + ctx = None |
1020 | + self.assertEqual(read_other_contacts(self.bob_contact_id, context=ctx), [self.bob_job1_id]) |
1021 | + ctx = {'search_show_all_positions': False} |
1022 | + self.assertEqual(read_other_contacts(self.bob_contact_id, context=ctx), [self.bob_job1_id]) |
1023 | + ctx = {'search_show_all_positions': True} |
1024 | + self.assertEqual(read_other_contacts(self.bob_contact_id, context=ctx), [self.bob_job1_id]) |
1025 | + |
1026 | + ctx = None |
1027 | + self.assertTrue(self.bob_job1_id in read_contacts(self.main_partner_id, context=ctx)) |
1028 | + ctx = {'search_show_all_positions': False} |
1029 | + self.assertTrue(self.bob_job1_id in read_contacts(self.main_partner_id, context=ctx)) |
1030 | + ctx = {'search_show_all_positions': True} |
1031 | + self.assertTrue(self.bob_job1_id in read_contacts(self.main_partner_id, context=ctx)) |
1032 | + |
1033 | + def test_03_search_match_attached_contacts(self): |
1034 | + """Check that searching partner also return partners having attached contacts matching search criteria""" |
1035 | + cr, uid = self.cr, self.uid |
1036 | + # Bob's contact has one other position which is related to 'Your Company' |
1037 | + # so search for all contacts working for 'Your Company' should contain bob position. |
1038 | + partner_ids = self.partner.search(cr, uid, [('parent_id', 'ilike', 'Your Company')], context=None) |
1039 | + self.assertTrue(self.bob_job1_id in partner_ids) |
1040 | + |
1041 | + # but when searching without 'all positions', we should get the position standalone contact instead. |
1042 | + ctx = {'search_show_all_positions': False} |
1043 | + partner_ids = self.partner.search(cr, uid, [('parent_id', 'ilike', 'Your Company')], context=ctx) |
1044 | + self.assertTrue(self.bob_contact_id in partner_ids) |
1045 | + |
1046 | + def test_04_contact_creation(self): |
1047 | + """Check that we're begin to create a contact""" |
1048 | + cr, uid = self.cr, self.uid |
1049 | + |
1050 | + # Create a contact using only name |
1051 | + new_contact_id = self.partner.create(cr, uid, {'name': 'Bob Egnops'}) |
1052 | + self.assertEqual(self.partner.browse(cr, uid, new_contact_id).contact_type, 'standalone') |
1053 | + |
1054 | + # Create a contact with only contact_id |
1055 | + new_contact_id = self.partner.create(cr, uid, {'contact_id': self.bob_contact_id}) |
1056 | + new_contact = self.partner.browse(cr, uid, new_contact_id) |
1057 | + self.assertEqual(new_contact.name, 'Bob Egnops') |
1058 | + self.assertEqual(new_contact.contact_type, 'attached') |
1059 | + |
1060 | + # Create a contact with both contact_id and name; |
1061 | + # contact's name should override provided value in that case |
1062 | + new_contact_id = self.partner.create(cr, uid, {'contact_id': self.bob_contact_id, 'name': 'Rob Egnops'}) |
1063 | + self.assertEqual(self.partner.browse(cr, uid, new_contact_id).name, 'Bob Egnops') |
1064 | + |
1065 | + # Reset contact to standalone |
1066 | + self.partner.write(cr, uid, [new_contact_id], {'contact_id': False}) |
1067 | + self.assertEqual(self.partner.browse(cr, uid, new_contact_id).contact_type, 'standalone') |
1068 | + |
1069 | + def test_05_contact_fields_sync(self): |
1070 | + """Check that contact's fields are correctly synced between parent contact or related contacts""" |
1071 | + cr, uid = self.cr, self.uid |
1072 | + |
1073 | + # Test DOWNSTREAM sync |
1074 | + self.partner.write(cr, uid, [self.bob_contact_id], {'name': 'Rob Egnops'}) |
1075 | + self.assertEqual(self.partner.browse(cr, uid, self.bob_job1_id).name, 'Rob Egnops') |
1076 | + |
1077 | + # Test UPSTREAM sync |
1078 | + self.partner.write(cr, uid, [self.bob_job1_id], {'name': 'Bob Egnops'}) |
1079 | + self.assertEqual(self.partner.browse(cr, uid, self.bob_contact_id).name, 'Bob Egnops') |