#. module: base_contact #: field:res.partner.location,city:0 Index: /media/truecrypt1/work/Openerp/trunk-addons/base_contact/security/ir.model.access.csv =================================================================== --- /media/truecrypt1/work/Openerp/trunk-addons/base_contact/security/ir.model.access.csv (revision 12877) +++ /media/truecrypt1/work/Openerp/trunk-addons/base_contact/security/ir.model.access.csv (revision 13001) @@ -1,7 +1,8 @@ "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" "access_res_partner_contact","res.partner.contact","model_res_partner_contact","base.group_partner_manager",1,1,1,1 "access_res_partner_contact_all","res.partner.contact all","model_res_partner_contact","base.group_user",1,0,0,0 -"access_res_partner_location","res.partner.location","model_res_partner_location","base.group_user",1,0,0,0 +"access_res_partner_location_manager","res.partner.location","model_res_partner_location","base.group_partner_manager",1,1,1,1 +"access_res_partner_location_all","res.partner.location","model_res_partner_location","base.group_user",1,0,0,0 "access_res_partner_location_sale_salesman","res.partner.location","model_res_partner_location","base.group_sale_salesman",1,1,1,0 "access_res_partner_address_sale_salesman","res.partner.address.user","base.model_res_partner_address","base.group_sale_salesman",1,1,1,0 "access_group_sale_salesman","res.partner.contact.sale.salesman","model_res_partner_contact","base.group_sale_salesman",1,1,1,0 Index: /media/truecrypt1/work/Openerp/trunk-addons/base_contact/base_contact.py =================================================================== --- /media/truecrypt1/work/Openerp/trunk-addons/base_contact/base_contact.py (revision 12877) +++ /media/truecrypt1/work/Openerp/trunk-addons/base_contact/base_contact.py (revision 13001) @@ -21,37 +21,80 @@ from osv import fields, osv import addons +import pdb class res_partner_contact(osv.osv): """ Partner Contact """ _name = "res.partner.contact" _description = "Contact" + + _rec_name = 'last_name' + def _name_get_full(self, cr, uid, ids, prop, unknow_none, context=None): result = {} for rec in self.browse(cr, uid, ids, context=context): - result[rec.id] = rec.last_name+' '+(rec.first_name or '') + #use firstname lastname as in the demo data of base/res/res_partner_demo.xml + if(rec.first_name): + result[rec.id] = rec.first_name+' '+rec.last_name + else: + result[rec.id] = rec.last_name + return result + + def _main_job(self, cr, uid, ids, fields, arg, context=None): + """ + @summary: Returns id and function of job with the lowest 'sequence_contact' + @param self: The object pointer + @param cr: the current row, from the database cursor, + @param uid: the current user’s ID for security checks, + @param ids: List of partner contact’s IDs + @fields: Get Fields + @param context: A standard dictionary for contextual values + @param arg: list of tuples of form [(‘name_of_the_field’, ‘operator’, value), ...]. """ + + res = dict.fromkeys(ids, False) + + all_ids = self.pool.get('res.partner.address').search(cr, uid, [('contact_id','in',ids)], order='sequence_contact') + #pdb.set_trace() + addresses = self.pool.get('res.partner.address').browse(cr, uid, all_ids) + for addr in addresses: + if(res[addr.contact_id.id] == False): + res[addr.contact_id.id] = {'partner_id': addr.partner_id.id, 'function': addr.function} + + for id in res: + if (res[id]==False): + res[id] = {'partner_id': False, 'function': False} + + return res + + def _get_contact_id_from_address(self, cr, uid, ids, context=None): + #@todo: remove obsolete function + result = {} + for addr in self.pool.get('res.partner.address').browse(cr, uid, ids, context=context): + result[addr.contact_id.id] = True + return result.keys() + + _columns = { - 'name': fields.function(_name_get_full, string='Name', size=64, type="char", store=True, select=True), + 'name': fields.function(_name_get_full, string='Name', size=64, type="char", store=False, select=True), 'last_name': fields.char('Last Name', size=64, required=True), 'first_name': fields.char('First Name', size=64), 'mobile': fields.char('Mobile', size=64), 'title': fields.many2one('res.partner.title','Title', domain=[('domain','=','contact')]), - 'website': fields.char('Website', size=120), + 'website': fields.char('Private Website', size=120), 'lang_id': fields.many2one('res.lang', 'Language'), 'job_ids': fields.one2many('res.partner.address', 'contact_id', 'Functions and Addresses'), 'country_id': fields.many2one('res.country','Nationality'), - 'birthdate': fields.date('Birth Date'), + 'birthdate': fields.char('Birthdate', size=64), 'active': fields.boolean('Active', help="If the active field is set to False,\ it will allow you to hide the partner contact without removing it."), - 'partner_id': fields.related('job_ids', 'partner_id', type='many2one',\ - relation='res.partner', string='Main Employer'), - 'function': fields.related('job_ids', 'function', type='char', \ - string='Main Function'), - 'email': fields.char('E-Mail', size=240), + #Storage for partner_id and function not fully worked and not required -> removed + 'partner_id': fields.function(_main_job, type='many2one', relation='res.partner', string='Main Employer', store = False, multi='mainjob'), + 'function': fields.function(_main_job, type='char', size=128, string='Main Function', store = False, multi='mainjob'), + 'email': fields.char('Private E-Mail', size=240), 'comment': fields.text('Notes', translate=True), 'photo': fields.binary('Photo'), } @@ -65,7 +108,7 @@ 'active' : lambda *a: True, } - _order = "name" + _order = "last_name, first_name" def name_search(self, cr, uid, name='', args=None, operator='ilike', context=None, limit=None): if not args: @@ -73,7 +116,7 @@ if context is None: context = {} if name: - ids = self.search(cr, uid, ['|',('name', operator, name),('first_name', operator, name)] + args, limit=limit, context=context) + ids = self.search(cr, uid, ['|',('last_name', operator, name),('first_name', operator, name)] + args, limit=limit, context=context) else: ids = self.search(cr, uid, args, limit=limit, context=context) return self.name_get(cr, uid, ids, context=context) @@ -85,6 +128,22 @@ if obj.partner_id: result[obj.id] = result[obj.id] + ', ' + obj.partner_id.name return result.items() + + def view_init(self, cr, uid, fields, context=None): + """ + This function shall fill the first and last name if empty from context + """ + + if context is None: + context = {} + else: + default_name = context.get('default_name') + #if default_name: + #pdb.set_trace() + #The following does not work + #self._columns['last_name'] = default_name + pass + def _auto_init(self, cr, context=None): def table_exists(view_name): @@ -99,9 +158,9 @@ cr.execute(""" INSERT INTO res_partner_contact - (id,name,last_name,title,active) + (id,last_name,first_name,title,active,email,mobile,birthdate) SELECT - id,COALESCE(name, '/'),COALESCE(name, '/'),title,true + id,COALESCE(name, '/'),COALESCE(name, '/'),title,true,email,mobile,birthdate FROM res_partner_address""") cr.execute("alter table res_partner_address add contact_id int references res_partner_contact") @@ -124,6 +183,8 @@ 'job_ids': fields.one2many('res.partner.address', 'location_id', 'Contacts'), 'partner_id': fields.related('job_ids', 'partner_id', type='many2one',\ relation='res.partner', string='Main Partner'), + 'contact_id': fields.related('job_ids', 'contact_id', type='many2one',\ + relation='res.partner.contact', string='First Contact'), } _defaults = { 'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'res.partner.address', context=c), @@ -166,6 +227,29 @@ class res_partner_address(osv.osv): _inherit = 'res.partner.address' + + def _get_address_from_location_ids(self, cr, uid, ids, context=None): + result = {} + #if self._name=="res.partner.location": + for addr in self.pool.get('res.partner.address').search(cr, uid, [('location_id','in',ids)]): + result[addr] = True + #else: + #raise osv.except_osv(_('getAddressFromLocation'), self._name) + + return result.keys() + + def _get_address_from_contact_ids(self, cr, uid, ids, context=None): + result = {} + for addr in self.pool.get('res.partner.address').search(cr, uid, [('contact_id','in',ids)]): + result[addr] = True + return result.keys() + + def _get_own_addresses(self, cr, uid, ids, context=None): + result = {} + for id in ids: + result[id] = True + return result.keys() + def _default_location_id(self, cr, uid, context=None): if context is None: @@ -175,6 +259,17 @@ ids = self.pool.get('res.partner.location').search(cr, uid, [('partner_id','=',context['default_partner_id'])], context=context) return ids and ids[0] or False + def onchange_contact_id(self,cr, uid, ids, contact_id=False, context={}): + if not contact_id: + return {} + contact = self.pool.get('res.partner.contact').browse(cr, uid, contact_id, context=context) + return {'value':{ + 'mobile': contact.mobile, + 'name': contact.name, + 'title': contact.title and contact.title.id or False, + }} + + def onchange_location_id(self,cr, uid, ids, location_id=False, context={}): if not location_id: return {} @@ -191,23 +286,49 @@ _columns = { 'location_id' : fields.many2one('res.partner.location', 'Location'), 'contact_id' : fields.many2one('res.partner.contact', 'Contact'), + + #field for administer functions + 'sequence_contact': fields.integer('Contact Seq.',help='Order of\ + importance of this address in the list of addresses of the linked contact'), + 'sequence_partner': fields.integer('Partner Seq.',help='Order of importance\ + of this job title in the list of job title of the linked partner'), + 'date_start': fields.date('Date Start',help="Start date of job(Joining Date)"), + 'date_stop': fields.date('Date Stop', help="Last date of job"), + 'state': fields.selection([('past', 'Past'),('current', 'Current')], \ + 'State', required=True, help="Status of Address"), # fields from location - 'street': fields.related('location_id', 'street', string='Street', type="char", store=True, size=128), - 'street2': fields.related('location_id', 'street2', string='Street2', type="char", store=True, size=128), - 'zip': fields.related('location_id', 'zip', string='Zip', type="char", store=True, change_default=True, size=24), - 'city': fields.related('location_id', 'city', string='City', type="char", store=True, size=128), - 'state_id': fields.related('location_id', 'state_id', relation="res.country.state", string='Fed. State', type="many2one", store=True, domain="[('country_id','=',country_id)]"), - 'country_id': fields.related('location_id', 'country_id', type='many2one', string='Country', store=True, relation='res.country'), + #Trigger for change of location id of self is not required because this is handled by onchange_location_id triggered in the only form! + 'street': fields.related('location_id', 'street', string='Street', type="char", size=128, + store = {'res.partner.location': (_get_address_from_location_ids, ['street'], 10),}), + 'street2': fields.related('location_id', 'street2', string='Street2', type="char", size=128, + store = {'res.partner.location': (_get_address_from_location_ids, ['street2'], 10),}), + 'zip': fields.related('location_id', 'zip', string='Zip', type="char", change_default=True, size=24, + store = {'res.partner.location': (_get_address_from_location_ids, ['zip'], 10),}), + 'city': fields.related('location_id', 'city', string='City', type="char", size=128, + store = {'res.partner.location': (_get_address_from_location_ids, ['city'], 10),}), + 'state_id': fields.related('location_id', 'state_id', relation="res.country.state", string='Fed. State', type="many2one", domain="[('country_id','=',country_id)]", + store = {'res.partner.location': (_get_address_from_location_ids, ['state_id'], 10),}), + 'country_id': fields.related('location_id', 'country_id', type='many2one', string='Country', relation='res.country', + store = {'res.partner.location': (_get_address_from_location_ids, ['country_id'], 10),}), - 'phone': fields.char('Phone', size=64), - 'fax': fields.char('Fax', size=64), - 'email': fields.char('E-Mail', size=240), + #These fields exists + #'phone': fields.char('Phone', size=64), + #'fax': fields.char('Fax', size=64), + #'email': fields.char('E-Mail', size=240), + #this field is missing + 'other': fields.char('Other Phone', size=64, help='Additional phone field'), # fields from contact 'mobile' : fields.related('contact_id', 'mobile', type='char', size=64, string='Mobile'), - 'name' : fields.related('contact_id', 'name', type='char', size=64, string="Contact Name", store=True), - 'title' : fields.related('contact_id', 'title', type='many2one', relation='res.partner.title', string="Title", store=True), + #store = {'res.partner.contact': (_get_address_from_contact_ids, ['mobile'], 10), + # 'res.partner.address': (_get_own_addresses,['contact_id'], 20)}), @bug: query wants to store in crm_lead!!!! + 'name' : fields.related('contact_id', 'name', type='char', size=64, string="Contact Name", + store = {'res.partner.contact': (_get_address_from_contact_ids, ['last_name', 'first_name'], 10), + 'res.partner.address': (_get_own_addresses,['contact_id'], 20)}), + 'title' : fields.related('contact_id', 'title', type='many2one', relation='res.partner.title', string="Title"), + #store = {'res.partner.contact': (_get_address_from_contact_ids, ['title'], 10), + # 'res.partner.address': (_get_own_addresses,['contact_id'], 20)}), } def create(self, cr, uid, data, context={}): if not data.get('location_id', False): @@ -238,9 +359,16 @@ return result.items() _defaults = { - 'location_id': _default_location_id + 'location_id': _default_location_id, + 'sequence_contact' : lambda *a: 0, + 'sequence_partner' : lambda *a: 10, + 'state': lambda *a: 'current', } + + _order='sequence_partner, type, name' + + def default_get(self, cr, uid, fields=[], context=None): if context is None: context = {} Index: /media/truecrypt1/work/Openerp/trunk-addons/base_contact/base_contact_view.xml =================================================================== --- /media/truecrypt1/work/Openerp/trunk-addons/base_contact/base_contact_view.xml (revision 12877) +++ /media/truecrypt1/work/Openerp/trunk-addons/base_contact/base_contact_view.xml (revision 13001) @@ -1,6 +1,52 @@ + + + + + + res.partner.address.tree.contact + res.partner.address + tree + + + + + + + + + + + + + + + + + + + res.partner.address.tree.partner + res.partner.address + tree + + + + + + + + + + + + + + + + + @@ -10,7 +56,7 @@ tree - + @@ -48,22 +94,7 @@ - -
- - - - - - - - - - - - - - + @@ -93,7 +124,7 @@ - + @@ -127,6 +158,8 @@ + + @@ -135,30 +168,37 @@ form - - - - - - - + + + + + + + + - - res.partner.location.form res.partner.location form
+ + + + + + + +
@@ -170,6 +210,9 @@ tree + + + @@ -177,6 +220,34 @@ + + res.partner.location.search + res.partner.location + search + + + + + + + + + + + Locations + res.partner.location + form + tree,form + + + + + + + + + + res.partner.address.form.inherited0 res.partner.address @@ -184,12 +255,22 @@ form - + + - + + + + + + + + + +