[MERGE] from trunk
bzr revid: rco@openerp.com-20120928124403-aht90hi49yxwrcmz bzr revid: rco@openerp.com-20121001073112-xbxdturd27bwscg1
This commit is contained in:
commit
a6e30d305c
|
@ -8,6 +8,7 @@
|
|||
<field name="symbol">$</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
<field name="position">before</field>
|
||||
<field name="company_id" ref="main_company"/>
|
||||
</record>
|
||||
<record id="rateUSD" model="res.currency.rate">
|
||||
|
|
|
@ -1442,6 +1442,7 @@
|
|||
<field name="name"/>
|
||||
<field name="model_id"/>
|
||||
<field name="group_id"/>
|
||||
<field name="active"/>
|
||||
</group>
|
||||
<group string="Access" col="4">
|
||||
<field name="perm_read"/>
|
||||
|
@ -1493,8 +1494,9 @@
|
|||
<sheet>
|
||||
<group>
|
||||
<group string="General">
|
||||
<field colspan="4" name="name"/>
|
||||
<field name="name"/>
|
||||
<field name="model_id"/>
|
||||
<field name="active"/>
|
||||
</group>
|
||||
<group col="4" string="Access Rights">
|
||||
<field name="perm_read"/>
|
||||
|
|
|
@ -468,6 +468,7 @@ class ir_model_access(osv.osv):
|
|||
_name = 'ir.model.access'
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=64, required=True, select=True),
|
||||
'active': fields.boolean('Active', help='If you uncheck the active field, it will disable the ACL without deleting it (if you delete a native ACL, it will be re-created when you reload the module.'),
|
||||
'model_id': fields.many2one('ir.model', 'Object', required=True, domain=[('osv_memory','=', False)], select=True, ondelete='cascade'),
|
||||
'group_id': fields.many2one('res.groups', 'Group', ondelete='cascade', select=True),
|
||||
'perm_read': fields.boolean('Read Access'),
|
||||
|
@ -475,6 +476,9 @@ class ir_model_access(osv.osv):
|
|||
'perm_create': fields.boolean('Create Access'),
|
||||
'perm_unlink': fields.boolean('Delete Access'),
|
||||
}
|
||||
_defaults = {
|
||||
'active': True,
|
||||
}
|
||||
|
||||
def check_groups(self, cr, uid, group):
|
||||
grouparr = group.split('.')
|
||||
|
@ -499,14 +503,16 @@ class ir_model_access(osv.osv):
|
|||
cr.execute("SELECT perm_" + mode + " "
|
||||
" FROM ir_model_access a "
|
||||
" JOIN ir_model m ON (m.id = a.model_id) "
|
||||
" WHERE m.model = %s AND a.group_id = %s", (model_name, group_id)
|
||||
" WHERE m.model = %s AND a.active IS True "
|
||||
" AND a.group_id = %s", (model_name, group_id)
|
||||
)
|
||||
r = cr.fetchone()
|
||||
if r is None:
|
||||
cr.execute("SELECT perm_" + mode + " "
|
||||
" FROM ir_model_access a "
|
||||
" JOIN ir_model m ON (m.id = a.model_id) "
|
||||
" WHERE m.model = %s AND a.group_id IS NULL", (model_name, )
|
||||
" WHERE m.model = %s AND a.active IS True "
|
||||
" AND a.group_id IS NULL", (model_name, )
|
||||
)
|
||||
r = cr.fetchone()
|
||||
|
||||
|
@ -531,6 +537,7 @@ class ir_model_access(osv.osv):
|
|||
LEFT JOIN ir_module_category c ON (c.id=g.category_id)
|
||||
WHERE
|
||||
m.model=%s AND
|
||||
a.active IS True AND
|
||||
a.perm_''' + access_mode, (model_name,))
|
||||
return [('%s/%s' % x) if x[0] else x[1] for x in cr.fetchall()]
|
||||
|
||||
|
@ -560,6 +567,7 @@ class ir_model_access(osv.osv):
|
|||
' JOIN res_groups_users_rel gu ON (gu.gid = a.group_id) '
|
||||
' WHERE m.model = %s '
|
||||
' AND gu.uid = %s '
|
||||
' AND a.active IS True '
|
||||
, (model_name, uid,)
|
||||
)
|
||||
r = cr.fetchone()[0]
|
||||
|
@ -571,6 +579,7 @@ class ir_model_access(osv.osv):
|
|||
' JOIN ir_model m ON (m.id = a.model_id) '
|
||||
' WHERE a.group_id IS NULL '
|
||||
' AND m.model = %s '
|
||||
' AND a.active IS True '
|
||||
, (model_name,)
|
||||
)
|
||||
r = cr.fetchone()[0]
|
||||
|
|
|
@ -75,6 +75,7 @@ class ir_rule(osv.osv):
|
|||
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=128, select=1),
|
||||
'active': fields.boolean('Active', help="If you uncheck the active field, it will disable the record rule without deleting it (if you delete a native record rule, it may be re-created when you reload the module."),
|
||||
'model_id': fields.many2one('ir.model', 'Object',select=1, required=True, ondelete="cascade"),
|
||||
'global': fields.function(_get_value, string='Global', type='boolean', store=True, help="If no group is specified the rule is global and applied to everyone"),
|
||||
'groups': fields.many2many('res.groups', 'rule_group_rel', 'rule_group_id', 'group_id', 'Groups'),
|
||||
|
@ -89,6 +90,7 @@ class ir_rule(osv.osv):
|
|||
_order = 'model_id DESC'
|
||||
|
||||
_defaults = {
|
||||
'active': True,
|
||||
'perm_read': True,
|
||||
'perm_write': True,
|
||||
'perm_create': True,
|
||||
|
@ -114,6 +116,7 @@ class ir_rule(osv.osv):
|
|||
FROM ir_rule r
|
||||
JOIN ir_model m ON (r.model_id = m.id)
|
||||
WHERE m.model = %s
|
||||
AND r.active is True
|
||||
AND r.perm_""" + mode + """
|
||||
AND (r.id IN (SELECT rule_group_id FROM rule_group_rel g_rel
|
||||
JOIN res_groups_users_rel u_rel ON (g_rel.group_id = u_rel.gid)
|
||||
|
|
|
@ -25,25 +25,25 @@
|
|||
</record>
|
||||
|
||||
<record model="ir.module.category" id="module_category_sales_management">
|
||||
<field name="name">Sales Management</field>
|
||||
<field name="name">Sales</field>
|
||||
<field name="description">Helps you handle your quotations, sale orders and invoicing.</field>
|
||||
<field name="sequence">2</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.module.category" id="module_category_project_management">
|
||||
<field name="name">Project Management</field>
|
||||
<field name="name">Project</field>
|
||||
<field name="description">Helps you manage your projects and tasks by tracking them, generating plannings, etc...</field>
|
||||
<field name="sequence">3</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.module.category" id="module_category_knowledge_management">
|
||||
<field name="name">Knowledge Management</field>
|
||||
<field name="name">Knowledge</field>
|
||||
<field name="description">Lets you install addons geared towards sharing knowledge with and between your employees.</field>
|
||||
<field name="sequence">4</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.module.category" id="module_category_warehouse_management">
|
||||
<field name="name">Warehouse Management</field>
|
||||
<field name="name">Warehouse</field>
|
||||
<field name="description">Helps you manage your inventory and main stock operations: delivery orders, receptions, etc.</field>
|
||||
<field name="sequence">5</field>
|
||||
</record>
|
||||
|
@ -67,7 +67,7 @@
|
|||
</record>
|
||||
|
||||
<record model="ir.module.category" id="module_category_purchase_management">
|
||||
<field name="name">Purchase Management</field>
|
||||
<field name="name">Purchases</field>
|
||||
<field name="description">Helps you manage your purchase-related processes such as requests for quotations, supplier invoices, etc...</field>
|
||||
<field name="sequence">9</field>
|
||||
</record>
|
||||
|
|
|
@ -90,8 +90,8 @@
|
|||
<form string="Bank account" version="7.0">
|
||||
<group col="4">
|
||||
<field name="state"/>
|
||||
<field name="acc_number"/>
|
||||
<field name="company_id" on_change="onchange_company_id(company_id)"
|
||||
<field name="acc_number" placeholder="Account Number"/>
|
||||
<field name="company_id" groups="base.group_multi_company" on_change="onchange_company_id(company_id)"
|
||||
invisible="context.get('company_hide', True)" widget="selection"/>
|
||||
<field name="footer" invisible="context.get('footer_hide', True)"/>
|
||||
</group>
|
||||
|
@ -113,7 +113,7 @@
|
|||
<group name="bank" string="Information About the Bank">
|
||||
<field name="bank" on_change="onchange_bank_id(bank)"/>
|
||||
<field name="bank_name" attrs="{'required': [('company_id','<>',False)]}"/>
|
||||
<field name="bank_bic" placeholder="[Identifier code]" />
|
||||
<field name="bank_bic" placeholder="e.g. GEBABEBB" />
|
||||
</group>
|
||||
</group>
|
||||
|
||||
|
|
|
@ -195,7 +195,7 @@ class res_company(osv.osv):
|
|||
]
|
||||
|
||||
ids = proxy.search(cr, uid, args, context=context)
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
|
||||
for rule in proxy.browse(cr, uid, ids, context):
|
||||
if eval(rule.expression, {'context': context, 'user': user}):
|
||||
return rule.company_dest_id.id
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
import math
|
||||
import openerp
|
||||
from osv import osv, fields
|
||||
from openerp import SUPERUSER_ID
|
||||
import re
|
||||
import tools
|
||||
from tools.translate import _
|
||||
|
@ -33,7 +34,7 @@ from lxml import etree
|
|||
class format_address(object):
|
||||
def fields_view_get_address(self, cr, uid, arch, context={}):
|
||||
user_obj = self.pool.get('res.users')
|
||||
fmt = user_obj.browse(cr, uid, uid,context).company_id.country_id
|
||||
fmt = user_obj.browse(cr, SUPERUSER_ID, uid, context).company_id.country_id
|
||||
fmt = fmt and fmt.address_format
|
||||
layouts = {
|
||||
'%(city)s %(state_code)s\n%(zip)s': """
|
||||
|
@ -189,24 +190,27 @@ class res_partner(osv.osv, format_address):
|
|||
'child_ids': fields.one2many('res.partner', 'parent_id', 'Contacts'),
|
||||
'ref': fields.char('Reference', size=64, select=1),
|
||||
'lang': fields.selection(_lang_get, 'Language',
|
||||
help="If the selected language is loaded in the system, all documents related to this partner will be printed in this language. If not, it will be english."),
|
||||
help="If the selected language is loaded in the system, all documents related to this contact will be printed in this language. If not, it will be English."),
|
||||
'tz': fields.selection(_tz_get, 'Timezone', size=64,
|
||||
help="The partner's timezone, used to output proper date and time values inside printed reports. "
|
||||
"It is important to set a value for this field. You should use the same timezone "
|
||||
"that is otherwise used to pick and render date and time values: your computer's timezone."),
|
||||
'user_id': fields.many2one('res.users', 'Salesperson', help='The internal user that is in charge of communicating with this partner if any.'),
|
||||
'vat': fields.char('TIN', size=32, help="Tax Identification Number. Check the box if the partner is subjected to taxes. Used by the some of the legal statements."),
|
||||
'user_id': fields.many2one('res.users', 'Salesperson', help='The internal user that is in charge of communicating with this contact if any.'),
|
||||
'vat': fields.char('TIN', size=32, help="Tax Identification Number. Check the box if this contact is subjected to taxes. Used by the some of the legal statements."),
|
||||
'bank_ids': fields.one2many('res.partner.bank', 'partner_id', 'Banks'),
|
||||
'website': fields.char('Website', size=64, help="Website of Partner or Company"),
|
||||
'comment': fields.text('Notes'),
|
||||
'address': fields.one2many('res.partner.address', 'partner_id', 'Contacts'), # should be removed in version 7, but kept until then for backward compatibility
|
||||
'address': fields.one2many('res.partner.address', 'partner_id', 'Addresses',
|
||||
deprecated="The address information is now directly stored on each Partner record. "\
|
||||
"Multiple contacts with their own address can be added via the child_ids relationship. "\
|
||||
"This field will be removed as of OpenERP 7.1."),
|
||||
'category_id': fields.many2many('res.partner.category', id1='partner_id', id2='category_id', string='Tags'),
|
||||
'credit_limit': fields.float(string='Credit Limit'),
|
||||
'ean13': fields.char('EAN13', size=13),
|
||||
'active': fields.boolean('Active'),
|
||||
'customer': fields.boolean('Customer', help="Check this box if the partner is a customer."),
|
||||
'supplier': fields.boolean('Supplier', help="Check this box if the partner is a supplier. If it's not checked, purchase people will not see it when encoding a purchase order."),
|
||||
'employee': fields.boolean('Employee', help="Check this box if the partner is an Employee."),
|
||||
'customer': fields.boolean('Customer', help="Check this box if this contact is a customer."),
|
||||
'supplier': fields.boolean('Supplier', help="Check this box if this contact is a supplier. If it's not checked, purchase people will not see it when encoding a purchase order."),
|
||||
'employee': fields.boolean('Employee', help="Check this box if this contact is an Employee."),
|
||||
'function': fields.char('Job Position', size=128),
|
||||
'type': fields.selection([('default', 'Default'), ('invoice', 'Invoice'),
|
||||
('delivery', 'Delivery'), ('contact', 'Contact'),
|
||||
|
@ -218,7 +222,8 @@ class res_partner(osv.osv, format_address):
|
|||
'city': fields.char('City', size=128),
|
||||
'state_id': fields.many2one("res.country.state", 'State'),
|
||||
'country_id': fields.many2one('res.country', 'Country'),
|
||||
'country': fields.related('country_id', type='many2one', relation='res.country', string='Country'), # for backward compatibility
|
||||
'country': fields.related('country_id', type='many2one', relation='res.country', string='Country',
|
||||
deprecated="This field will be removed as of OpenERP 7.1, use country_id instead"),
|
||||
'email': fields.char('Email', size=240),
|
||||
'phone': fields.char('Phone', size=64),
|
||||
'fax': fields.char('Fax', size=64),
|
||||
|
@ -228,13 +233,13 @@ class res_partner(osv.osv, format_address):
|
|||
'use_parent_address': fields.boolean('Use Company Address', help="Select this if you want to set company's address information for this contact"),
|
||||
# image: all image fields are base64 encoded and PIL-supported
|
||||
'image': fields.binary("Image",
|
||||
help="This field holds the image used as avatar for the partner, limited to 1024x1024px"),
|
||||
help="This field holds the image used as avatar for this contact, limited to 1024x1024px"),
|
||||
'image_medium': fields.function(_get_image, fnct_inv=_set_image,
|
||||
string="Medium-sized image", type="binary", multi="_get_image",
|
||||
store={
|
||||
'res.partner': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
|
||||
},
|
||||
help="Medium-sized image of the partner. It is automatically "\
|
||||
help="Medium-sized image of this contact. It is automatically "\
|
||||
"resized as a 128x128px image, with aspect ratio preserved. "\
|
||||
"Use this field in form views or some kanban views."),
|
||||
'image_small': fields.function(_get_image, fnct_inv=_set_image,
|
||||
|
@ -242,7 +247,7 @@ class res_partner(osv.osv, format_address):
|
|||
store={
|
||||
'res.partner': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
|
||||
},
|
||||
help="Small-sized image of the partner. It is automatically "\
|
||||
help="Small-sized image of this contact. It is automatically "\
|
||||
"resized as a 64x64px image, with aspect ratio preserved. "\
|
||||
"Use this field anywhere a small image is required."),
|
||||
'company_id': fields.many2one('res.company', 'Company', select=1),
|
||||
|
@ -392,7 +397,7 @@ class res_partner(osv.osv, format_address):
|
|||
- otherwise: default, everything is set as the name """
|
||||
match = re.search(r'([^\s,<@]+@[^>\s,]+)', text)
|
||||
if match:
|
||||
email = match.group(1)
|
||||
email = match.group(1)
|
||||
name = text[:text.index(email)].replace('"','').replace('<','').strip()
|
||||
else:
|
||||
name, email = text, ''
|
||||
|
@ -440,7 +445,7 @@ class res_partner(osv.osv, format_address):
|
|||
def find_or_create(self, cr, uid, email, context=None):
|
||||
""" Find a partner with the given ``email`` or use :py:method:`~.name_create`
|
||||
to create one
|
||||
|
||||
|
||||
:param str email: email-like string, which should contain at least one email,
|
||||
e.g. ``"Raoul Grosbedon <r.g@grosbedon.fr>"``"""
|
||||
assert email, 'an email is required for find_or_create to work'
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -47,7 +47,7 @@
|
|||
-->
|
||||
|
||||
<record id="action_partner_title_partner" model="ir.actions.act_window">
|
||||
<field name="name">Partner Titles</field>
|
||||
<field name="name">Titles</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">res.partner.title</field>
|
||||
<field name="view_type">form</field>
|
||||
|
|
|
@ -52,7 +52,7 @@ class groups(osv.osv):
|
|||
else:
|
||||
res[g.id] = g.name
|
||||
return res
|
||||
|
||||
|
||||
def _search_group(self, cr, uid, obj, name, args, context=None):
|
||||
operand = args[0][2]
|
||||
operator = args[0][1]
|
||||
|
@ -64,7 +64,7 @@ class groups(osv.osv):
|
|||
group_name = values[1]
|
||||
where = ['|',('category_id.name', operator, application_name)] + where
|
||||
return where
|
||||
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=64, required=True, translate=True),
|
||||
'users': fields.many2many('res.users', 'res_groups_users_rel', 'gid', 'uid', 'Users'),
|
||||
|
@ -138,7 +138,7 @@ class res_users(osv.osv):
|
|||
|
||||
def _get_password(self, cr, uid, ids, arg, karg, context=None):
|
||||
return dict.fromkeys(ids, '')
|
||||
|
||||
|
||||
_columns = {
|
||||
'id': fields.integer('ID'),
|
||||
'login_date': fields.date('Latest connection', select=1),
|
||||
|
@ -193,21 +193,6 @@ class res_users(osv.osv):
|
|||
partner_ids = [user.partner_id.id for user in self.browse(cr, uid, ids, context=context)]
|
||||
return self.pool.get('res.partner').onchange_address(cr, uid, partner_ids, use_parent_address, parent_id, context=context)
|
||||
|
||||
def read(self,cr, uid, ids, fields=None, context=None, load='_classic_read'):
|
||||
def override_password(o):
|
||||
if 'password' in o and ( 'id' not in o or o['id'] != uid ):
|
||||
o['password'] = '********'
|
||||
return o
|
||||
result = super(res_users, self).read(cr, uid, ids, fields, context, load)
|
||||
canwrite = self.pool.get('ir.model.access').check(cr, uid, 'res.users', 'write', False)
|
||||
if not canwrite:
|
||||
if isinstance(ids, (int, long)):
|
||||
result = override_password(result)
|
||||
else:
|
||||
result = map(override_password, result)
|
||||
return result
|
||||
|
||||
|
||||
def _check_company(self, cr, uid, ids, context=None):
|
||||
return all(((this.company_id in this.company_ids) or not this.company_ids) for this in self.browse(cr, uid, ids, context))
|
||||
|
||||
|
@ -276,8 +261,34 @@ class res_users(osv.osv):
|
|||
return self.pool.get('res.partner').fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
|
||||
return super(res_users, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
|
||||
|
||||
# User can write to a few of her own fields (but not her groups for example)
|
||||
SELF_WRITEABLE_FIELDS = ['password', 'signature', 'action_id', 'company_id', 'email', 'name', 'image', 'image_medium', 'image_small']
|
||||
# User can write on a few of his own fields (but not his groups for example)
|
||||
SELF_WRITEABLE_FIELDS = ['password', 'signature', 'action_id', 'company_id', 'email', 'name', 'image', 'image_medium', 'image_small', 'lang', 'tz']
|
||||
# User can read a few of his own fields
|
||||
SELF_READABLE_FIELDS = ['signature', 'company_id', 'login', 'email', 'name', 'image', 'image_medium', 'image_small', 'lang', 'tz', 'groups_id', 'partner_id', '__last_update']
|
||||
|
||||
def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'):
|
||||
def override_password(o):
|
||||
if 'password' in o and ('id' not in o or o['id'] != uid):
|
||||
o['password'] = '********'
|
||||
return o
|
||||
|
||||
if fields and (ids == [uid] or ids == uid):
|
||||
for key in fields:
|
||||
if not (key in self.SELF_READABLE_FIELDS or key.startswith('context_')):
|
||||
break
|
||||
else:
|
||||
# safe fields only, so we read as super-user to bypass access rights
|
||||
uid = SUPERUSER_ID
|
||||
|
||||
result = super(res_users, self).read(cr, uid, ids, fields=fields, context=context, load=load)
|
||||
canwrite = self.pool.get('ir.model.access').check(cr, uid, 'res.users', 'write', False)
|
||||
if not canwrite:
|
||||
if isinstance(ids, (int, long)):
|
||||
result = override_password(result)
|
||||
else:
|
||||
result = map(override_password, result)
|
||||
|
||||
return result
|
||||
|
||||
def write(self, cr, uid, ids, values, context=None):
|
||||
if not hasattr(ids, '__iter__'):
|
||||
|
@ -495,14 +506,14 @@ class res_users(osv.osv):
|
|||
"""
|
||||
assert group_ext_id and '.' in group_ext_id, "External ID must be fully qualified"
|
||||
module, ext_id = group_ext_id.split('.')
|
||||
cr.execute("""SELECT 1 FROM res_groups_users_rel WHERE uid=%s AND gid IN
|
||||
cr.execute("""SELECT 1 FROM res_groups_users_rel WHERE uid=%s AND gid IN
|
||||
(SELECT res_id FROM ir_model_data WHERE module=%s AND name=%s)""",
|
||||
(uid, module, ext_id))
|
||||
return bool(cr.fetchone())
|
||||
|
||||
|
||||
#
|
||||
# Extension of res.groups and res.users with a relation for "implied" or
|
||||
# Extension of res.groups and res.users with a relation for "implied" or
|
||||
# "inherited" groups. Once a user belongs to a group, it automatically belongs
|
||||
# to the implied groups (transitively).
|
||||
#
|
||||
|
|
|
@ -45,7 +45,9 @@
|
|||
<form string="Access Controls" version="7.0">
|
||||
<group col="4">
|
||||
<field name="name"/>
|
||||
<field name="active"/>
|
||||
<field name="model_id"/>
|
||||
<newline/>
|
||||
<field name="perm_read"/>
|
||||
<field name="perm_write"/>
|
||||
<field name="perm_create"/>
|
||||
|
@ -202,8 +204,6 @@
|
|||
</h1>
|
||||
<group name="preferences" col="4">
|
||||
<field name="lang" readonly="0"/>
|
||||
<field name="company_id" readonly="0"
|
||||
groups="base.group_multi_company" on_change="on_change_company_id(company_id)"/>
|
||||
<field name="tz" readonly="0"/>
|
||||
<field name="company_id" widget="selection" readonly="0"
|
||||
groups="base.group_multi_company" on_change="on_change_company_id(company_id)"/>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<field name="name">Access Rights</field>
|
||||
</record>
|
||||
<record model="res.groups" id="group_system">
|
||||
<field name="name">Configuration</field>
|
||||
<field name="name">Settings</field>
|
||||
<field name="implied_ids" eval="[(4, ref('group_erp_manager'))]"/>
|
||||
<field name="users" eval="[(4, ref('base.user_root'))]"/>
|
||||
</record>
|
||||
|
|
|
@ -1552,24 +1552,16 @@ def field_to_dict(model, cr, user, field, context=None):
|
|||
res['fnct_search'] = field._fnct_search and field._fnct_search.func_name or False
|
||||
res['fnct_inv'] = field._fnct_inv and field._fnct_inv.func_name or False
|
||||
res['fnct_inv_arg'] = field._fnct_inv_arg or False
|
||||
res['func_obj'] = field._obj or False
|
||||
if isinstance(field, many2many):
|
||||
(table, col1, col2) = field._sql_names(model)
|
||||
res['related_columns'] = [col1, col2]
|
||||
res['third_table'] = table
|
||||
for arg in ('string', 'readonly', 'states', 'size', 'required', 'group_operator',
|
||||
'change_default', 'translate', 'help', 'select', 'selectable', 'groups'):
|
||||
if getattr(field, arg):
|
||||
res[arg] = getattr(field, arg)
|
||||
for arg in ('digits', 'invisible', 'filters'):
|
||||
res['m2m_join_columns'] = [col1, col2]
|
||||
res['m2m_join_table'] = table
|
||||
for arg in ('string', 'readonly', 'states', 'size', 'group_operator', 'required',
|
||||
'change_default', 'translate', 'help', 'select', 'selectable', 'groups',
|
||||
'deprecated', 'digits', 'invisible', 'filters'):
|
||||
if getattr(field, arg, None):
|
||||
res[arg] = getattr(field, arg)
|
||||
|
||||
if field.string:
|
||||
res['string'] = field.string
|
||||
if field.help:
|
||||
res['help'] = field.help
|
||||
|
||||
if hasattr(field, 'selection'):
|
||||
if isinstance(field.selection, (tuple, list)):
|
||||
res['selection'] = field.selection
|
||||
|
|
Loading…
Reference in New Issue