[FIX+merge] base_contact

bzr revid: fp@tinyerp.com-20111217095149-14s6jj7h6cjj1lce
This commit is contained in:
Fabien Pinckaers 2011-12-17 10:51:49 +01:00
commit d50878f312
12 changed files with 234 additions and 549 deletions

View File

@ -20,7 +20,6 @@
##############################################################################
import base_contact
import base_contact_installer
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -47,7 +47,6 @@ Pay attention that this module converts the existing addresses into "addresses +
'update_xml': [
'security/ir.model.access.csv',
'base_contact_view.xml',
'base_contact_installer_view.xml',
'process/base_contact_process.xml'
],
'demo_xml': ['base_contact_demo.xml'],

View File

@ -20,6 +20,7 @@
##############################################################################
from osv import fields, osv
import addons
class res_partner_contact(osv.osv):
""" Partner Contact """
@ -27,27 +28,6 @@ class res_partner_contact(osv.osv):
_name = "res.partner.contact"
_description = "Contact"
def _main_job(self, cr, uid, ids, fields, arg, context=None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of partner contacts 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)
res_partner_job_obj = self.pool.get('res.partner.job')
all_job_ids = res_partner_job_obj.search(cr, uid, [])
all_job_names = dict(zip(all_job_ids, res_partner_job_obj.name_get(cr, uid, all_job_ids, context=context)))
for contact in self.browse(cr, uid, ids, context=context):
if contact.job_ids:
res[contact.id] = all_job_names.get(contact.job_ids[0].id, False)
return res
_columns = {
'name': fields.char('Last Name', size=64, required=True),
'first_name': fields.char('First Name', size=64),
@ -55,53 +35,32 @@ class res_partner_contact(osv.osv):
'title': fields.many2one('res.partner.title','Title'),
'website': fields.char('Website', size=120),
'lang_id': fields.many2one('res.lang', 'Language'),
'job_ids': fields.one2many('res.partner.job', 'contact_id', 'Functions and Addresses'),
'job_ids': fields.one2many('res.partner.address', 'contact_id', 'Functions and Addresses'),
'country_id': fields.many2one('res.country','Nationality'),
'birthdate': fields.date('Birth Date'),
'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', 'address_id', 'partner_id', type='many2one',\
'partner_id': fields.related('job_ids', 'location_id', 'partner_id', type='many2one',\
relation='res.partner', string='Main Employer'),
'function': fields.related('job_ids', 'function', type='char', \
string='Main Function'),
'job_id': fields.function(_main_job, type='many2one',\
relation='res.partner.job', string='Main Job'),
'email': fields.char('E-Mail', size=240),
'comment': fields.text('Notes', translate=True),
'photo': fields.binary('Image'),
'photo': fields.binary('Photo'),
}
def _get_photo(self, cr, uid, context=None):
photo_path = addons.get_module_resource('base_contact', 'images', 'photo.png')
return open(photo_path, 'rb').read().encode('base64')
_defaults = {
'photo' : _get_photo,
'active' : lambda *a: True,
}
_order = "name,first_name"
def name_get(self, cr, user, ids, context=None):
""" will return name and first_name.......
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param user: the current users ID for security checks,
@param ids: List of create menus IDs
@return: name and first_name
@param context: A standard dictionary for contextual values
"""
if not len(ids):
return []
res = []
for contact in self.browse(cr, user, ids, context=context):
_contact = ""
if contact.title:
_contact += "%s "%(contact.title.name)
_contact += contact.name or ""
if contact.name and contact.first_name:
_contact += " "
_contact += contact.first_name or ""
res.append((contact.id, _contact))
return res
def name_search(self, cr, uid, name='', args=None, operator='ilike', context=None, limit=None):
if not args:
args = []
@ -112,151 +71,154 @@ class res_partner_contact(osv.osv):
else:
ids = self.search(cr, uid, args, limit=limit, context=context)
return self.name_get(cr, uid, ids, context=context)
def name_get(self, cr, uid, ids, context=None):
return [
(obj.id, " ".join(filter(None, [obj.first_name, obj.name])),)
for obj in self.browse(cr, uid, ids, context=context)
]
res_partner_contact()
class res_partner(osv.osv):
_inherit = 'res.partner'
_columns = {
'address': fields.one2many('res.partner.location', 'partner_id', 'Address')
}
res_partner()
class res_partner_location(osv.osv):
_name = 'res.partner.location'
_inherit = 'res.partner.address'
_columns = {
'job_ids': fields.one2many('res.partner.address', 'location_id', 'Contacts'),
}
def _auto_init(self, cr, context=None):
def table_exists(view_name):
cr.execute('SELECT count(relname) FROM pg_class WHERE relname = %s', (view_name,))
value = cr.fetchone()[0]
return bool(value == 1)
exists = table_exists(self._table)
super(res_partner_location, self)._auto_init(cr, context)
if not exists:
sequence_name = self.pool.get('res.partner.address')._sequence
cr.execute("SELECT last_value FROM " + sequence_name)
last_sequence = cr.fetchone()[0]
cr.execute("INSERT INTO res_partner_location SELECT * FROM res_partner_address")
cr.execute("ALTER SEQUENCE " + self._sequence + " RESTART WITH " + str(last_sequence + 10))
def name_get(self, cr, uid, ids, context=None):
return [
((obj.id, "%s, %s" % (obj.city, obj.country_id and obj.country_id.name or '')))
for obj in self.browse(cr, uid, ids, context=context)
]
res_partner_location()
class res_partner_address(osv.osv):
#overriding of the name_get defined in base in order to remove the old contact name
def name_get(self, cr, user, ids, context=None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param user: the current user,
@param ids: List of partner addresss IDs
@param context: A standard dictionary for contextual values
"""
if not len(ids):
return []
res = []
if context is None:
context = {}
for r in self.read(cr, user, ids, ['zip', 'city', 'partner_id', 'street']):
if context.get('contact_display', 'contact')=='partner' and r['partner_id']:
res.append((r['id'], r['partner_id'][1]))
else:
addr = str('')
addr += "%s %s %s" % (r.get('street', '') or '', r.get('zip', '') \
or '', r.get('city', '') or '')
res.append((r['id'], addr.strip() or '/'))
return res
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100):
if not args:
args=[]
ids = self.search(cr, user, [('name',operator,name)] + args, limit=limit, context=context)
jobs = self.pool.get('res.partner.job')
if name:
job_ids = jobs.search(cr, user, [('contact_id', operator, name)] + args, limit=limit, context=context)
for job in jobs.browse(cr, user, job_ids):
ids += [job.address_id.id]
return self.name_get(cr, user, ids, context)
_name = 'res.partner.address'
_inherit = 'res.partner.address'
_description ='Partner Address'
_inherits = { 'res.partner.location' : 'location_id' }
def _get_use_existing_address(self, cr, uid, ids, fieldnames, args, context=None):
return dict(map(lambda x: (x, False), ids))
def _set_use_existing_address(self, cr, uid, ids, name, value, arg, context=None):
return True
def _default_location_id(self, cr, uid, context=None):
context = context or {}
if not context.get('default_partner_id',False):
return False
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 _default_existing_get(self, cr, uid, context=None):
return bool(self._default_location_id(cr, uid, context))
_columns = {
'job_id': fields.related('job_ids','contact_id','job_id',type='many2one',\
relation='res.partner.job', string='Main Job'),
'job_ids': fields.one2many('res.partner.job', 'address_id', 'Contacts'),
}
res_partner_address()
'location_id' : fields.many2one('res.partner.location', 'Location'),
'use_existing_address' : fields.function(_get_use_existing_address,
fnct_inv=_set_use_existing_address,
type='boolean',
string='Link to Existing Address'),
class res_partner_job(osv.osv):
def name_get(self, cr, uid, ids, context=None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param user: the current user,
@param ids: List of partner addresss IDs
@param context: A standard dictionary for contextual values
"""
if context is None:
context = {}
'contact_id' : fields.many2one('res.partner.contact', 'Contact'),
if not ids:
return []
res = []
# come modules are doing SQL reports on those fields (crm)
'country_id': fields.related('location_id', 'country_id', type='many2one', string='Country', store=True, relation='res.country'),
'company_id': fields.related('location_id', 'company_id', type='many2one', string='Company', store=True, relation='res.company'),
jobs = self.browse(cr, uid, ids, context=context)
contact_ids = [rec.contact_id.id for rec in jobs]
contact_names = dict(self.pool.get('res.partner.contact').name_get(cr, uid, contact_ids, context=context))
for r in jobs:
function_name = r.function
funct = function_name and (", " + function_name) or ""
res.append((r.id, contact_names.get(r.contact_id.id, '') + funct))
return res
_name = 'res.partner.job'
_description ='Contact Partner Function'
_order = 'sequence_contact'
_columns = {
'name': fields.related('address_id', 'partner_id', type='many2one',\
relation='res.partner', string='Partner', help="You may\
enter Address first,Partner will be linked automatically if any."),
'address_id': fields.many2one('res.partner.address', 'Address', \
help='Address which is linked to the Partner'), # TO Correct: domain=[('partner_id', '=', name)]
'contact_id': fields.many2one('res.partner.contact','Contact', required=True, ondelete='cascade'),
# Do not use the one of the location, each job position has it's phone
'phone': fields.char('Phone', size=64),
'fax': fields.char('Fax', size=64),
'email': fields.char('E-Mail', size=240),
'function': fields.char('Partner Function', size=64, help="Function of this contact with this partner"),
'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'),
'email': fields.char('E-Mail', size=240, help="Job E-Mail"),
'phone': fields.char('Phone', size=64, help="Job Phone no."),
'fax': fields.char('Fax', size=64, help="Job FAX no."),
'extension': fields.char('Extension', size=64, help='Internal/External extension phone number'),
'other': fields.char('Other', size=64, help='Additional phone field'),
'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"),
#'partner_id' : fields.related('location_id', 'partner_id', type="many2one", relation='res.partner', string='Partner'),
'contact_firstname' : fields.related('contact_id', 'first_name', type='char', size=64, string='Firstname'),
'contact_name' : fields.related('contact_id', 'name', type='char', size=64, string="Lastname"),
'name' : fields.related('contact_id', 'name', type='char', size=64, string="Lastname", store=True),
}
def name_get(self, cr, uid, ids, context=None):
return [
((obj.id, "%s, %s" % (obj.contact_id.name_get()[0][1], obj.location_id.name_get()[0][1],)))
for obj in self.browse(cr, uid, ids, context=context)
]
_defaults = {
'sequence_contact' : lambda *a: 0,
'state': lambda *a: 'current',
'use_existing_address': _default_existing_get,
'location_id': _default_location_id
}
def onchange_name(self, cr, uid, ids, address_id='', name='', context=None):
return {'value': {'address_id': address_id}, 'domain':{'partner_id':'name'}}
def onchange_partner(self, cr, uid, _, partner_id, context=None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user,
@param _: List of IDs,
@partner_id : ID of the Partner selected,
@param context: A standard dictionary for contextual values
"""
return {'value': {'address_id': False}}
def onchange_address(self, cr, uid, _, address_id, context=None):
"""
@@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user,
@param _: List of IDs,
@address_id : ID of the Address selected,
@param context: A standard dictionary for contextual values
"""
partner_id = False
if address_id:
address = self.pool.get('res.partner.address')\
.browse(cr, uid, address_id, context=context)
partner_id = address.partner_id.id
return {'value': {'name': partner_id}}
res_partner_job()
def _auto_init(self, cr, context=None):
def column_exists(column):
cr.execute("select count(attname) from pg_attribute where attrelid = \
(select oid from pg_class where relname = %s) \
and attname = %s", (self._table, column,))
value = cr.fetchone()[0]
return bool(value == 1)
exists = column_exists('location_id')
super(res_partner_address, self)._auto_init(cr, context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
if not exists:
contact_proxy = self.pool.get('res.partner.contact')
uid = 1
cr.execute("SELECT id, name, mobile, country_id, partner_id, phone, email, street, street2, city, company_id, state_id, zip, location_id \
FROM res_partner_address")
for item in cr.fetchall():
values = {
'name' : item[1] or '/',
'mobile' : item[2],
'country_id' : item[3],
'phone' : item[5],
'email' : item[6],
'company_id' : item[10],
}
contact_id = contact_proxy.create(cr, uid, values, context=context)
values = {
'street' : item[7],
'street2' : item[8],
'city' : item[9],
'country_id' : item[3],
'company_id' : item[10],
'state_id' : item[11],
'zip' : item[12],
}
location_id = self.pool.get('res.partner.location').create(cr, uid, values, context=context)
cr.execute("UPDATE res_partner_address SET location_id = %s, contact_id = %s, partner_id = %s WHERE id = %s",
(location_id, contact_id, item[4], item[0],))
def default_get(self, cr, uid, fields=[], context=None):
context = context or {}
if 'default_type' in context:
del context['default_type']
return super(res_partner_address, self).default_get(cr, uid, fields, context)
res_partner_address()

View File

@ -141,45 +141,8 @@
</record>
<!-- Create the addresses -->
<record id="base.main_address" model="res.partner.address">
<field eval="&quot;&quot;&quot;Grand-Rosière&quot;&quot;&quot;" name="city"/>
<field eval="&quot;&quot;&quot;+32.81.73.35.01&quot;&quot;&quot;" name="fax"/>
<field eval="&quot;&quot;&quot;1367&quot;&quot;&quot;" name="zip"/>
<!-- The partner associated with the main company should not have a country specified in the demo data,
as it may conflicts with the accounting installing chart wizard. This wizard will indeed try to
install the localization module accordingly to this variable automatically. Thus, in demo data,
everyone would have the belgian chart of account by default, what should be avoided. -->
<!-- <field name="country_id" ref="base.be"/> -->
<field eval="&quot;&quot;&quot;+32.81.81.37.00&quot;&quot;&quot;" name="phone"/>
<field eval="&quot;&quot;&quot;Chaussée de Namur, 40&quot;&quot;&quot;" name="street"/>
</record>
<record id="res_partner_address_0" model="res.partner.address">
<field eval="&quot;&quot;&quot;Louvain-La-Neuve&quot;&quot;&quot;" name="city"/>
<field eval="&quot;&quot;&quot;1348&quot;&quot;&quot;" name="zip"/>
<field eval="&quot;&quot;&quot;contact&quot;&quot;&quot;" name="type"/>
<!-- The partner associated with the main company should not have a country specified in the demo data,
as it may conflicts with the accounting installing chart wizard. This wizard will indeed try to
install the localization module accordingly to this variable automatically. Thus, in demo data,
everyone would have the belgian chart of account by default, what should be avoided. -->
<!-- <field name="country_id" ref="base.be"/> -->
<field eval="&quot;&quot;&quot;rue du pré, 115&quot;&quot;&quot;" name="street"/>
<field eval="1" name="active"/>
</record>
<record id="res_partner_address_1" model="res.partner.address">
<field eval="&quot;&quot;&quot;Charleroi&quot;&quot;&quot;" name="city"/>
<field eval="&quot;&quot;&quot;6000&quot;&quot;&quot;" name="zip"/>
<field eval="&quot;&quot;&quot;contact&quot;&quot;&quot;" name="type"/>
<!-- The partner associated with the main company should not have a country specified in the demo data,
as it may conflicts with the accounting installing chart wizard. This wizard will indeed try to
install the localization module accordingly to this variable automatically. Thus, in demo data,
everyone would have the belgian chart of account by default, what should be avoided. -->
<!-- <field name="country_id" ref="base.be"/> -->
<field eval="&quot;&quot;&quot;Boulevars Tirou, 32&quot;&quot;&quot;" name="street"/>
<field eval="1" name="active"/>
</record>
<!-- Create the jobs -->
<!--
<record id="res_partner_job_0" model="res.partner.job">
<field name="address_id" ref="base.res_partner_address_1"/>
<field name="function">Salesman</field>
@ -334,5 +297,6 @@
<field name="function">CEO</field>
<field name="sequence_contact">1</field>
</record>
-->
</data>
</openerp>

View File

@ -1,67 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields, osv
class base_contact_installer(osv.osv_memory):
_name = 'base.contact.installer'
_inherit = 'res.config.installer'
_columns = {
'name': fields.char('Name', size=64),
'migrate': fields.boolean('Migrate', help="If you select this, all addresses will be migrated."),
}
def execute(self, cr, uid, ids, context=None):
"""
This function is used to create contact and address from existing partner address
"""
obj = self.pool.get("base.contact.installer").browse(cr, uid, uid, context=context)
if obj.migrate:
# Enable PL/pgSQL if not enabled yet in the database
cr.execute("SELECT 1 FROM pg_language WHERE lanname = 'plpgsql'")
if not cr.fetchone():
cr.execute("CREATE LANGUAGE plpgsql;")
cr.execute("""DROP TRIGGER IF EXISTS contactjob on res_partner_contact;
CREATE OR REPLACE FUNCTION add_to_job() RETURNS TRIGGER AS $contactjob$
DECLARE
new_name varchar;
new_phonenum varchar;
BEGIN
IF(TG_OP='INSERT') THEN
INSERT INTO res_partner_job(contact_id, address_id, function, state) VALUES(NEW.id, NEW.website::integer,NEW.first_name, 'current');
UPDATE res_partner_contact set first_name=Null, website=Null, active=True where id=NEW.id;
END IF;
RETURN NEW;
END;
$contactjob$ LANGUAGE plpgsql;
CREATE TRIGGER contactjob AFTER INSERT ON res_partner_contact FOR EACH ROW EXECUTE PROCEDURE add_to_job();""")
cr.execute("INSERT into res_partner_contact (name, title, email, first_name, website) (SELECT coalesce(name, 'Noname'), title, email, function , to_char(id, '99999999') from res_partner_address)")
cr.execute("DROP TRIGGER IF EXISTS contactjob on res_partner_contact")
cr.execute("DROP FUNCTION IF EXISTS add_to_job()")
base_contact_installer()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,59 +0,0 @@
<openerp>
<data>
<record id="view_base_contact_installer" model="ir.ui.view">
<field name="name">base.contact.installer.view</field>
<field name="model">base.contact.installer</field>
<field name="type">form</field>
<field name="inherit_id" ref="base.res_config_installer"/>
<field name="arch" type="xml">
<data>
<form position="attributes">
<attribute name="string">Address's Migration to Contacts</attribute>
</form>
<separator string="title" position="attributes">
<attribute name="string">Select the Option for Addresses Migration</attribute>
</separator>
<xpath expr="//label[@string='description']" position="attributes">
<attribute name="string">You can migrate Partner's current addresses to the contact.</attribute>
</xpath>
<xpath expr="//separator[@string=&quot;vsep&quot;]" position="attributes">
<attribute name="rowspan">13</attribute>
<attribute name="string"/>
</xpath>
<xpath expr="//button[@string='Install Modules']" position="attributes">
<attribute name="string">Configure</attribute>
</xpath>
<group colspan="8">
<group colspan="2" col="2">
<label string="Due to changes in Address and Partner's relation, some of the details from address are needed to be migrated into contact information." colspan="4"/>
<label string="Otherwise these details will not be visible from address/contact." colspan="4"/>
<label string="Do you want to migrate your Address data in Contact Data?" colspan="4"/>
<group colspan="6">
<field name="migrate" string="Migrate" colspan="1"/>
</group>
</group>
</group>
</data>
</field>
</record>
<record id="action_base_contact_installer" model="ir.actions.act_window">
<field name="name">Address Migration</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">base.contact.installer</field>
<field name="view_id" ref="view_base_contact_installer"/>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<record id="base_contact_installer_todo" model="ir.actions.todo">
<field name="action_id" ref="action_base_contact_installer"/>
<field name="category_id" ref="base.category_administration_config"/>
<field name="sequence">3</field>
<field name="type">automatic</field>
</record>
</data>
</openerp>

View File

@ -30,12 +30,12 @@
<field name="arch" type="xml">
<form string="Partner Contact">
<group colspan="4" col="6">
<field name="title" select="1" widget="selection" domain="[('domain', '=', 'contact')]" size="0"/>
<field name="name" select="1"/>
<field name="first_name" select="1"/>
<field name="title" select="1" widget="selection" domain="[('domain', '=', 'contact')]" size="0"/>
</group>
<notebook colspan="4" >
<page string="General">
<page string="General">
<group colspan="4" col="4">
<group colspan="2" col="4">
<separator string="Communication" colspan="4"/>
@ -47,54 +47,41 @@
<separator string="Photo" colspan="4"/>
<field name="photo" widget='image' nolabel="1"/>
</group>
</group>
</group>
<field name="job_ids" colspan="4" nolabel="1" mode="tree,form">
<form string="Functions and Addresses">
<group colspan="4" col="4">
<field name="sequence_contact" />
<field name="function"/>
<field name="name" on_change="onchange_name(name,address_id)"/>
<field name="address_id"/>
<field name="date_start" />
<field name="date_stop" />
<field name="state" />
<field name="name" />
</group>
<separator string="Communication" colspan="4"/>
<group colspan="4" col="4">
<field name="phone"/>
<field name="fax"/>
<field name="email" widget="email"/>
<field name="extension"/>
<field name="other"/>
</group>
</form>
<tree string="Functions and Addresses">
<field name="sequence_contact" string="Seq."/>
<field name="function"/>
<field name="name" on_change="onchange_partner(name)"/>
<field name="address_id" attrs="{'required': [('name', '!=', False)]}" on_change="onchange_address(address_id)"/>
<field name="name" on_change="onchange_partner(name)"/>
<field name="phone"/>
<field name="fax"/>
<field name="extension"/>
<field name="other"/>
<field name="email"/>
<field name="state" />
</tree>
</field>
</page>
<page string="Extra Information">
<page string="Extra Information">
<field name="active"/>
<field name="lang_id" widget="selection"/>
<field name="partner_id" invisible="1" select="1"/>
<field name="function" invisible="1" />
<field name="partner_id" invisible="1" select="1"/>
<field name="function" invisible="1" />
<field name="country_id"/>
<field name="birthdate"/>
</page>
<page string="Notes">
<field name="comment" nolabel="1"/>
</page>
</notebook>
</form>
</field>
@ -132,7 +119,7 @@
<field name="name">Addresses</field>
</record>
<!--
<!--
Contacts for Suppliers
-->
<menuitem icon="terp-purchase" id="base.menu_purchase_root" name="Purchases"
@ -141,7 +128,7 @@
parent="base.menu_purchase_root" sequence="3"/>
<menuitem id="base.menu_procurement_management_supplier_name" name="Suppliers"
parent="base.menu_procurement_management_supplier" action="base.action_partner_supplier_form" sequence="1"/>
<menuitem name="Contacts" id="menu_purchases_partner_contact_form" action="action_partner_contact_form"
<menuitem name="Contacts" id="menu_purchases_partner_contact_form" action="action_partner_contact_form"
parent = "base.menu_procurement_management_supplier" sequence="2"/>
<!-- Views for Partners Form View -->
@ -173,29 +160,23 @@
</group>
<field name="job_ids" mode="tree,form" nolabel="1" colspan="4">
<tree string="Contacts" editable="top">
<field name="sequence_partner"/>
<field name="contact_id"/>
<field name="function"/>
<field name="phone"/>
<field name="fax"/>
<field name="extension"/>
<field name="other"/>
<field name="email"/>
</tree>
<form string="Contacts">
<group colspan="4" col="4">
<field name="sequence_partner"/>
<field name="contact_id"/>
<field name="function"/>
</group>
<separator string="Communication" colspan="4"/>
<group colspan="4" col="4">
<field name="phone"/>
<field name="fax"/>
<field name="extension"/>
<field name="other"/>
<field name="email" widget="email"/>
</group>
<group colspan="4" col="4">
<field name="contact_id"/>
<field name="function"/>
</group>
<separator string="Communication" colspan="4"/>
<group colspan="4" col="4">
<field name="phone"/>
<field name="fax"/>
<field name="email" widget="email"/>
</group>
</form>
</field>
</form>
@ -256,15 +237,22 @@
<!-- Views for Addresses -->
<record model="ir.ui.view" id="view_partner_address_tree_inherited1">
<field name="name">Partner addresses inherited</field>
<field name="model">res.partner.address</field>
<field name="inherit_id" ref="base.view_partner_address_tree"/>
<record model="ir.ui.view" id="view_partner_location_tree">
<field name="name">res.partner.location.tree</field>
<field name="model">res.partner.location</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<field name="name" position="replace">
<field name='job_ids' string='# of Contacts'/>
</field>
<tree string="Locations">
<field name="type" />
<field name="street"/>
<field name="street2"/>
<field name="zip"/>
<field name="city"/>
<field name="country_id" />
<field name="state_id"/>
<field name="phone"/>
<field name="fax"/>
</tree>
</field>
</record>
@ -274,65 +262,44 @@
<field name="inherit_id" ref="base.view_partner_address_form1"/>
<field name='type'>form</field>
<field name='arch' type='xml'>
<field name="type" position="replace">
<field name="type" position="replace" />
<field name="title" position="replace" />
<field name="function" position="replace" />
<field name="name" position="replace" />
<field name="active" position="after">
<separator string="Contact" colspan="6" />
<group colspan="6" col="4">
<field name="contact_id" />
<field name="function" />
<field name='type' invisible="1"/>
</group>
</field>
</field>
</record>
<record model="ir.ui.view" id="view_partner_address_form_inherited1">
<field name='name'>res.partner.address.form.inherited1</field>
<field name='model'>res.partner.address</field>
<field name="inherit_id" ref="base.view_partner_address_form1"/>
<field name='type'>form</field>
<field name='arch' type='xml'>
<field name="name" position="replace">
<field name="street" position="before">
<field name="use_existing_address"/>
<field name="location_id" required="0"
attrs="{'readonly': [('use_existing_address', '=', 0)], 'invisible': [('use_existing_address', '=', 0)]}"
domain="[('partner_id', '=', partner_id)]" />
</field>
</field>
</record>
<record id='view_partner_address_form_inherited2' model='ir.ui.view'>
<field name='name'>res.partner.address.form.inherited2</field>
<field name='model'>res.partner.address</field>
<field name="inherit_id" ref="base.view_partner_address_form1"/>
<field name='type'>form</field>
<field name='arch' type='xml'>
<field name="title" position="replace">
<field name="street" position="attributes">
<attribute name="attrs">{'invisible' : [('use_existing_address', '=', 1)], 'readonly' : [('use_existing_address', '=', 1)]}</attribute>
</field>
</field>
</record>
<record id='view_partner_address_form_inherited3' model='ir.ui.view'>
<field name='name'>res.partner.address.form.inherited3</field>
<field name='model'>res.partner.address</field>
<field name="inherit_id" ref="base.view_partner_address_form1"/>
<field name='type'>form</field>
<field name='arch' type='xml'>
<field name="function" position="replace">
<field name="street2" position="attributes">
<attribute name="attrs">{'invisible' : [('use_existing_address', '=', 1)], 'readonly' : [('use_existing_address', '=', 1)]}</attribute>
</field>
</field>
</record>
<record id='view_partner_address_form_inherited4' model='ir.ui.view'>
<field name='name'>res.partner.address.form.inherited4</field>
<field name='model'>res.partner.address</field>
<field name="inherit_id" ref="base.view_partner_address_form1"/>
<field name='type'>form</field>
<field name='arch' type='xml'>
<field name='mobile' position="replace">
<field name="city" position="attributes">
<attribute name="attrs">{'invisible' : [('use_existing_address', '=', 1)], 'readonly' : [('use_existing_address', '=', 1)]}</attribute>
</field>
</field>
</record>
<record model="ir.ui.view" id="view_partner_address_form_inherited6">
<field name='name'>res.partner.address.form.inherited6</field>
<field name='model'>res.partner.address</field>
<field name="inherit_id" ref="base.view_partner_address_form1"/>
<field name='type'>form</field>
<field name='arch' type='xml'>
<field name="partner_id" position="replace">
<field name='partner_id' select='1'/>
<field name='type' select='2'/>
<field name='job_id' invisible="1"/>
<field name="zip" position="attributes">
<attribute name="attrs">{'invisible' : [('use_existing_address', '=', 1)], 'readonly' : [('use_existing_address', '=', 1)]}</attribute>
</field>
<field name="mobile" position="attributes">
<attribute name="attrs">{'invisible' : [('use_existing_address', '=', 1)], 'readonly' : [('use_existing_address', '=', 1)]}</attribute>
</field>
<field name="state_id" position="attributes">
<attribute name="attrs">{'invisible' : [('use_existing_address', '=', 1)], 'readonly' : [('use_existing_address', '=', 1)]}</attribute>
</field>
<field name="country_id" position="attributes">
<attribute name="attrs">{'invisible' : [('use_existing_address', '=', 1)], 'readonly' : [('use_existing_address', '=', 1)]}</attribute>
</field>
</field>
</record>
@ -344,13 +311,14 @@
<field name="inherit_id" ref="base.view_res_partner_address_filter"/>
<field name="arch" type="xml">
<search string="Search Contact">
<field name="job_ids"/>
<field name="job_ids"/>
</search>
</field>
</record>
<!-- Views for partner job Tree view -->
<!--
<record model="ir.ui.view" id="view_partner_job_tree">
<field name="name">res.partner.job.tree</field>
<field name="model">res.partner.job</field>
@ -364,14 +332,15 @@
<field name="email"/>
<field name="phone"/>
<field name="fax"/>
<field name="extension"/>
<field name="state" />
</tree>
</field>
</record>
-->
<!-- Views for partner job Form view -->
<!--
<record model="ir.ui.view" id="view_partner_job_form">
<field name="name">res.partner.job.form</field>
<field name="model">res.partner.job</field>
@ -385,18 +354,17 @@
<field name="email" widget="email"/>
<field name="phone"/>
<field name="fax"/>
<field name="extension"/>
<field name="sequence_contact" groups="base.group_user"/>
<field name="sequence_partner" groups="base.group_user"/>
<field name="date_start" groups="base.group_user"/>
<field name="date_stop" groups="base.group_user"/>
<field name="state" />
</form>
</field>
</record>
-->
<!-- Menuitem for res.partner.job -->
<!--
<record model="ir.actions.act_window" id="action_res_partner_job">
<field name="name">Contact's Jobs</field>
<field name="type">ir.actions.act_window</field>
@ -409,16 +377,19 @@
res_model="res.partner.job"
src_model="res.partner"
/>
-->
<!-- Act window defining a shorcut on partner address to open all his jobs -->
<!--
<act_window
id="act_res_partner_jobs"
id="act_res_partner_jobs"
name="Open Jobs"
context="{'search_default_address_id': [active_id], 'default_address_id': active_id}"
res_model="res.partner.job"
src_model="res.partner.address"
/>
-->
</data>
</openerp>

View File

@ -36,15 +36,6 @@
<field eval="1" name="flow_start"/>
</record>
<record id="process_node_function0" model="process.node">
<field name="model_id" ref="base_contact.model_res_partner_job"/>
<field eval="&quot;&quot;&quot;state&quot;&quot;&quot;" name="kind"/>
<field eval="&quot;&quot;&quot;Jobs at a same partner address.&quot;&quot;&quot;" name="note"/>
<field eval="&quot;&quot;&quot;Function&quot;&quot;&quot;" name="name"/>
<field name="process_id" ref="process_process_basecontactprocess0"/>
<field eval="0" name="flow_start"/>
</record>
<record id="process_node_addresses0" model="process.node">
<field name="menu_id" ref="base.menu_partner_address_form"/>
<field name="model_id" ref="base.model_res_partner_address"/>
@ -59,22 +50,6 @@
Process Transition
-->
<record id="process_transition_contacttofunction0" model="process.transition">
<field eval="[(6,0,[])]" name="transition_ids"/>
<field eval="&quot;&quot;&quot;Contact to function&quot;&quot;&quot;" name="name"/>
<field eval="&quot;&quot;&quot;Defines contacts and functions.&quot;&quot;&quot;" name="note"/>
<field model="process.node" name="target_node_id" ref="process_node_function0"/>
<field model="process.node" name="source_node_id" ref="process_node_contacts0"/>
</record>
<record id="process_transition_functiontoaddress0" model="process.transition">
<field eval="[(6,0,[])]" name="transition_ids"/>
<field eval="&quot;&quot;&quot;Function to address&quot;&quot;&quot;" name="name"/>
<field eval="&quot;&quot;&quot;Define functions and address.&quot;&quot;&quot;" name="note"/>
<field model="process.node" name="target_node_id" ref="process_node_addresses0"/>
<field model="process.node" name="source_node_id" ref="process_node_function0"/>
</record>
<record id="process_transition_partnertoaddress0" model="process.transition">
<field eval="[(6,0,[])]" name="transition_ids"/>
<field eval="&quot;&quot;&quot;Partner to address&quot;&quot;&quot;" name="name"/>
@ -84,4 +59,4 @@
</record>
</data>
</openerp>
</openerp>

View File

@ -1,7 +1,4 @@
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_job,res.partner.job,model_res_partner_job,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_job_all,res.partner.job all,model_res_partner_job,base.group_user,1,0,0,0
access_group_sale_salesman,res.partner.contact.sale.salesman,model_res_partner_contact,base.group_sale_salesman,1,1,1,0
access_res_partner_job_salesman,res.partner.job.salesman,model_res_partner_job,base.group_sale_salesman,1,1,1,0
"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_group_sale_salesman","res.partner.contact.sale.salesman","model_res_partner_contact","base.group_sale_salesman",1,1,1,0

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 1
3 access_res_partner_job access_res_partner_contact_all res.partner.job res.partner.contact all model_res_partner_job model_res_partner_contact base.group_partner_manager base.group_user 1 1 0 1 0 1 0
4 access_res_partner_contact_all access_group_sale_salesman res.partner.contact all res.partner.contact.sale.salesman model_res_partner_contact base.group_user base.group_sale_salesman 1 0 1 0 1 0
access_res_partner_job_all res.partner.job all model_res_partner_job base.group_user 1 0 0 0
access_group_sale_salesman res.partner.contact.sale.salesman model_res_partner_contact base.group_sale_salesman 1 1 1 0
access_res_partner_job_salesman res.partner.job.salesman model_res_partner_job base.group_sale_salesman 1 1 1 0

View File

@ -3,18 +3,6 @@
*contacts unrelated to a partner,
*contacts working at several addresses (possibly for different partners),
*contacts with possibly different functions for each of its job's addresses
- |
In order to assign language to contacts first I will create Language FR
(Remove)
-
!record {model: res.lang, id: res_lang_french0}:
code: fr_BE
date_format: '%m/%d/%Y'
decimal_point: '.'
direction: ltr
grouping: '[]'
name: French
time_format: '%H:%M:%S'
- |
In order to check contacts first I will create contact unrelated to a partner
-
@ -25,9 +13,6 @@
- email: lwilliams@mydomain.com
function: PA
phone: (+32).10.45.18.77
sequence_contact: 1
state: current
lang_id: res_lang_french0
mobile: (+32).10.45.18.77
name: Williams
- |
@ -42,53 +27,12 @@
type: default
zip: '2324324'
job_ids:
- address_id: res_partner_address_1
function: CEO
- function: CEO
contact_id: res_partner_contact_williams0
sequence_partner: 2
state: current
lang: fr_BE
name: Laura's Company
name: Lauras Company
ref: LC
- |
-
Now I will check that the new job is assigned properly to contact or not
-
!assert {model: res.partner.contact, id: res_partner_contact_williams0}:
- len(job_ids) >= 2
- |
In order to check contacts working at several addresses for different partners
I will create contact with 2 different addresses
-
!record {model: res.partner.contact, id: res_partner_contact_pauwels0}:
country_id: base.be
first_name: Nicolas
job_ids:
- address_id: base.res_partner_address_1
function: CTO
state: current
- address_id: base.res_partner_address_3000
function: CEO
state: current
lang_id: res_lang_french0
mobile: (+32).23.44.32.12
name: Pauwels
- |
In order to check one contact working at one partner with different functions
I will create contact with 2 different jobs with different function but the same address
-
!record {model: res.partner.contact, id: res_partner_contact_mortier0}:
country_id: base.be
first_name: Christina
job_ids:
- address_id: base.res_partner_address_1
function: CEO
state: past
- address_id: base.res_partner_address_1
function: CTO
state: current
lang_id: base_contact.res_lang_french0
mobile: (+32).10.45.18.77
name: Mortier
- len(job_ids) == 2

View File

@ -39,7 +39,7 @@ Note that:
Association / Configuration / Types of Events
""",
'author': 'OpenERP SA',
'depends': ['crm', 'base_contact', 'account', 'marketing', 'mail'],
'depends': ['crm', 'account', 'marketing', 'mail'],
'init_xml': [],
'update_xml': [
'security/ir.model.access.csv',

View File

@ -303,7 +303,7 @@ class event_registration(osv.osv):
'event_id': fields.many2one('event.event', 'Event', required=True, readonly=True, states={'draft': [('readonly', False)]}),
'partner_id': fields.many2one('res.partner', 'Partner', states={'done': [('readonly', True)]}),
"partner_invoice_id": fields.many2one('res.partner', 'Partner Invoiced', readonly=True, states={'draft': [('readonly', False)]}),
"contact_id": fields.many2one('res.partner.contact', 'Partner Contact', readonly=False, states={'done': [('readonly', True)]}), #TODO: filter only the contacts that have a function into the selected partner_id
"contact_id": fields.many2one('res.partner.address', 'Partner Contact', readonly=False, states={'done': [('readonly', True)]}), #TODO: filter only the contacts that have a function into the selected partner_id
"unit_price": fields.float('Unit Price', required=True, digits_compute=dp.get_precision('Sale Price'), readonly=True, states={'draft': [('readonly', False)]}),
'price_subtotal': fields.function(_amount_line, string='Subtotal', digits_compute=dp.get_precision('Sale Price'), store=True),
"badge_ids": fields.one2many('event.registration.badge', 'registration_id', 'Badges', readonly=False, states={'done': [('readonly', True)]}),
@ -382,7 +382,7 @@ class event_registration(osv.osv):
inv_lines_pool = self.pool.get('account.invoice.line')
inv_pool = self.pool.get('account.invoice')
product_pool = self.pool.get('product.product')
contact_pool = self.pool.get('res.partner.contact')
contact_pool = self.pool.get('res.partner.address')
if context is None:
context = {}
# If date was specified, use it as date invoiced, usefull when invoices are generated this month and put the