Merge lp:~hirt/ocb-addons/6.1_base_contact_finalize into lp:ocb-addons/6.1

Proposed by Etienne Hirt
Status: Needs review
Proposed branch: lp:~hirt/ocb-addons/6.1_base_contact_finalize
Merge into: lp:ocb-addons/6.1
Diff against target: 973 lines (+559/-100)
4 files modified
base_contact/__openerp__.py (+11/-6)
base_contact/base_contact.py (+294/-53)
base_contact/base_contact_view.xml (+252/-40)
base_contact/security/ir.model.access.csv (+2/-1)
To merge this branch: bzr merge lp:~hirt/ocb-addons/6.1_base_contact_finalize
Reviewer Review Type Date Requested Status
Omar (Pexego) code review, no test Needs Fixing
Review via email: mp+193941@code.launchpad.net

Description of the change

Finalising the base contact 6.1 desig by adding the missing fields as described in https://bugs.launchpad.net/openobject-addons/+bug/923440

To post a comment you must log in.
Revision history for this message
Pedro Manuel Baeza (pedro.baeza) wrote :

Hi, Etienne, thank you for making again the MP properly. I will check it, but it's a huge diff for only a bugfix. I'm not sure if this is going to fit into OCB project and goals.

Let's see what others reviewers say.

Regards.

Revision history for this message
Etienne Hirt (hirt) wrote :

Dear Pedro,

Thanks for your offer to check it.

Somehow the redesign of the base_contact module for 6.1 was never
finished as it was abandoned by openerp. I prepared the fixes some time
ago to have the function available at Art of Technology. This
functionality is also the main reason for us not considering Version 7
(yet).

The effort now is to have others being able to profit from it, too and
also to profit from the community.

Best Regards

Etienne

On 05.11.2013 17:09, Pedro Manuel Baeza wrote:
> Hi, Etienne, thank you for making again the MP properly. I will check it, but it's a huge diff for only a bugfix. I'm not sure if this is going to fit into OCB project and goals.
>
> Let's see what others reviewers say.
>
> Regards.

Revision history for this message
Omar (Pexego) (omar7r) wrote :

At first sight, you should remove pdb import and the commented lines, on the other hand, you convert the partner_id field, from related to function field without search function, this field could be used in several addons as filter, with function field will not work anymore at least without search function.
IMHO I prefer name_search as works now, because your way don't support, for example, with compound first names or more than one last name, this is applyable to view_init function too.

It's a huge diff as Pedro said and I think that isn't the best way to complete this addon but we can wait for opinion of other reviewers, for now, I will mark it as needs fixing, for the up things.

Regards

review: Needs Fixing (code review, no test)
Revision history for this message
Etienne Hirt (hirt) wrote :

Dear Omar,

thanks for the review and your valuable comments. Please check my
answers below.

Best Regards

Etienne

On 20.11.2013 01:19, Omar (Pexego) wrote:
> Review: Needs Fixing code review, no test
>
> At first sight, you should remove pdb import and the commented lines, on the other hand,
mostly done
> you convert the partner_id field, from related to function field without search function, this field could be used in several addons as filter, with function field will not work anymore at least without search function.
With the related field you have no real control what partner is selected
as main partner.
Originally I wanted to have conditional storage but this somehow did not
work. I removed it then because contacts are nowhere searched for
partners as far as I know. Also IMHO the related fields can not be
searched if not stored.
What do you propose?
> IMHO I prefer name_search as works now, because your way don't support, for example, with compound first names or more than one last name, this is applyable to view_init function too.
Please check again the proposed search function. Because it's intention
is to extend the original function instead of limit it. Should we also
consider one lastname with multiple/compound first names?

Without the view_init function all newly entered contacts are filled
into lastname only. Thus the proposed function is an extension but not
perfect as it can not guess that multiple Firstnames are used.
>
> It's a huge diff as Pedro said and I think that isn't the best way to complete this addon but we can wait for opinion of other reviewers, for now, I will mark it as needs fixing, for the up things.
>
> Regards

Revision history for this message
Omar (Pexego) (omar7r) wrote :

Hi Etienne,

Thanks for updating. Related fields can not be grouped but, searched yes. Other solution, you could have a search function defined in your function field.

At Spain for example, everyone have two last names and one or two first names, like Jose Antonio or Diego Armando, we could not have limitation in that.

Regards

Revision history for this message
Etienne Hirt (hirt) wrote :

Hi Omar,

Thanks for insisting. With your inputs I found now a solution that supports any number of first and lastname for all searches. This was not the case in the baseline I started with.

Also the partner_id I could change back to related as the sorting of the address_id fits the requirements for the main job.

The view_init is a helper function that is a 90% solution but helps the user even if the remaining 10% when there is more than one firstname.

The partner_contact class is ready for re-reviewing. But the partner_address requires some further work. I therefore set the state to WIP.

Best Regards

6817. By Etienne Hirt

remove the executable flag that wrongly added in last commit

6818. By Etienne Hirt

* store partner_id in location directly to solve usability issue of having
  locations assigned to partners if any and to view it while using.
  Attention: this commit does not store the partner_ids yet at updating
             but for install the module it is added.
* override copy method for res.partner.location to avoid copying the
  related addresses's

6819. By Etienne Hirt

add auto_init for partner_id in res_partner_location

6820. By Etienne Hirt

* streamline location editing
* enhance and streamline search

6821. By Etienne Hirt

delete action as menu deletion did not work for upgrade contact/address with new action

6822. By Etienne Hirt

*further streamlining location editing
*restrict deletion of partner when there are assigned addresses

6823. By Etienne Hirt

* changes of partner of address does still not fully update the location partner_id
to be continued

6824. By Etienne Hirt

* use storage triggers for partner_id in res_partner_location
* minor UI adjustments:
** group extended for location menu but not addresses
** add partner to functions/addresses in contact form

6825. By Etienne Hirt

* enhance contact and location search
* fix length of name in contact to allow full lenght of last_name + first_name

6826. By Etienne Hirt

void delection of assigned locations

6827. By Etienne Hirt

commit files no longer executable

6828. By Etienne Hirt

do merge

6829. By Etienne Hirt

add street to res_partner_address displayname

6830. By Etienne Hirt

add other phone to address tree and form

6831. By Etienne Hirt

* store all related fields from location if one changes
* add trigger on change_location_id also because the on_change function does not store all changes!

Unmerged revisions

6831. By Etienne Hirt

* store all related fields from location if one changes
* add trigger on change_location_id also because the on_change function does not store all changes!

6830. By Etienne Hirt

add other phone to address tree and form

6829. By Etienne Hirt

add street to res_partner_address displayname

6828. By Etienne Hirt

do merge

6827. By Etienne Hirt

commit files no longer executable

6826. By Etienne Hirt

void delection of assigned locations

6825. By Etienne Hirt

* enhance contact and location search
* fix length of name in contact to allow full lenght of last_name + first_name

6824. By Etienne Hirt

* use storage triggers for partner_id in res_partner_location
* minor UI adjustments:
** group extended for location menu but not addresses
** add partner to functions/addresses in contact form

6823. By Etienne Hirt

* changes of partner of address does still not fully update the location partner_id
to be continued

6822. By Etienne Hirt

*further streamlining location editing
*restrict deletion of partner when there are assigned addresses

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'account_asset/i18n/ca.po' (properties changed: +x to -x)
=== modified file 'account_asset/i18n/de.po' (properties changed: +x to -x)
=== modified file 'account_asset/i18n/es.po' (properties changed: +x to -x)
=== modified file 'account_asset/i18n/es_CR.po' (properties changed: +x to -x)
=== modified file 'account_asset/i18n/fr.po' (properties changed: +x to -x)
=== modified file 'account_asset/i18n/fr_BE.po' (properties changed: +x to -x)
=== modified file 'account_asset/i18n/pl.po' (properties changed: +x to -x)
=== modified file 'account_asset/i18n/pt.po' (properties changed: +x to -x)
=== modified file 'account_asset/i18n/sv.po' (properties changed: +x to -x)
=== modified file 'account_asset/security/ir.model.access.csv' (properties changed: +x to -x)
=== modified file 'account_asset/wizard/__init__.py' (properties changed: +x to -x)
=== modified file 'account_asset/wizard/account_asset_change_duration.py' (properties changed: +x to -x)
=== modified file 'account_asset/wizard/wizard_asset_compute.py' (properties changed: +x to -x)
=== modified file 'base_contact/__openerp__.py'
--- base_contact/__openerp__.py 2012-01-31 13:36:57 +0000
+++ base_contact/__openerp__.py 2015-01-16 20:04:03 +0000
@@ -21,7 +21,7 @@
2121
22{22{
23 'name': 'Contacts Management',23 'name': 'Contacts Management',
24 'version': '1.0',24 'version': '1.1',
25 'category': 'Customer Relationship Management',25 'category': 'Customer Relationship Management',
26 'complexity': "expert",26 'complexity': "expert",
27 'description': """27 'description': """
@@ -35,12 +35,17 @@
3535
36It also adds new menu items located in36It also adds new menu items located in
37 Purchases / Address Book / Contacts37 Purchases / Address Book / Contacts
38 Sales / Address Book / Contacts38 Sales / Address Book / Contacts and Locations
3939
40Pay attention that this module converts the existing addresses into "addresses + contacts". It means that some fields of the addresses will be missing (like the contact name), since these are supposed to be defined in an other object.40Pay attention that this module converts the existing addresses into "addresses + contacts".
41It means that some fields of the addresses will be missing (the contact name is copied into
42addresses to be compatible with other modules contact name). Others are supposed to be defined in an other object.
43
44All UI work with lastname(s) firstname(s) but the order has to be observed.
45When entering a new contact only one firstname is assumed. You migh add the additional firstname(s) later
41 """,46 """,
42 'author': 'OpenERP SA',47 'author': 'OpenERP SA, Art of Technology AG',
43 'website': 'http://www.openerp.com',48 'website': 'http://www.openerp.com, http://www.aotag.ch',
44 'depends': ['base','process'],49 'depends': ['base','process'],
45 'init_xml': [],50 'init_xml': [],
46 'update_xml': [51 'update_xml': [
4752
=== modified file 'base_contact/base_contact.py'
--- base_contact/base_contact.py 2013-09-10 15:12:35 +0000
+++ base_contact/base_contact.py 2015-01-16 20:04:03 +0000
@@ -27,31 +27,36 @@
2727
28 _name = "res.partner.contact"28 _name = "res.partner.contact"
29 _description = "Contact"29 _description = "Contact"
3030
31 def _name_get_full(self, cr, uid, ids, prop, unknow_none, context=None):31 def _name_get_full(self, cr, uid, ids, prop, unknow_none, context=None):
32 result = {}32 result = {}
33 for rec in self.browse(cr, uid, ids, context=context):33 for rec in self.browse(cr, uid, ids, context=context):
34 result[rec.id] = rec.last_name+' '+(rec.first_name or '')34 if(rec.first_name):
35 #last_name is a required field. Therefore always available
36 result[rec.id] = rec.last_name+' '+rec.first_name
37 else:
38 result[rec.id] = rec.last_name
39
35 return result40 return result
3641
37 _columns = {42 _columns = {
38 'name': fields.function(_name_get_full, string='Name', size=64, type="char", store=True, select=True),43 'name': fields.function(_name_get_full, string='Name', size=128, type="char", store=True, select=True),
39 'last_name': fields.char('Last Name', size=64, required=True),44 'last_name': fields.char('Last Name', size=64, required=True),
40 'first_name': fields.char('First Name', size=64),45 'first_name': fields.char('First Name', size=64),
41 'mobile': fields.char('Mobile', size=64),46 'mobile': fields.char('Mobile', size=64),
42 'title': fields.many2one('res.partner.title','Title', domain=[('domain','=','contact')]),47 'title': fields.many2one('res.partner.title','Title', domain=[('domain','=','contact')], required=True),
43 'website': fields.char('Website', size=120),48 'website': fields.char('Private Website', size=120),
44 'lang_id': fields.many2one('res.lang', 'Language'),49 'lang_id': fields.many2one('res.lang', 'Language'),
45 'job_ids': fields.one2many('res.partner.address', 'contact_id', 'Functions and Addresses'),50 'job_ids': fields.one2many('res.partner.address', 'contact_id', 'Functions and Addresses'),
46 'country_id': fields.many2one('res.country','Nationality'),51 'country_id': fields.many2one('res.country','Nationality'),
47 'birthdate': fields.char('Birthdate', size=64),52 'birthdate': fields.char('Birthdate', size=64),
48 'active': fields.boolean('Active', help="If the active field is set to False,\53 'active': fields.boolean('Active', help="If the active field is set to False,\
49 it will allow you to hide the partner contact without removing it."),54 it will allow you to hide the partner contact without removing it."),
50 'partner_id': fields.related('job_ids', 'partner_id', type='many2one',\55 'partner_id': fields.related('job_ids', 'partner_id', type='many2one',\
51 relation='res.partner', string='Main Employer'),56 relation='res.partner', string='Main Employer'),
52 'function': fields.related('job_ids', 'function', type='char', \57 'function': fields.related('job_ids', 'function', type='char', \
53 string='Main Function'),58 string='Main Function'),
54 'email': fields.char('E-Mail', size=240),59 'email': fields.char('Private E-Mail', size=240),
55 'comment': fields.text('Notes', translate=True),60 'comment': fields.text('Notes', translate=True),
56 'photo': fields.binary('Photo'),61 'photo': fields.binary('Photo'),
57 }62 }
@@ -67,17 +72,6 @@
6772
68 _order = "name"73 _order = "name"
6974
70 def name_search(self, cr, uid, name='', args=None, operator='ilike', context=None, limit=None):
71 if not args:
72 args = []
73 if context is None:
74 context = {}
75 if name:
76 ids = self.search(cr, uid, ['|',('name', operator, name),('first_name', operator, name)] + args, limit=limit, context=context)
77 else:
78 ids = self.search(cr, uid, args, limit=limit, context=context)
79 return self.name_get(cr, uid, ids, context=context)
80
81 def name_get(self, cr, uid, ids, context=None):75 def name_get(self, cr, uid, ids, context=None):
82 result = {}76 result = {}
83 for obj in self.browse(cr, uid, ids, context=context):77 for obj in self.browse(cr, uid, ids, context=context):
@@ -85,6 +79,32 @@
85 if obj.partner_id:79 if obj.partner_id:
86 result[obj.id] = result[obj.id] + ', ' + obj.partner_id.name80 result[obj.id] = result[obj.id] + ', ' + obj.partner_id.name
87 return result.items()81 return result.items()
82
83 def view_init(self, cr, uid, fields, context=None):
84 """
85 This function shall fill the last_name and first_name if empty from context default_name
86 It assumes entry of lastnames Firstname or lastname only. Entry of multiple
87 firstnames has to be adjusted afterwards
88 """
89
90 if context is None:
91 context = {}
92 else:
93 default_name = context.get('default_name')
94 if default_name:
95 split = default_name.split(' ')
96 length = len(split)
97 if length > 1:
98 context.update({'default_first_name': split[length-1]})
99 #join again
100 default_name = split[0]
101 for i in range(1,length-1):
102 default_name = default_name + ' ' + split[i]
103
104 #either fill joined rest or original text into context for last name
105 context.update({'default_last_name': default_name})
106 pass
107
88108
89 def _auto_init(self, cr, context=None):109 def _auto_init(self, cr, context=None):
90 def table_exists(view_name):110 def table_exists(view_name):
@@ -99,9 +119,9 @@
99 cr.execute("""119 cr.execute("""
100 INSERT INTO120 INSERT INTO
101 res_partner_contact121 res_partner_contact
102 (id,name,last_name,title,active,email,mobile,birthdate)122 (id,name, last_name,first_name,title,active,email,mobile,birthdate)
103 SELECT123 SELECT
104 id,COALESCE(name, '/'),COALESCE(name, '/'),title,true,email,mobile,birthdate124 id,name, COALESCE(name, '/'),COALESCE(name, '/'),title,true,email,mobile,birthdate
105 FROM125 FROM
106 res_partner_address""")126 res_partner_address""")
107 cr.execute("alter table res_partner_address add contact_id int references res_partner_contact")127 cr.execute("alter table res_partner_address add contact_id int references res_partner_contact")
@@ -115,6 +135,14 @@
115class res_partner_location(osv.osv):135class res_partner_location(osv.osv):
116 _name = 'res.partner.location'136 _name = 'res.partner.location'
117 _rec_name = 'street'137 _rec_name = 'street'
138
139 def _get_location_from_address_ids(self, cr, uid, ids, context=None):
140 result = {}
141
142 for location in self.pool.get('res.partner.location').search(cr, uid, [('job_ids','in',ids)]):
143 result[location] = True
144
145 return result.keys()
118 _columns = {146 _columns = {
119 'street': fields.char('Street', size=128),147 'street': fields.char('Street', size=128),
120 'street2': fields.char('Street2', size=128),148 'street2': fields.char('Street2', size=128),
@@ -123,13 +151,55 @@
123 'state_id': fields.many2one("res.country.state", 'Fed. State', domain="[('country_id','=',country_id)]"),151 'state_id': fields.many2one("res.country.state", 'Fed. State', domain="[('country_id','=',country_id)]"),
124 'country_id': fields.many2one('res.country', 'Country'),152 'country_id': fields.many2one('res.country', 'Country'),
125 'company_id': fields.many2one('res.company', 'Company',select=1),153 'company_id': fields.many2one('res.company', 'Company',select=1),
126 'job_ids': fields.one2many('res.partner.address', 'location_id', 'Contacts'),154 'job_ids': fields.one2many('res.partner.address', 'location_id', 'Addresses'),
155 #storage triggers are important if an address is changed to another partner etc.
127 'partner_id': fields.related('job_ids', 'partner_id', type='many2one',\156 'partner_id': fields.related('job_ids', 'partner_id', type='many2one',\
128 relation='res.partner', string='Main Partner'),157 relation='res.partner', string='Main Partner',
158 store = {
159 'res.partner.location': (lambda self,cr,uid,ids,c=None: ids, ['job_ids'], 10),
160 'res.partner.address': (_get_location_from_address_ids, ['partner_id'], 10),
161 }),
162 'contact_id': fields.related('job_ids', 'contact_id', type='many2one',\
163 relation='res.partner.contact', string='First Contact'),
129 }164 }
130 _defaults = {165 _defaults = {
131 'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'res.partner.address', context=c),166 'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'res.partner.address', context=c),
132 }167 }
168
169 def copy(self, cr, uid, id, default=None, context=None):
170 """
171 Overrides orm copy method in order to avoid copying of related objects such as
172 * job_ids
173 @param self: the object pointer
174 @param cr: the current row, from the database cursor,
175 @param uid: the current user’s ID for security checks,
176 @param id: Id of crm_lead
177 @param default: Dictionary of default values for copy.
178 @param context: A standard dictionary for contextual values
179 """
180 if context is None:
181 context = {}
182 if default is None:
183 default = {}
184
185 default.update({
186 'job_ids': [],
187 })
188 return super(osv.osv, self).copy(cr, uid, id, default, context=context)
189
190 def view_init(self, cr, uid, fields, context=None):
191 """
192 This function shall fill the street from the entry
193 """
194
195 if context is None:
196 context = {}
197 else:
198 default_name = context.get('default_name')
199 if default_name:
200 context.update({'default_street': default_name})
201 pass
202
133 def _auto_init(self, cr, context=None):203 def _auto_init(self, cr, context=None):
134 def table_exists(view_name):204 def table_exists(view_name):
135 cr.execute('SELECT count(relname) FROM pg_class WHERE relname = %s', (view_name,))205 cr.execute('SELECT count(relname) FROM pg_class WHERE relname = %s', (view_name,))
@@ -144,21 +214,32 @@
144 INSERT INTO214 INSERT INTO
145 res_partner_location215 res_partner_location
146 (id,street,street2,zip,city,216 (id,street,street2,zip,city,
147 state_id,country_id,company_id)217 state_id,country_id,company_id,partner_id)
148 SELECT218 SELECT
149 id,street,street2,zip,city,219 id,street,street2,zip,city,
150 state_id,country_id,company_id220 state_id,country_id,company_id,partner_id
151 FROM221 FROM
152 res_partner_address""")222 res_partner_address""")
153 cr.execute("alter table res_partner_address add location_id int references res_partner_location")223 cr.execute("alter table res_partner_address add location_id int references res_partner_location")
154 cr.execute("update res_partner_address set location_id=id")224 cr.execute("update res_partner_address set location_id=id")
155 cr.execute("select setval('res_partner_location_id_seq', (select max(id)+1 from res_partner_address))")225 cr.execute("select setval('res_partner_location_id_seq', (select max(id)+1 from res_partner_address))")
226 else:
227 cr.execute("""
228 UPDATE
229 res_partner_location l
230 SET
231 partner_id = addr.partner_id
232 FROM
233 res_partner_address addr INNER JOIN res_partner_location loc ON (loc.id = addr.location_id)
234 WHERE
235 l.id = loc.id and l.partner_id is null and addr.partner_id is not null """)
236
156237
157 def name_get(self, cr, uid, ids, context=None):238 def name_get(self, cr, uid, ids, context=None):
158 result = {}239 result = {}
159 for obj in self.browse(cr, uid, ids, context=context):240 for obj in self.browse(cr, uid, ids, context=context):
160 res = []241 res = []
161 if obj.partner_id: res.append(obj.partner_id.name_get()[0][1])242 if obj.street: res.append(obj.street)
162 if obj.city: res.append(obj.city)243 if obj.city: res.append(obj.city)
163 if obj.country_id: res.append(obj.country_id.name_get()[0][1])244 if obj.country_id: res.append(obj.country_id.name_get()[0][1])
164 result[obj.id] = ', '.join(res)245 result[obj.id] = ', '.join(res)
@@ -168,15 +249,83 @@
168249
169class res_partner_address(osv.osv):250class res_partner_address(osv.osv):
170 _inherit = 'res.partner.address'251 _inherit = 'res.partner.address'
252
253 def _get_address_from_location_ids(self, cr, uid, ids, context=None):
254 result = {}
255
256 for addr in self.pool.get('res.partner.address').search(cr, uid, [('location_id','in',ids)]):
257 result[addr] = True
258
259 return result.keys()
260
261 def _get_address_from_contact_ids(self, cr, uid, ids, context=None):
262 result = {}
263 for addr in self.pool.get('res.partner.address').search(cr, uid, [('contact_id','in',ids)]):
264 result[addr] = True
265 return result.keys()
266
267 def _get_own_addresses(self, cr, uid, ids, context=None):
268 result = {}
269 for id in ids:
270 result[id] = True
271 return result.keys()
272
171273
172 def _default_location_id(self, cr, uid, context=None):274 def _default_location_id(self, cr, uid, context=None):
173 if context is None:275 if context is None:
174 context = {}276 context = {}
175 if not context.get('default_partner_id',False):277 if not context.get('default_partner_id',False):
176 return False278 return False
177 ids = self.pool.get('res.partner.location').search(cr, uid, [('partner_id','=',context['default_partner_id'])], context=context)279 #if a default location is available than this is the default location
280 address_pool = self.pool.get('res.partner.address')
281 address_ids = address_pool.search(cr, uid, [('partner_id','=',context['default_partner_id']),('type','=','default')], context=context)
282 ids=[]
283 if address_ids:
284 addresses = address_pool.browse(cr, uid, address_ids)
285 for address in addresses:
286 if address and address.location_id:
287 ids.append(address.location_id.id)
288 break
289 if not ids:
290 ids = self.pool.get('res.partner.location').search(cr, uid, [('partner_id','=',context['default_partner_id'])], context=context)
291
178 return ids and ids[0] or False292 return ids and ids[0] or False
293
294 def onchange_partner_id(self,cr, uid, ids, partner_id=False, context={}):
295 #if this address is the only one that points to its location then keep the location
296 if ids:
297 address = self.pool.get('res.partner.address').browse(cr, uid, ids[0], context=context)
298 if address.location_id:
299 location = self.pool.get('res.partner.location').browse(cr, uid, address.location_id.id, context=context)
300 if len(location.job_ids) <=1:
301 return {}
302
303 if partner_id:
304 context['default_partner_id'] = partner_id
305 location_id = self._default_location_id(cr, uid, context)
306 else:
307 location_id = False
308 return {'value':{
309 'location_id': location_id,
310 }
311 }
179312
313 def onchange_contact_id(self,cr, uid, ids, contact_id=False, context={}):
314 if not contact_id:
315 return {'value':{
316 'mobile': False,
317 #setting of name is not required. If no contact_id it is set to False by the relation
318 'title': False,
319 }
320 }
321 contact = self.pool.get('res.partner.contact').browse(cr, uid, contact_id, context=context)
322 return {'value':{
323 'mobile': contact.mobile,
324 'name': contact.name,
325 'title': contact.title and contact.title.id or False,
326 }}
327
328
180 def onchange_location_id(self,cr, uid, ids, location_id=False, context={}):329 def onchange_location_id(self,cr, uid, ids, location_id=False, context={}):
181 if not location_id:330 if not location_id:
182 return {}331 return {}
@@ -191,37 +340,73 @@
191 }}340 }}
192341
193 _columns = {342 _columns = {
194 'location_id' : fields.many2one('res.partner.location', 'Location'),343 #do not allow to delete a partner as long as jobs are related to it
344 'partner_id': fields.many2one('res.partner', 'Partner Name', ondelete='restrict', select=True, help="Keep empty for a private address, not related to partner."),
345 'location_id' : fields.many2one('res.partner.location', 'Location', ondelete='restrict',),
195 'contact_id' : fields.many2one('res.partner.contact', 'Contact'),346 'contact_id' : fields.many2one('res.partner.contact', 'Contact'),
347
348 #add private type
349 'type': fields.selection( [ ('default','Default'),('invoice','Invoice'), ('delivery','Delivery'), ('contact','Contact'), ('other','Other'), ('private', 'Private') ],'Address Type', help="Used to select automatically the right address according to the context in sales and purchases documents."),
350
351
352 #field for administer functions
353 'sequence_contact': fields.integer('Contact Seq.',help='Order of\
354 importance of this address in the list of addresses of the linked contact'),
355 'date_start': fields.date('Date Start',help="Start date of job(Joining Date)"),
356 'date_stop': fields.date('Date Stop', help="Last date of job"),
357 'state': fields.selection([('past', 'Past'),('current', 'Current')], \
358 'State', required=True, help="Status of Address"),
196359
197 # fields from location360 # fields from location
198 'street': fields.related('location_id', 'street', string='Street', type="char", store=True, size=128),361 #Trigger for change of location id of self seems not required because this is handled by onchange_location_id
199 'street2': fields.related('location_id', 'street2', string='Street2', type="char", store=True, size=128),362 # triggered in the form, but this does not properly store the values!. None looks at any fields for change
200 'zip': fields.related('location_id', 'zip', string='Zip', type="char", store=True, change_default=True, size=24),363 'street': fields.related('location_id', 'street', string='Street',
201 'city': fields.related('location_id', 'city', string='City', type="char", store=True, size=128),364 type="char", size=128, readonly=True,
202 'state_id': fields.related('location_id', 'state_id', relation="res.country.state", string='Fed. State', type="many2one", store=True, domain="[('country_id','=',country_id)]"),365 store = { 'res.partner.address': (lambda self, cr, uid, ids, c={}: ids, ['location_id'], 5),
203 'country_id': fields.related('location_id', 'country_id', type='many2one', string='Country', store=True, relation='res.country'),366 'res.partner.location': (_get_address_from_location_ids, None, 10),}),
367 'street2': fields.related('location_id', 'street2', string='Street2',
368 type="char", size=128, readonly=True,
369 store = {'res.partner.address': (lambda self, cr, uid, ids, c={}: ids, ['location_id'], 5),
370 'res.partner.location': (_get_address_from_location_ids, None, 10),}),
371 'zip': fields.related('location_id', 'zip', string='Zip',
372 type="char", change_default=True, size=24, readonly=True,
373 store = {'res.partner.address': (lambda self, cr, uid, ids, c={}: ids, ['location_id'], 5),
374 'res.partner.location': (_get_address_from_location_ids, None, 10),}),
375 'city': fields.related('location_id', 'city', string='City',
376 type="char", size=128, readonly=True,
377 store = {'res.partner.address': (lambda self, cr, uid, ids, c={}: ids, ['location_id'], 5),
378 'res.partner.location': (_get_address_from_location_ids, None, 10),}),
379 'state_id': fields.related('location_id', 'state_id', relation="res.country.state",
380 string='Fed. State', type="many2one",
381 domain="[('country_id','=',country_id)]", readonly=True,
382 store = {'res.partner.address': (lambda self, cr, uid, ids, c={}: ids, ['location_id'], 5),
383 'res.partner.location': (_get_address_from_location_ids, None, 10),}),
384 'country_id': fields.related('location_id', 'country_id', type='many2one',
385 string='Country', relation='res.country', readonly=True,
386 store = {'res.partner.address': (lambda self, cr, uid, ids, c={}: ids, ['location_id'], 5),
387 'res.partner.location': (_get_address_from_location_ids, None, 10),}),
204388
205 'phone': fields.char('Phone', size=64),389 #this field is missing compared to 6.0 implementation
206 'fax': fields.char('Fax', size=64),390 'other': fields.char('Other Phone', size=64, help='Additional phone field'),
207 'email': fields.char('E-Mail', size=240),
208391
209 # fields from contact392 # fields from contact
210 'mobile' : fields.related('contact_id', 'mobile', type='char', size=64, string='Mobile'),393 'mobile' : fields.related('contact_id', 'mobile', type='char', size=64, string='Mobile'),
211 'name' : fields.related('contact_id', 'name', type='char', size=64, string="Contact Name", store=True),394 #store = {'res.partner.contact': (_get_address_from_contact_ids, ['mobile'], 10),
212 'title' : fields.related('contact_id', 'title', type='many2one', relation='res.partner.title', string="Title", store=True),395 # 'res.partner.address': (_get_own_addresses,['contact_id'], 20)}), @bug: query wants to store in crm_lead!!!!
396 'name' : fields.related('contact_id', 'name', type='char', size=64, string="Contact Name",
397 store = {'res.partner.contact': (_get_address_from_contact_ids, ['last_name', 'first_name'], 10),
398 'res.partner.address': (_get_own_addresses,['contact_id'], 20)}),
399 'title' : fields.related('contact_id', 'title', type='many2one', relation='res.partner.title', string="Title"),
213 }400 }
214 def create(self, cr, uid, data, context={}):401 def create(self, cr, uid, data, context={}):
215 if not data.get('location_id', False):402 if data.get('location_id', False):
216 loc_id = self.pool.get('res.partner.location').create(cr, uid, {403 location = self.pool.get('res.partner.location').browse(cr, uid, [data['location_id']])[0]
217 'street': data.get('street',''),404 data['street'] = location.street or False
218 'street2': data.get('street2',''),405 data['street2'] = location.street2 or False
219 'zip': data.get('zip',''),406 data['zip'] = location.zip or False
220 'city': data.get('city',''),407 data['city'] = location.city or False
221 'country_id': data.get('country_id',False),408 data['country_id'] = location.country_id and location.country_id.id or False
222 'state_id': data.get('state_id',False)409 data['state_id'] = location.state_id and location.state_id.id or False
223 }, context=context)
224 data['location_id'] = loc_id
225 result = super(res_partner_address, self).create(cr, uid, data, context=context)410 result = super(res_partner_address, self).create(cr, uid, data, context=context)
226 return result411 return result
227412
@@ -229,26 +414,82 @@
229 result = {}414 result = {}
230 for rec in self.browse(cr,uid, ids, context=context):415 for rec in self.browse(cr,uid, ids, context=context):
231 res = []416 res = []
417 if rec.contact_id and rec.contact_id.name:
418 res.append(rec.contact_id.name)
232 if rec.partner_id:419 if rec.partner_id:
233 res.append(rec.partner_id.name_get()[0][1])420 res.append(rec.partner_id.name_get()[0][1])
234 if rec.contact_id and rec.contact_id.name:
235 res.append(rec.contact_id.name)
236 if rec.location_id:421 if rec.location_id:
422 if rec.location_id.street: res.append(rec.location_id.street)
237 if rec.location_id.city: res.append(rec.location_id.city)423 if rec.location_id.city: res.append(rec.location_id.city)
238 if rec.location_id.country_id: res.append(rec.location_id.country_id.name_get()[0][1])424 if rec.location_id.country_id: res.append(rec.location_id.country_id.name_get()[0][1])
239 result[rec.id] = ', '.join(res)425 result[rec.id] = ', '.join(res)
240 return result.items()426 return result.items()
241427
242 _defaults = {428 _defaults = {
243 'location_id': _default_location_id429 'location_id': _default_location_id,
430 'sequence_contact' : lambda *a: 0,
431 'state': lambda *a: 'current',
244 }432 }
433
434 def name_search(self, cr, uid, name='', args=None, operator='ilike', context=None, limit=None):
435 """
436 Search function searches in (contact) name and partner_id depending on context
437 while using otherwise the standard implementation
438 """
439 if not args:
440 args = []
441 if context is None:
442 context = {}
443
444 if name and context.get('contact_display', 'contact') == 'partner':
445 ids = self.search(cr, uid, ['|',('name', operator, name),('partner_id', operator, name)] + args, limit=limit, context=context)
446 return self.name_get(cr, uid, ids, context=context)
447 else:
448 return super(res_partner_address, self).name_search(cr, uid, name, args, operator, context, limit)
449
450
451
452 #order by name. default addresses are assumed to have no name = empty -> are last entry!
453 _order='state, name, sequence_contact'
454
455
245456
246 def default_get(self, cr, uid, fields=[], context=None):457 def default_get(self, cr, uid, fields=[], context=None):
247 if context is None:458 if context is None:
248 context = {}459 context = {}
249 if 'default_type' in context:460 #if 'default_type' in context:
250 del context['default_type']461 # del context['default_type']
251 return super(res_partner_address, self).default_get(cr, uid, fields, context)462 return super(res_partner_address, self).default_get(cr, uid, fields, context)
252463
253res_partner_address()464res_partner_address()
254465
466class res_partner(osv.osv):
467 _inherit = 'res.partner'
468
469 def _default_address_id(self, cr, uid, ids, prop, unknow_none, context=None):
470
471 res = dict.fromkeys(ids, False)
472
473 all_ids = self.pool.get('res.partner.address').search(cr, uid, [('partner_id','in',ids), ('type','=','default')])
474
475 addresses = self.pool.get('res.partner.address').browse(cr, uid, all_ids)
476 for addr in addresses:
477 if(res[addr.partner_id.id] == False):
478 res[addr.partner_id.id] = addr.id
479
480 return res
481
482
483 _columns = {#default_address_id has to be stored to enable search of the related fields!!! Somehow trigger is not required!
484 'default_address_id': fields.function(_default_address_id, type='many2one', obj='res.partner.address', string='address_id', store = True),
485 'phone': fields.related('default_address_id', 'phone', type='char', string='Phone'),
486 'fax': fields.related('default_address_id', 'fax', type='char', string='Fax', store = False),
487 'email': fields.related('default_address_id', 'email', type='char', size=240, string='E-mail', store = False),
488 'street': fields.related('default_address_id', 'street', type='char', string='Street', store = False),
489 'city': fields.related('default_address_id', 'city', type='char', string='City', store = False),
490 'country': fields.related('default_address_id','country_id', type='many2one', relation='res.country', string='Country'),
491 }
492
493res_partner()
494
495
255496
=== modified file 'base_contact/base_contact_view.xml'
--- base_contact/base_contact_view.xml 2012-01-31 13:36:57 +0000
+++ base_contact/base_contact_view.xml 2015-01-16 20:04:03 +0000
@@ -1,6 +1,106 @@
1<?xml version="1.0" encoding="utf-8"?>1<?xml version="1.0" encoding="utf-8"?>
2<openerp>2<openerp>
3<data>3<data>
4
5 <!-- Address views -->
6
7 <record id="view_partner_address_tree" model="ir.ui.view">
8 <field name="name">res.partner.address.tree</field>
9 <field name="model">res.partner.address</field>
10 <field name="inherit_id" ref="base.view_partner_address_tree"/>
11 <field name="type">tree</field>
12 <field name="context">{"search_default_state": "current"}</field>
13 <field name="arch" type="xml">
14 <tree string="Partner Addresses" position="replace">
15 <tree string="Addresses" colors="gray:state in ('past')">
16 <field name="name"/>
17 <field name="partner_id"/>
18 <field name="function"/>
19 <field name="email"/>
20 <field name="phone"/>
21 <field name="mobile"/>
22 <field name="other" />
23 <field name="country_id"/>
24 <field name="type"/>
25 <field name="state" />
26 </tree>
27 </tree>
28 </field>
29 </record>
30
31 <record id="view_res_partner_address_filter" model="ir.ui.view">
32 <field name="name">res.partner.address.select</field>
33 <field name="model">res.partner.address</field>
34 <field name="inherit_id" ref="base.view_res_partner_address_filter"/>
35 <field name="type">search</field>
36 <field name="arch" type="xml">
37 <search string="Search Contact" position="replace" >
38 <search string="Search Address">
39 <group>
40 <field name="partner_id" string="Partner"/>
41 <field name="name" string="Contact (Lastname(s) Firstname(s))" />
42 <field name="function"/>
43 <field name="street" />
44 <field name="city" />
45 <field name="country_id" />
46 <field name="type" />
47 <field name="state" />
48 </group>
49 <newline/>
50 <group expand="0" string="Group By...">
51 <filter string="Partner" icon="terp-personal" domain="[]" context="{'group_by' : 'partner_id'}" />
52 <filter string="Function" icon="terp-go-home" domain="[]" context="{'group_by' : 'function'}" />
53 <filter string="Type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'type'}" />
54 <filter string="State" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'state'}" />
55 </group>
56 </search>
57 </search>
58 </field>
59 </record>
60
61 <!-- Address Tree view for Contact -->
62 <record id="view_partner_address_tree_contact" model="ir.ui.view">
63 <field name="name">res.partner.address.tree.contact</field>
64 <field name="model">res.partner.address</field>
65 <field name="type">tree</field>
66 <field eval="17" name="priority"/>
67 <field name="arch" type="xml">
68 <tree string="Functions and Addresses" colors="gray:state in ('past')">
69 <field name="partner_id"/>
70 <field name="location_id"/>
71 <field name="function"/>
72 <field name="email" widget="email"/>
73 <field name="phone"/>
74 <field name="other" />
75 <field name="fax"/>
76 <field name="type"/>
77 <field name="state" />
78 <field name="sequence_contact" string="Seq."/>
79 </tree>
80 </field>
81 </record>
82
83 <!-- Adress Tree view for Partner -->
84 <record id="view_partner_address_tree_partner" model="ir.ui.view">
85 <field name="name">res.partner.address.tree.partner</field>
86 <field name="model">res.partner.address</field>
87 <field name="type">tree</field>
88 <field eval="18" name="priority"/>
89 <field name="arch" type="xml">
90 <tree string="Functions and Addresses" colors="gray:state in ('past')" >
91 <field name="name"/>
92 <field name="location_id"/>
93 <field name="function"/>
94 <field name="email" widget="email"/>
95 <field name="phone"/>
96 <field name="mobile"/>
97 <field name="other" />
98 <field name="fax"/>
99 <field name="type"/>
100 <field name="state" />
101 </tree>
102 </field>
103 </record>
4104
5 <!-- Views for Contacts Tree View -->105 <!-- Views for Contacts Tree View -->
6106
@@ -9,8 +109,8 @@
9 <field name="model">res.partner.contact</field>109 <field name="model">res.partner.contact</field>
10 <field name="type">tree</field>110 <field name="type">tree</field>
11 <field name="arch" type="xml">111 <field name="arch" type="xml">
12 <tree string="Partner Contact">112 <tree string="Contact">
13 <field name="name"/>113 <field name="last_name"/>
14 <field name="first_name"/>114 <field name="first_name"/>
15 <field name="mobile"/>115 <field name="mobile"/>
16 <field name="email"/>116 <field name="email"/>
@@ -28,7 +128,7 @@
28 <field name="model">res.partner.contact</field>128 <field name="model">res.partner.contact</field>
29 <field name="type">form</field>129 <field name="type">form</field>
30 <field name="arch" type="xml">130 <field name="arch" type="xml">
31 <form string="Partner Contact">131 <form string="Contact">
32 <group colspan="4" col="6">132 <group colspan="4" col="6">
33 <field name="last_name" select="1"/>133 <field name="last_name" select="1"/>
34 <field name="first_name" select="1"/>134 <field name="first_name" select="1"/>
@@ -48,22 +148,7 @@
48 <field name="photo" widget='image' nolabel="1"/>148 <field name="photo" widget='image' nolabel="1"/>
49 </group>149 </group>
50 </group>150 </group>
51 <field name="job_ids" colspan="4" nolabel="1" mode="tree,form">151 <field name="job_ids" colspan="4" nolabel="1" mode="tree,form" context="{'tree_view_ref' : 'base_contact.view_partner_address_tree_contact', 'default_contact_id': active_id, 'default_type': 'contact'}">
52 <form string="Functions and Addresses">
53 <field name="partner_id" />
54 <field name="location_id" domain="[('partner_id', '=', partner_id)]"/>
55 <field name="function" />
56 <separator string="Professional Info" colspan="4"/>
57 <field name="phone"/>
58 <field name="fax"/>
59 <field name="email" widget="email"/>
60 </form>
61 <tree string="Functions and Addresses">
62 <field name="location_id"/>
63 <field name="function"/>
64 <field name="phone"/>
65 <field name="email"/>
66 </tree>
67 </field>152 </field>
68 </page>153 </page>
69 <page string="Extra Information">154 <page string="Extra Information">
@@ -90,15 +175,15 @@
90 <field name="model">res.partner.contact</field>175 <field name="model">res.partner.contact</field>
91 <field name="type">search</field>176 <field name="type">search</field>
92 <field name="arch" type="xml">177 <field name="arch" type="xml">
93 <search string="Partner Contact">178 <search string="Contact">
94 <field name="name" string="First/Lastname"179 <field name="last_name" />
95 filter_domain="['|', ('first_name','ilike', self), ('last_name', 'ilike', self)]"/>180 <field name="first_name" />
96 <field name="partner_id" string="Partner"/>181 <field name="partner_id" string="Partner"/>
97 </search>182 </search>
98 </field>183 </field>
99 </record>184 </record>
100185
101<!-- Views for Contacts Action -->186 <!-- Views for Contacts Action and menu -->
102187
103 <record model="ir.actions.act_window" id="action_partner_contact_form">188 <record model="ir.actions.act_window" id="action_partner_contact_form">
104 <field name="name">Contacts</field>189 <field name="name">Contacts</field>
@@ -110,11 +195,27 @@
110 </record>195 </record>
111 <menuitem name="Contacts" id="menu_partner_contact_form" action="action_partner_contact_form" parent = "base.menu_address_book" sequence="2"/>196 <menuitem name="Contacts" id="menu_partner_contact_form" action="action_partner_contact_form" parent = "base.menu_address_book" sequence="2"/>
112197
113 <!-- Rename menuitem for partner addresses -->198 <!-- Views for Address Action and menu -->
114 <record model="ir.ui.menu" id="base.menu_partner_address_form">199 <record id="action_partner_address_form" model="ir.actions.act_window">
115 <field name="name">Addresses</field>200 <field name="name">Addresses</field>
201 <field name="type">ir.actions.act_window</field>
202 <field name="res_model">res.partner.address</field>
203 <field name="view_type">form</field>
204 <field name="view_mode">tree,form,kanban</field>
205 <field name="context"> {"search_default_state": "current"}</field>
206 <field name="search_view_id" ref="view_res_partner_address_filter"/>
207 <field name="help">Address helps you manage your contacts jobs wether they are private, main/switchboard or contacts.</field>
116 </record>208 </record>
117209
210 <!-- Replace menuitem with new action
211 delete action window as menu deletion did not work -->
212 <delete model="ir.actions.act_window" id="base.action_partner_address_form" />
213
214 <menuitem action="action_partner_address_form" id="menu_partner_address_form"
215 name="Addresses"
216 parent="base.menu_address_book" sequence="30"/>
217
218
118 <!--219 <!--
119 Contacts for Suppliers220 Contacts for Suppliers
120 -->221 -->
@@ -126,8 +227,13 @@
126 parent="base.menu_procurement_management_supplier" action="base.action_partner_supplier_form" sequence="1"/>227 parent="base.menu_procurement_management_supplier" action="base.action_partner_supplier_form" sequence="1"/>
127 <menuitem name="Contacts" id="menu_purchases_partner_contact_form" action="action_partner_contact_form"228 <menuitem name="Contacts" id="menu_purchases_partner_contact_form" action="action_partner_contact_form"
128 parent = "base.menu_procurement_management_supplier" sequence="2"/>229 parent = "base.menu_procurement_management_supplier" sequence="2"/>
230
231 <menuitem action="action_partner_address_form" id="menu_purchase_partner_address_form"
232 name="Addresses"
233 parent="base.menu_procurement_management_supplier" sequence="30"/>
234
129235
130 <!-- Views for Partners Form View -->236 <!-- Views for Partner -->
131237
132 <record model="ir.ui.view" id="view_partner_form_inherit">238 <record model="ir.ui.view" id="view_partner_form_inherit">
133 <field name="name">Partner form inherited</field>239 <field name="name">Partner form inherited</field>
@@ -135,17 +241,50 @@
135 <field name="inherit_id" ref="base.view_partner_form"/>241 <field name="inherit_id" ref="base.view_partner_form"/>
136 <field name="type">form</field>242 <field name="type">form</field>
137 <field name="arch" type="xml">243 <field name="arch" type="xml">
138 <separator string="Postal Address" position="after">244 <field name="address" position="replace" >
139 <field name="location_id" on_change="onchange_location_id(location_id)" domain="[('partner_id', '=', parent.id)]"/>245 <field colspan="4" mode="tree,form" name="address" nolabel="1" select="1" height="260" context="{'tree_view_ref' : 'base_contact.view_partner_address_tree_partner', 'default_partner_id': active_id, 'default_type': 'contact'}">
140 </separator>246 </field>
141 <xpath expr="//field[@string='Contact Name']" position="replace">247 </field>
142 <field name="contact_id"/>248
143 </xpath>
144 <field name="title" position="replace"/>
145 </field>249 </field>
146 </record>250 </record>
147251
148 <!-- Views for Addresses -->252 <record id="view_partner_tree" model="ir.ui.view">
253 <field name="name">res.partner.tree</field>
254 <field name="model">res.partner</field>
255 <field name="inherit_id" ref="base.view_partner_tree"/>
256 <field name="type">tree</field>
257 <field name="arch" type="xml">
258
259 <field name="phone" position="after" >
260 <field name="fax"/>
261 </field>
262
263 <field name="city" position="before" >
264 <field name="street"/>
265 </field>
266
267 </field>
268 </record>
269
270 <record id="view_res_partner_filter" model="ir.ui.view">
271 <field name="name">res.partner.select</field>
272 <field name="model">res.partner</field>
273 <field name="inherit_id" ref="base.view_res_partner_filter"/>
274 <field name="type">search</field>
275 <field name="arch" type="xml">
276
277
278 <field name="country" position="before">
279 <field name="street" select="1"/>
280 <field name="city" select="1"/>
281 </field>
282
283 </field>
284 </record>
285
286
287 <!-- Views for Location -->
149288
150 <record model="ir.ui.view" id="view_partner_location_form">289 <record model="ir.ui.view" id="view_partner_location_form">
151 <field name="name">res.partner.location.form</field>290 <field name="name">res.partner.location.form</field>
@@ -153,12 +292,24 @@
153 <field name="type">form</field>292 <field name="type">form</field>
154 <field name="arch" type="xml">293 <field name="arch" type="xml">
155 <form string="Locations">294 <form string="Locations">
295 <field name="partner_id" readonly="1" />
156 <field name="street" colspan="4"/>296 <field name="street" colspan="4"/>
157 <field name="street2" colspan="4"/>297 <field name="street2" colspan="4"/>
158 <field name="zip"/>298 <field name="zip"/>
159 <field name="city"/>299 <field name="city"/>
160 <field name="country_id" />300 <field name="country_id" />
161 <field name="state_id"/>301 <field name="state_id"/>
302 <newline />
303 <separator string="Addresses" colspan="4" />
304 <field name="job_ids" nolabel="1" colspan="4" readonly="1" mode="tree">
305 <tree string="Address">
306 <field name = "contact_id" />
307 <field name = "partner_id" />
308 <field name = "function" />
309 <field name = "type" />
310 <field name = "state" />
311 </tree>
312 </field>
162 </form>313 </form>
163 </field>314 </field>
164 </record>315 </record>
@@ -170,6 +321,9 @@
170 <field name="type">tree</field>321 <field name="type">tree</field>
171 <field name="arch" type="xml">322 <field name="arch" type="xml">
172 <tree string="Locations">323 <tree string="Locations">
324 <field name="partner_id" string="Partner" />
325 <field name="contact_id" />
326 <field name="street" />
173 <field name="city"/>327 <field name="city"/>
174 <field name="country_id" />328 <field name="country_id" />
175 <field name="state_id"/>329 <field name="state_id"/>
@@ -177,19 +331,77 @@
177 </field>331 </field>
178 </record>332 </record>
179333
334 <record model="ir.ui.view" id="view_partner_location_search">
335 <field name="name">res.partner.location.search</field>
336 <field name="model">res.partner.location</field>
337 <field name="type">search</field>
338 <field name="arch" type="xml">
339 <search string="Partner Location">
340 <field name="partner_id" string="Partner"/>
341 <field name="job_ids" />
342 <field name="street" />
343 <field name="city" />
344 <field name="country_id" />
345 </search>
346 </field>
347 </record>
348
349
350 <record model="ir.actions.act_window" id="action_partner_location_form">
351 <field name="name">Locations</field>
352 <field name="res_model">res.partner.location</field>
353 <field name="view_type">form</field>
354 <field name="view_mode">tree,form</field>
355 <field name="view_id" ref="view_partner_location_tree"/>
356 <field name="search_view_id" ref="view_partner_location_search"/>
357 </record>
358 <!-- sequence=30 is because 11 is not enough for beeing below addresses to be checked further -->
359 <menuitem name="Locations" id="menu_partner_location_form" action="action_partner_location_form"
360 parent = "base.menu_address_book" groups="base.group_extended" sequence="40"/>
361 <menuitem name="Locations" id="menu_purchase_partner_location_form" action="action_partner_location_form"
362 parent = "base.menu_procurement_management_supplier" groups="base.group_extended" sequence="40"/>
363
364
365 <!-- Update default address view -->
366
180 <record model="ir.ui.view" id="view_partner_address_form_inherited0">367 <record model="ir.ui.view" id="view_partner_address_form_inherited0">
181 <field name='name'>res.partner.address.form.inherited0</field>368 <field name='name'>res.partner.address.form.inherited0</field>
182 <field name='model'>res.partner.address</field>369 <field name='model'>res.partner.address</field>
183 <field name="inherit_id" ref="base.view_partner_address_form1"/>370 <field name="inherit_id" ref="base.view_partner_address_form1"/>
184 <field name='type'>form</field>371 <field name='type'>form</field>
185 <field name='arch' type='xml'>372 <field name='arch' type='xml'>
373
374 <field name="partner_id" position="replace">
375 <field name="partner_id" colspan="2" on_change="onchange_partner_id(partner_id)" attrs="{'required':[('contact_id','=', False)]}"/>
376 </field>
377
186 <field name="name" position="replace">378 <field name="name" position="replace">
187 <field name="contact_id"/>379 <field name="contact_id" on_change="onchange_contact_id(contact_id)" attrs="{'required':[('partner_id','=', False)]}"/>
188 </field>380 <!-- <field name="name" string="use this field for initial name only" /> would require adaption of create-->
381 </field>
382
383 <field name="type" position="replace">
384 <field name="type" required="1"/>
385 </field>
386 <field name="mobile" position="after">
387 <field name="other" />
388
389 </field>
189 <separator string="Postal Address" position="after">390 <separator string="Postal Address" position="after">
190 <field name="location_id" on_change="onchange_location_id(location_id)"/>391 <field name="location_id" required="1"
392 on_change="onchange_location_id(location_id)"
393 domain="[('partner_id', '=', partner_id)]"
394 context="{'default_partner_id': partner_id}"/>
191 </separator>395 </separator>
192 <field name="title" position="replace"/>396 <field name="title" position="replace"/>
397 <field name="function" position="after">
398 <separator string="Status" colspan="6"/>
399 <field name="state" />
400 <field name="date_start" />
401 <field name="date_stop" />
402 <separator string="Sequence" colspan="6" col="2"/>
403 <field name="sequence_contact" string="Contact Seq."/>
404 </field>
193 </field>405 </field>
194 </record>406 </record>
195407
196408
=== modified file 'base_contact/security/ir.model.access.csv'
--- base_contact/security/ir.model.access.csv 2012-01-31 13:36:57 +0000
+++ base_contact/security/ir.model.access.csv 2015-01-16 20:04:03 +0000
@@ -1,7 +1,8 @@
1"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"1"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
2"access_res_partner_contact","res.partner.contact","model_res_partner_contact","base.group_partner_manager",1,1,1,12"access_res_partner_contact","res.partner.contact","model_res_partner_contact","base.group_partner_manager",1,1,1,1
3"access_res_partner_contact_all","res.partner.contact all","model_res_partner_contact","base.group_user",1,0,0,03"access_res_partner_contact_all","res.partner.contact all","model_res_partner_contact","base.group_user",1,0,0,0
4"access_res_partner_location","res.partner.location","model_res_partner_location","base.group_user",1,0,0,04"access_res_partner_location_manager","res.partner.location","model_res_partner_location","base.group_partner_manager",1,1,1,1
5"access_res_partner_location_all","res.partner.location","model_res_partner_location","base.group_user",1,0,0,0
5"access_res_partner_location_sale_salesman","res.partner.location","model_res_partner_location","base.group_sale_salesman",1,1,1,06"access_res_partner_location_sale_salesman","res.partner.location","model_res_partner_location","base.group_sale_salesman",1,1,1,0
6"access_res_partner_address_sale_salesman","res.partner.address.user","base.model_res_partner_address","base.group_sale_salesman",1,1,1,07"access_res_partner_address_sale_salesman","res.partner.address.user","base.model_res_partner_address","base.group_sale_salesman",1,1,1,0
7"access_group_sale_salesman","res.partner.contact.sale.salesman","model_res_partner_contact","base.group_sale_salesman",1,1,1,08"access_group_sale_salesman","res.partner.contact.sale.salesman","model_res_partner_contact","base.group_sale_salesman",1,1,1,0
89
=== modified file 'base_report_designer/plugin/openerp_report_designer/bin/OOo_run.sh' (properties changed: +x to -x)
=== modified file 'document/odt2txt.py' (properties changed: +x to -x)
=== modified file 'document/test_cindex.py' (properties changed: +x to -x)
=== modified file 'document_ftp/ftpserver/ftpserver.py' (properties changed: +x to -x)
=== modified file 'document_webdav/test_davclient.py' (properties changed: +x to -x)
=== modified file 'email_template/html2text.py' (properties changed: +x to -x)
=== modified file 'l10n_ch/report/ocrbb.ttf' (properties changed: +x to -x)
=== modified file 'l10n_ch/test/test.v11' (properties changed: +x to -x)
=== modified file 'l10n_ch/test/test_part_1.v11' (properties changed: +x to -x)
=== modified file 'l10n_ch/test/test_part_2.v11' (properties changed: +x to -x)
=== modified file 'mail/static/scripts/openerp_mailgate.py' (properties changed: +x to -x)
=== modified file 'plugin_thunderbird/static/thunderbird_plugin/install.sh' (properties changed: +x to -x)
=== modified file 'purchase/purchase.py' (properties changed: +x to -x)
=== modified file 'purchase/wizard/purchase_line_invoice.py' (properties changed: +x to -x)
=== modified file 'purchase_double_validation/test/purchase_double_validation_test.yml' (properties changed: +x to -x)
=== modified file 'purchase_requisition/test/purchase_requisition_demo.yml' (properties changed: +x to -x)
=== modified file 'wiki/static/src/lib/wiky/Readme.md' (properties changed: +x to -x)
=== modified file 'wiki/static/src/lib/wiky/autogit.sh' (properties changed: +x to -x)
=== modified file 'wiki/static/src/lib/wiky/index.html' (properties changed: +x to -x)
=== modified file 'wiki/static/src/lib/wiky/input_complete' (properties changed: +x to -x)
=== modified file 'wiki/static/src/lib/wiky/jquery-1.4.2.min.js' (properties changed: +x to -x)
=== modified file 'wiki/static/src/lib/wiky/wiky.css' (properties changed: +x to -x)
=== modified file 'wiki/static/src/lib/wiky/wiky.js' (properties changed: +x to -x)

Subscribers

People subscribed via source and target branches