HDA (OpenERP) 2010-01-13 13:03:01 +05:30
commit a922f46615
20 changed files with 446 additions and 565 deletions

View File

@ -33,6 +33,7 @@
'base_menu.xml',
'security/base_security.xml',
'res/res_security.xml',
'res/res_config.xml',
'maintenance/maintenance_security.xml'
],
'update_xml': [

View File

@ -141,6 +141,7 @@ CREATE TABLE res_users (
active boolean default True,
login varchar(64) NOT NULL UNIQUE,
password varchar(64) default null,
email varchar(64) default null,
context_tz varchar(64) default null,
signature text,
-- action_id int references ir_act_window on delete set null,

View File

@ -206,48 +206,50 @@
</record>
<record id="view_users_configuration_form" model="ir.ui.view">
<field name="name">res.users.confirm.form</field>
<field name="model">res.users</field>
<field name="name">res.config.users.confirm.form</field>
<field name="model">res.config.users</field>
<field name="type">form</field>
<field name="inherit_id" ref="res_config_view_base"/>
<field name="arch" type="xml">
<form string="Configure User">
<separator string="Define New Users" colspan="4"/>
<field name="name" select="1"/>
<field name="active" select="1"/>
<field name="login" select="1"/>
<field name="password" password="True"/>
<notebook colspan="4">
<page string="User">
<field name="address_id"/>
<field name="company_id" required="1"/>
<field name="action_id" required="True"/>
<field domain="[('usage','=','menu')]" name="menu_id" required="True"/>
<field name="context_lang"/>
<field name="context_tz"/>
<field colspan="4" name="signature"/>
</page>
<page string="Groups">
<label string="Groups are used to defined access rights on each screen and menu." align="0.0" colspan="4"/>
<field colspan="4" nolabel="1" name="groups_id"/>
</page>
<page string="Roles">
<label string="Roles are used to defined available actions, provided by workflows." align="0.0" colspan="4"/>
<field colspan="4" nolabel="1" name="roles_id"/>
</page>
</notebook>
<label string="" colspan="2"/>
<group col="2" colspan="2">
<button icon='gtk-cancel' special="cancel" name="action_next" type='object' string='Skip'/>
<button name='action_new' icon='gtk-ok' type='object' string='Add User'/>
</group>
<data>
<form position="attributes">
<attribute name="string">Create User</attribute>
</form>
<group string="res_config_contents" position="replace">
<separator string="New User" colspan="4"/>
<field name="name"/>
<field name="email"/>
<field name="login"/>
<field name="password" password="True"/>
<field name="context_lang"/>
<field name="context_tz"/>
<separator string="Group" colspan="4"/>
<label align="0.0" colspan="4" string="
Groups are used to define access rights on objects and
the visibility of screens and menus"/>
<field colspan="4" nolabel="1" name="groups_id"/>
</group>
<xpath expr='//button[@name="action_skip"]'
position='attributes'>
<attribute name='string'>Next</attribute>
<attribute name='icon'>gtk-go-forward</attribute>
</xpath>
<xpath expr='//button[@name="action_next"]'
position='attributes'>
<attribute name='string'>Add User</attribute>
<attribute name='icon'>gtk-add</attribute>
</xpath>
</data>
</field>
</record>
<record id="action_config_user_form" model="ir.actions.act_window">
<field name="name">Configure User</field>
<field name="name">Create Users</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">res.users</field>
<field name="res_model">res.config.users</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="view_users_configuration_form"/>
@ -258,26 +260,43 @@
<field name="name">res.users.confirm.simple_view</field>
<field name="model">res.config.view</field>
<field name="type">form</field>
<field name="inherit_id" ref="res_config_view_base"/>
<field name="arch" type="xml">
<form string="Configure simple view">
<separator string="Choose Your Mode" colspan="4"/>
<field colspan="2" name="view"/>
<label string="Choose the simplified interface if you are testing OpenERP for the first time. Less used options or fields are automatically hidden. You will be able to change this, later, through the Administration menu." colspan="4" align="0.0"/>
<newline/>
<separator string="" colspan="4"/>
<label string="" colspan="2"/>
<group colspan="2" col="1">
<button icon="gtk-ok" name="action_set" string="Set" type="object"/>
</group>
<data>
<form position="attributes">
<attribute name="string">Select your Interface</attribute>
</form>
<group string="res_config_contents" position="replace">
<label colspan="4" align="0.0" string='
Choose between the simplified interface and the extended
one.'/>
<newline/>
<label colspan="4" align="0.0" string='
If you are testing OpenERP or using it for the first time,
we suggest you use the simplified interface. It has less
options and fields but is easier to understand.'/>
<newline/>
<label colspan="4" align="0.0" string='
You will be able to switch to the extended interface later.
'/>
<separator string="Choose Your Interface" colspan="4"/>
<field colspan="2" name="view" nolabel="1"/>
</group>
<xpath expr='//button[@name="action_skip"]' position='replace'/>
<xpath expr='//button[@name="action_next"]' position='attributes'>
<attribute name='string'>Set</attribute>
</xpath>
</data>
</field>
</record>
<record id="action_config_simple_view_form" model="ir.actions.act_window">
<field name="name">Configure Simple View</field>
<field name="name">Select Your Interface</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">res.config.view</field>
<field name="view_type">form</field>
<field name="view_id" ref="view_confirm_simple_view_form"/>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
@ -289,21 +308,11 @@
</data>
<data noupdate="1">
<record id="config_wizard_step_user" model="ir.actions.todo">
<field name="name">Create User</field>
<field name="note">Create your users.
You will be able to assign groups to users. Groups define the access rights of each users on the different objects of the system.
</field>
<field name="action_id" ref="action_config_user_form"/>
<field name="sequence">10</field>
</record>
<record id="config_wizard_simple_view" model="ir.actions.todo">
<field name="name">Select Your Interface</field>
<field name="note">Choose between the "Simplified Interface" or the extended one.
If you are testing or using OpenERP for the first time, we suggest you to use
the simplified interface, which has less options and fields but is easier to
understand. You will be able to switch to the extended view later.
</field>
<field name="action_id" ref="action_config_simple_view_form"/>
<field name="sequence">5</field>
</record>

View File

@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-01-11 17:26+0000\n"
"Last-Translator: Luiz Fernando M.França <Unknown>\n"
"PO-Revision-Date: 2010-01-12 06:01+0000\n"
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-01-12 04:46+0000\n"
"X-Launchpad-Export-Date: 2010-01-13 04:50+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base

View File

@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-01-11 06:03+0000\n"
"PO-Revision-Date: 2010-01-12 06:02+0000\n"
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-01-12 04:46+0000\n"
"X-Launchpad-Export-Date: 2010-01-13 04:50+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base

View File

@ -1341,11 +1341,10 @@
<field name="type">tree</field>
<field name="arch" type="xml">
<tree editable="bottom" string="Config Wizard Steps">
<field name="name" select="1"/>
<field name="action_id" select="1"/>
<field name="sequence"/>
<field name="action_id" select="1"/>
<field name="state"/>
<field name="active" select="1"/>
<field name="active" select="2"/>
</tree>
</field>
</record>
@ -1355,12 +1354,10 @@
<field name="type">form</field>
<field name="arch" type="xml">
<form editable="bottom" string="Config Wizard Steps">
<field name="name" select="1"/>
<field name="active" select="1"/>
<field name="action_id" select="1"/>
<field name="sequence"/>
<field name="action_id" select="1"/>
<field name="state"/>
<field colspan="4" name="note"/>
<field name="active" select="2"/>
</form>
</field>
</record>
@ -1369,42 +1366,18 @@
<field name="res_model">ir.actions.todo</field>
<field name="view_id" ref="ir_actions_todo_tree"/>
<field name="view_type">form</field>
<field name="domain">[('type','=','configure')]</field>
</record>
<menuitem id="next_id_11" name="Configuration Wizards" parent="base.menu_config" sequence="1"/>
<menuitem action="act_ir_actions_todo_form" id="menu_ir_actions_todo_form" parent="next_id_11"/>
<record id="view_config_wizard_form" model="ir.ui.view">
<field name="name">Main Configuration Wizard</field>
<field name="model">ir.actions.configuration.wizard</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Next Configuration Step">
<image name="gtk-dialog-info"/>
<group>
<separator string="Next Configuration Step" colspan="4"/>
<field name="name" nolabel="1" colspan="4" width="500"/>
<field name="progress" widget="progressbar"/>
<separator colspan="4" string=""/>
<label string="" colspan="2"/>
<group colspan="2" col="2">
<button icon="gtk-cancel" name="button_skip" string="Skip Step" type="object"/>
<button icon="gtk-go-forward" name="button_continue" string="Continue" type="object"/>
</group>
</group>
</form>
</field>
<record id="action_start_configurator" model="ir.actions.server">
<field name="name">Start Configuration</field>
<field name="model_id" ref="model_res_config"/>
<field name="state">code</field>
<field name="code">action = self.next(cr, uid, [])</field>
</record>
<record id="action_config_wizard_form" model="ir.actions.act_window">
<field name="name">Configuration Wizard</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">ir.actions.configuration.wizard</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<menuitem action="action_config_wizard_form" id="menu_config_module" parent="base.next_id_11"/>
<menuitem action="action_start_configurator" name="Start Configuration"
id="menu_configurator_module" parent="next_id_11"
type="server"/>
</data>
</openerp>

View File

@ -28,7 +28,6 @@ import netsvc
import re
import copy
import sys
from xml import dom
class actions(osv.osv):
@ -344,59 +343,6 @@ class ir_model_fields(osv.osv):
_columns = {
'complete_name': fields.char('Complete Name', size=64, select=1),
}
def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100):
return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit)
# def get_fields(cr, uid, field, rel):
# result = []
# mobj = self.pool.get('ir.model')
# id = mobj.search(cr, uid, [('model','=',rel)])
# obj = self.pool.get('ir.model.fields')
# ids = obj.search(cr, uid, [('model_id','in',id)])
# records = obj.read(cr, uid, ids)
# for record in records:
# id = record['id']
# fld = field + '/' + record['name']
# result.append((id, fld))
# return result
# if not args:
# args=[]
# if not context:
# context={}
# return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit)
# if context.get('key') != 'server_action':
# return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit)
# result = []
# obj = self.pool.get('ir.model.fields')
# ids = obj.search(cr, uid, args)
# records = obj.read(cr, uid, ids)
# for record in records:
# id = record['id']
# field = record['name']
# if record['ttype'] == 'many2one':
# rel = record['relation']
# res = get_fields(cr, uid, field, record['relation'])
# for rs in res:
# result.append(rs)
# result.append((id, field))
# for rs in result:
# obj.write(cr, uid, [rs[0]], {'complete_name':rs[1]})
# iids = []
# for rs in result:
# iids.append(rs[0])
# result = super(ir_model_fields, self).name_search(cr, uid, name, [('complete_name','ilike',name), ('id','in',iids)], operator, context, limit)
# return result
ir_model_fields()
class server_object_lines(osv.osv):
@ -429,7 +375,7 @@ class actions_server(osv.osv):
result = cr.fetchall() or []
res = []
for rs in result:
if not rs[0] == None and not rs[1] == None:
if rs[0] is not None and rs[1] is not None:
res.append(rs)
return res
@ -577,8 +523,8 @@ class actions_server(osv.osv):
if action.state=='client_action':
if not action.action_id:
raise osv.except_osv(_('Error'), _("Please specify an action to launch !"))
result = self.pool.get(action.action_id.type).read(cr, uid, action.action_id.id, context=context)
return result
return self.pool.get(action.action_id.type)\
.read(cr, uid, action.action_id.id, context=context)
if action.state == 'code':
localdict = {
@ -733,128 +679,29 @@ class act_window_close(osv.osv):
act_window_close()
# This model use to register action services.
# if action type is 'configure', it will be start on configuration wizard.
# if action type is 'service',
# - if start_type= 'at once', it will be start at one time on start date
# - if start_type='auto', it will be start on auto starting from start date, and stop on stop date
# - if start_type="manual", it will start and stop on manually
TODO_STATES = [('open', 'Not Started'),
('done', 'Done'),
('skip','Skipped'),
('cancel','Cancel')]
class ir_actions_todo(osv.osv):
_name = 'ir.actions.todo'
_columns={
'name':fields.char('Name',size=64,required=True, select=True),
'note':fields.text('Text', translate=True),
'start_date': fields.datetime('Start Date'),
'end_date': fields.datetime('End Date'),
'action_id':fields.many2one('ir.actions.act_window', 'Action', select=True,required=True, ondelete='cascade'),
'sequence':fields.integer('Sequence'),
'action_id': fields.many2one(
'ir.actions.act_window', 'Action', select=True, required=True,
ondelete='cascade'),
'sequence': fields.integer('Sequence'),
'active': fields.boolean('Active'),
'type':fields.selection([('configure', 'Configure'),('service', 'Service'),('other','Other')], string='Type', required=True),
'start_on':fields.selection([('at_once', 'At Once'),('auto', 'Auto'),('manual','Manual')], string='Start On'),
'groups_id': fields.many2many('res.groups', 'res_groups_act_todo_rel', 'act_todo_id', 'group_id', 'Groups'),
'users_id': fields.many2many('res.users', 'res_users_act_todo_rel', 'act_todo_id', 'user_id', 'Users'),
'state':fields.selection([('open', 'Not Started'),('done', 'Done'),('skip','Skipped'),('cancel','Cancel')], string='State', required=True)
'state': fields.selection(TODO_STATES, string='State', required=True),
'name':fields.char('Name', size=64),
'note':fields.text('Text', translate=True),
}
_defaults={
'state': lambda *a: 'open',
'sequence': lambda *a: 10,
'active':lambda *a:True,
'type':lambda *a:'configure'
'active': lambda *a: True,
}
_order="sequence"
ir_actions_todo()
# This model to use run all configuration actions
class ir_actions_configuration_wizard(osv.osv_memory):
_name='ir.actions.configuration.wizard'
def next_configuration_action(self,cr,uid,context={}):
item_obj = self.pool.get('ir.actions.todo')
item_ids = item_obj.search(cr, uid, [('type','=','configure'),('state', '=', 'open'),('active','=',True)], limit=1, context=context)
if item_ids and len(item_ids):
item = item_obj.browse(cr, uid, item_ids[0], context=context)
return item
return False
def _get_action_name(self, cr, uid, context={}):
next_action=self.next_configuration_action(cr,uid,context=context)
if next_action:
return next_action.note
else:
return "Your database is now fully configured.\n\nClick 'Continue' and enjoy your OpenERP experience..."
return False
def _get_action(self, cr, uid, context={}):
next_action=self.next_configuration_action(cr,uid,context=context)
if next_action:
return next_action.id
return False
def _progress_get(self,cr,uid, context={}):
total = self.pool.get('ir.actions.todo').search_count(cr, uid, [], context)
todo = self.pool.get('ir.actions.todo').search_count(cr, uid, [('type','=','configure'),('active','=',True),('state','<>','open')], context)
if total > 0.0:
return max(5.0,round(todo*100/total))
else:
return 100.0
_columns = {
'name': fields.text('Next Wizard',readonly=True),
'progress': fields.float('Configuration Progress', readonly=True),
'item_id':fields.many2one('ir.actions.todo', 'Next Configuration Wizard',invisible=True, readonly=True),
}
_defaults={
'progress': _progress_get,
'item_id':_get_action,
'name':_get_action_name,
}
def button_next(self,cr,uid,ids,context=None):
user_action=self.pool.get('res.users').browse(cr,uid,uid)
act_obj=self.pool.get(user_action.menu_id.type)
action_ids=act_obj.search(cr,uid,[('name','=',user_action.menu_id.name)])
action_open=act_obj.browse(cr,uid,action_ids)[0]
if context.get('menu',False):
return{
'view_type': action_open.view_type,
'view_id':action_open.view_id and [action_open.view_id.id] or False,
'res_model': action_open.res_model,
'type': action_open.type,
'domain':action_open.domain
}
return {'type':'ir.actions.act_window_close'}
def button_skip(self,cr,uid,ids,context=None):
item_obj = self.pool.get('ir.actions.todo')
item_id=self.read(cr,uid,ids)[0]['item_id']
if item_id:
item = item_obj.browse(cr, uid, item_id, context=context)
item_obj.write(cr, uid, item.id, {
'state': 'skip',
}, context=context)
return{
'view_type': 'form',
"view_mode": 'form',
'res_model': 'ir.actions.configuration.wizard',
'type': 'ir.actions.act_window',
'target':'new',
}
return self.button_next(cr, uid, ids, context)
def button_continue(self, cr, uid, ids, context=None):
item_obj = self.pool.get('ir.actions.todo')
item_id=self.read(cr,uid,ids)[0]['item_id']
if item_id:
item = item_obj.browse(cr, uid, item_id, context=context)
item_obj.write(cr, uid, item.id, {
'state': 'done',
}, context=context)
return{
'view_mode': item.action_id.view_mode,
'view_type': item.action_id.view_type,
'view_id':item.action_id.view_id and [item.action_id.view_id.id] or False,
'res_model': item.action_id.res_model,
'type': item.action_id.type,
'target':item.action_id.target,
}
return self.button_next(cr, uid, ids, context)
ir_actions_configuration_wizard()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -611,38 +611,4 @@ class ir_model_data(osv.osv):
return True
ir_model_data()
class ir_model_config(osv.osv):
_name = 'ir.model.config'
_columns = {
'password': fields.char('Password', size=64),
'password_check': fields.char('Confirmation', size=64),
}
def action_cancel(self, cr, uid, ids, context={}):
return {
'view_type': 'form',
"view_mode": 'form',
'res_model': 'ir.actions.configuration.wizard',
'type': 'ir.actions.act_window',
'target':'new',
}
def action_update_pw(self, cr, uid, ids, context={}):
res = self.read(cr,uid,ids)[0]
root = self.pool.get('res.users').browse(cr, uid, [1])[0]
self.unlink(cr, uid, [res['id']])
if res['password']!=res['password_check']:
raise except_orm(_('Error'), _("Password mismatch !"))
elif not res['password']:
raise except_orm(_('Error'), _("Password empty !"))
self.pool.get('res.users').write(cr, uid, [root.id], {'password':res['password']})
return {
'view_type': 'form',
"view_mode": 'form',
'res_model': 'ir.actions.configuration.wizard',
'type': 'ir.actions.act_window',
'target':'new',
}
ir_model_config()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -6,6 +6,7 @@ class module_web(osv.osv):
_columns = {
'name': fields.char("Name", size=128, readonly=True, required=True),
'module': fields.char("Module", size=128, readonly=True, required=True),
'description': fields.text("Description", readonly=True, translate=True),
'author': fields.char("Author", size=128, readonly=True),
'website': fields.char("Website", size=256, readonly=True),

View File

@ -9,6 +9,7 @@
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="module"/>
<field name="description"/>
<field name="author"/>
<field name="state"/>

View File

@ -92,13 +92,8 @@ class wizard_info_get(wizard.interface):
return {}
def _config(self, cr, uid, data, context=None):
return {
'view_type': 'form',
"view_mode": 'form',
'res_model': 'ir.actions.configuration.wizard',
'type': 'ir.actions.act_window',
'target':'new',
}
return pooler.get_pool(cr.dbname).get('res.config')\
.next(cr, uid, [], context=context)
states = {
'init': {
@ -183,13 +178,8 @@ class wizard_info_get_simple(wizard.interface):
return {}
def _config(self, cr, uid, data, context=None):
return {
'view_type': 'form',
"view_mode": 'form',
'res_model': 'ir.actions.configuration.wizard',
'type': 'ir.actions.act_window',
'target':'new',
}
return pooler.get_pool(cr.dbname).get('res.config')\
.next(cr, uid, [], context=context)
states = {
'init': {

View File

@ -25,6 +25,7 @@ import country
import bank
import res_lang
import partner
import res_config
import res_currency
import res_company
import res_user

View File

@ -271,7 +271,15 @@ class res_partner(osv.osv):
if (not context.get('category_id', False)):
return False
return _('Partners: ')+self.pool.get('res.partner.category').browse(cr, uid, context['category_id'], context).name
def main_partner(self, cr, uid):
''' Return the id of the main partner
'''
model_data = self.pool.get('ir.model.data')
return model_data.browse(
cr, uid,
model_data.search(cr, uid, [('module','=','base'),
('name','=','main_partner')])[0],
).res_id
res_partner()
class res_partner_address(osv.osv):

View File

@ -0,0 +1,196 @@
# -*- 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 osv, fields
import netsvc
import pooler
class res_config_configurable(osv.osv_memory):
''' Base classes for new-style configuration items
Configuration items should inherit from this class, implement
the execute method (and optionally the cancel one) and have
their view inherit from the related res_config_view_base view.
'''
_name = 'res.config'
logger = netsvc.Logger()
def _progress(self, cr, uid, context=None):
total = self.pool.get('ir.actions.todo')\
.search_count(cr, uid, [], context)
open = self.pool.get('ir.actions.todo')\
.search_count(cr, uid, [('active','=',True),
('state','<>','open')],
context)
if total:
return round(open*100./total)
return 100.
_columns = dict(
progress=fields.float('Configuration Progress', readonly=True),
)
_defaults = dict(
progress=_progress
)
def _next_action(self, cr, uid):
todos = self.pool.get('ir.actions.todo')
self.logger.notifyChannel('actions', netsvc.LOG_INFO,
'getting next %s' % todos)
active_todos = todos.search(cr, uid, [('state','=','open'),
('active','=',True)],
limit=1, context=None)
if active_todos:
return todos.browse(cr, uid, active_todos[0], context=None)
return None
def _next(self, cr, uid):
self.logger.notifyChannel('actions', netsvc.LOG_INFO,
'getting next operation')
next = self._next_action(cr, uid)
self.logger.notifyChannel('actions', netsvc.LOG_INFO,
'next action is %s' % next)
if next:
self.pool.get('ir.actions.todo').write(cr, uid, next.id, {
'state':'done',
}, context=None)
action = next.action_id
return {
'view_mode': action.view_mode,
'view_type': action.view_type,
'view_id': action.view_id and [action.view_id.id] or False,
'res_model': action.res_model,
'type': action.type,
'target': action.target,
}
self.logger.notifyChannel(
'actions', netsvc.LOG_INFO,
'all configuration actions have been executed')
current_user_menu = self.pool.get('res.users')\
.browse(cr, uid, uid).menu_id
# return the action associated with the menu
return self.pool.get(current_user_menu.type)\
.read(cr, uid, current_user_menu.id)
def next(self, cr, uid, ids, context=None):
return self._next(cr, uid)
def execute(self, cr, uid, ids, context=None):
raise NotImplementedError(
'Configuration items need to implement execute')
def cancel(self, cr, uid, ids, context=None):
pass
def action_next(self, cr, uid, ids, context=None):
next = self.execute(cr, uid, ids, context=None)
if next: return next
return self.next(cr, uid, ids, context=context)
def action_skip(self, cr, uid, ids, context=None):
next = self.cancel(cr, uid, ids, context=None)
if next: return next
return self.next(cr, uid, ids, context=context)
res_config_configurable()
class res_config_installer(osv.osv_memory):
''' New-style configuration base specialized for modules selection
and installation.
'''
_name = 'res.config.installer'
_inherit = 'res.config'
_install_if = {}
def _modules_to_install(self, cr, uid, ids, context=None):
base = set(module_name
for installer in self.read(cr, uid, ids, context=context)
for module_name, to_install in installer.iteritems()
if module_name != 'id'
if type(self._columns[module_name]) is fields.boolean
if to_install)
hooks_results = set()
for module in base:
hook = getattr(self, '_if_%s'%(module), None)
if hook:
hooks_results.update(hook(cr, uid, ids, context=None) or set())
additionals = set(
module for requirements, consequences \
in self._install_if.iteritems()
if base.issuperset(requirements)
for module in consequences)
return base | hooks_results | additionals
def execute(self, cr, uid, ids, context=None):
modules = self.pool.get('ir.module.module')
to_install = list(self._modules_to_install(
cr, uid, ids, context=context))
self.logger.notifyChannel(
'installer', netsvc.LOG_INFO,
'Selecting addons %s to install'%to_install)
modules.state_update(
cr, uid,
modules.search(cr, uid, [('name','in',to_install)]),
'to install', ['uninstalled'], context=context)
cr.commit()
pooler.restart_pool(cr.dbname, update_module=True)
res_config_installer()
DEPRECATION_MESSAGE = 'You are using an addon using old-style configuration '\
'wizards (ir.actions.configuration.wizard). Old-style configuration '\
'wizards have been deprecated.\n'\
'The addon should be migrated to res.config objects.'
class ir_actions_configuration_wizard(osv.osv_memory):
''' Compatibility configuration wizard
The old configuration wizard has been replaced by res.config, but in order
not to break existing but not-yet-migrated addons, the old wizard was
reintegrated and gutted.
'''
_name='ir.actions.configuration.wizard'
_inherit = 'res.config'
def _next_action_note(self, cr, uid, ids, context=None):
next = self._next_action(cr, uid)
if next:
# if the next one is also an old-style extension, you never know...
if next.note:
return next.note
return "Click 'Continue' to configure the next addon..."
return "Your database is now fully configured.\n\n"\
"Click 'Continue' and enjoy your OpenERP experience..."
_columns = {
'note': fields.text('Next Wizard', readonly=True),
}
_defaults = {
'note': _next_action_note,
}
def execute(self, cr, uid, ids, context=None):
self.logger.notifyChannel(
'configuration', netsvc.LOG_WARNING, DEPRECATION_MESSAGE)
ir_actions_configuration_wizard()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,51 @@
<openerp>
<data>
<record id="res_config_view_base" model="ir.ui.view">
<field name="name">res.config.view.base</field>
<field name="model">res.config</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form>
<group string="res_config_contents">
</group>
<separator string="" colspan="4"/>
<group colspan="4" col="8">
<field name="progress" widget="progressbar"/>
<label string="" colspan="3"/>
<group colspan="1" col="2">
<button name="action_skip" icon="gtk-goto-last" special="cancel"
type="object" string="Skip"/>
</group>
<group colspan="1" col="2">
<button name="action_next" icon="gtk-go-forward"
type="object" string="Next"/>
</group>
</group>
</form>
</field>
</record>
<record id="view_config_wizard_form" model="ir.ui.view">
<field name="name">Compabitiliby configuration wizard</field>
<field name="model">ir.actions.configuration.wizard</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Next Configuration Step">
<image name="gtk-dialog-info"/>
<group>
<field name="note" nolabel="1" colspan="4" width="500"/>
<group colspan="4" col="8">
<field name="progress" widget="progressbar"/>
<label string="" colspan="4"/>
<group colspan="1" col="2">
<button name="action_next" icon="gtk-go-forward"
type="object" string="Continue"/>
</group>
</group>
</group>
</form>
</field>
</record>
</data>
</openerp>

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
@ -15,7 +15,7 @@
# 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/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@ -60,7 +60,7 @@ class groups(osv.osv):
if vals['name'].startswith('-'):
raise osv.except_osv(_('Error'),
_('The name of the group can not start with "-"'))
gid = super(groups, self).create(cr, uid, vals, context=context)
gid = super(groups, self).create(cr, uid, vals, context=context)
if context and context.get('noadmin', False):
pass
else:
@ -120,18 +120,19 @@ def _companies_get(self,cr, uid, context={}):
class users(osv.osv):
__admin_ids = {}
_name = "res.users"
#_log_access = False
def get_current_company(self, cr, uid):
res=[]
cr.execute('select company_id, res_company.name from res_users left join res_company on res_company.id = company_id where res_users.id=%s' %uid)
res = cr.fetchall()
return res
return res
_columns = {
'name': fields.char('Name', size=64, required=True, select=True),
'login': fields.char('Login', size=64, required=True),
'password': fields.char('Password', size=64, invisible=True, help="Keep empty if you don't want the user to be able to connect on the system."),
'email': fields.char('E-mail', size=64, help='If an email is provided'\
', the user will be sent a message welcoming him'),
'signature': fields.text('Signature', size=64),
'address_id': fields.many2one('res.partner.address', 'Address'),
'active': fields.boolean('Active'),
@ -144,7 +145,7 @@ class users(osv.osv):
'company_ids':fields.many2many('res.company','res_company_users_rel','user_id','cid','Accepted Companies'),
'context_lang': fields.selection(_lang_get, 'Language', required=True),
'context_tz': fields.selection(_tz_get, 'Timezone', size=64),
'company': fields.selection(_companies_get, 'Company', size=64),
'company': fields.selection(_companies_get, 'Company', size=64),
}
def read(self,cr, uid, ids, fields=None, context=None, load='_classic_read'):
def override_password(o):
@ -188,13 +189,14 @@ class users(osv.osv):
return ids or False
_defaults = {
'password' : lambda obj,cr,uid,context={} : '',
'password' : lambda *a : '',
'context_lang': lambda *args: 'en_US',
'active' : lambda obj,cr,uid,context={} : True,
'active' : lambda *a: True,
'menu_id': _get_menu,
'action_id': _get_menu,
'company_id': _get_company,
'groups_id': _get_group,
'address_id': False,
}
def company_get(self, cr, uid, uid2):
company_id = self.pool.get('res.users').browse(cr, uid, uid2).company_id.id
@ -246,37 +248,6 @@ class users(osv.osv):
result[k[8:]] = getattr(user,k)
return result
def action_get(self, cr, uid, context={}):
dataobj = self.pool.get('ir.model.data')
data_id = dataobj._get_id(cr, 1, 'base', 'action_res_users_my')
return dataobj.browse(cr, uid, data_id, context).res_id
def action_next(self,cr,uid,ids,context=None):
return {
'view_type': 'form',
"view_mode": 'form',
'res_model': 'ir.actions.configuration.wizard',
'type': 'ir.actions.act_window',
'target':'new',
}
def action_continue(self,cr,uid,ids,context={}):
return {
'view_type': 'form',
"view_mode": 'form',
'res_model': 'ir.actions.configuration.wizard',
'type': 'ir.actions.act_window',
'target':'new',
}
def action_new(self,cr,uid,ids,context={}):
return {
'view_type': 'form',
"view_mode": 'form',
'res_model': 'res.users',
'view_id':self.pool.get('ir.ui.view').search(cr,uid,[('name','=','res.users.confirm.form')]),
'type': 'ir.actions.act_window',
'target':'new',
}
def _check_company(self, cursor, user, ids):
for user in self.browse(cursor, user, ids):
@ -284,11 +255,59 @@ class users(osv.osv):
return False
return True
def action_get(self, cr, uid, context={}):
dataobj = self.pool.get('ir.model.data')
data_id = dataobj._get_id(cr, 1, 'base', 'action_res_users_my')
return dataobj.browse(cr, uid, data_id, context).res_id
_constraints = [
(_check_company, 'This user can not connect using this company !', ['company_id']),
]
users()
class config_users(osv.osv_memory):
_name = 'res.config.users'
_inherit = ['res.users', 'res.config']
def _generate_signature(self, cr, name, email, context=None):
return _('--\n%(name)s %(email)s\n') % {
'name': name or '',
'email': email and ' <'+email+'>' or '',
}
def create_user(self, cr, uid, new_id, context=None):
''' create a new res.user instance from the data stored
in the current res.config.users
'''
base_data = self.read(cr, uid, new_id, context=context)
partner_id = self.pool.get('res.partner').main_partner(cr, uid)
address = self.pool.get('res.partner.address').create(
cr, uid, {'name': base_data['name'],
'email': base_data['email'],
'partner_id': partner_id,},
context)
user_data = dict(
base_data,
signature=self._generate_signature(
cr, base_data['name'], base_data['email'], context=context),
address_id=address,
)
self.pool.get('res.users').create(
cr, uid, user_data, context)
def execute(self, cr, uid, ids, context=None):
self.create_user(cr, uid, ids[0], context=context)
return {
'view_type': 'form',
"view_mode": 'form',
'res_model': 'res.config.users',
'view_id':self.pool.get('ir.ui.view')\
.search(cr,uid,[('name','=','res.config.users.confirm.form')]),
'type': 'ir.actions.act_window',
'target':'new',
}
config_users()
class groups2(osv.osv): ##FIXME: Is there a reason to inherit this object ?
_inherit = 'res.groups'
_columns = {
@ -296,26 +315,20 @@ class groups2(osv.osv): ##FIXME: Is there a reason to inherit this object ?
}
groups2()
class res_config_view(osv.osv_memory):
_name='res.config.view'
_name = 'res.config.view'
_inherit = 'res.config'
_columns = {
'name':fields.char('Name', size=64),
'view': fields.selection([('simple','Simplified Interface'),('extended','Extended Interface')], 'View Mode', required=True ),
'view': fields.selection([('simple','Simplified'),
('extended','Extended')],
'Interface', required=True ),
}
_defaults={
'view':lambda *args: 'simple',
}
def action_cancel(self,cr,uid,ids,conect=None):
return {
'view_type': 'form',
"view_mode": 'form',
'res_model': 'ir.actions.configuration.wizard',
'type': 'ir.actions.act_window',
'target':'new',
}
def action_set(self, cr, uid, ids, context=None):
def execute(self, cr, uid, ids, context=None):
res=self.read(cr,uid,ids)[0]
users_obj = self.pool.get('res.users')
group_obj=self.pool.get('res.groups')
@ -325,14 +338,6 @@ class res_config_view(osv.osv_memory):
users_obj.write(cr, uid, [uid],{
'groups_id':[(4,group_ids[0])]
}, context=context)
return {
'view_type': 'form',
"view_mode": 'form',
'res_model': 'ir.actions.configuration.wizard',
'type': 'ir.actions.act_window',
'target':'new',
}
res_config_view()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -8,13 +8,11 @@
"access_ir_model_group_erp_manager","ir_model group_erp_manager","model_ir_model","group_erp_manager",1,1,1,1
"access_ir_model_access_group_erp_manager","ir_model_access_group_erp_manager","model_ir_model_access","group_erp_manager",1,1,1,1
"access_ir_model_grid_group_erp_manager","ir_model_access_grid_group_erp_manager","model_ir_model_grid","group_erp_manager",1,1,1,1
"access_ir_model_config_group_erp_manager","ir_model_config group_erp_manager","model_ir_model_config","group_erp_manager",1,1,1,1
"access_ir_model_data_group_erp_manager","ir_model_data group_erp_manager","model_ir_model_data","group_erp_manager",1,1,1,1
"access_ir_model_fields_group_erp_manager","ir_model_fields group_erp_manager","model_ir_model_fields","group_erp_manager",1,1,1,1
"access_ir_model_all","ir_model_all","model_ir_model",,1,0,0,0
"access_ir_model_access_all","ir_model_access_all","model_ir_model_access",,1,0,0,0
"access_ir_model_grid_all","ir_model_access_grid_all","model_ir_model_grid",,0,0,0,0
"access_ir_model_config_all","ir_model_config_all","model_ir_model_config",,1,0,0,0
"access_ir_model_data_all","ir_model_data all","model_ir_model_data",,1,0,0,0
"access_ir_model_fields_all","ir_model_fields all","model_ir_model_fields",,1,0,0,0
"access_ir_module_category_group_user","ir_module_category group_user","model_ir_module_category","group_system",1,0,0,0
@ -46,6 +44,8 @@
"access_wizard_module_lang_export_group_system","wizard_module_lang_export group_system","model_wizard_module_lang_export","group_system",1,1,1,1
"access_res_company_group_erp_manager","res_company group_erp_manager","model_res_company","group_erp_manager",1,1,1,1
"access_res_company_group_user","res_company group_user","model_res_company",,1,0,0,0
"access_res_config_all","res_config all","model_res_config",,1,0,0,0
"access_res_config_users_all","res_config_users all","model_res_config_users",,1,0,0,0
"access_res_country_group_all","res_country group_user_all","model_res_country",,1,0,0,0
"access_res_country_state_group_all","res_country_state group_user_all","model_res_country_state",,1,0,0,0
"access_res_country_group_user","res_country group_user","model_res_country","group_partner_manager",1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
8 access_ir_model_group_erp_manager ir_model group_erp_manager model_ir_model group_erp_manager 1 1 1 1
9 access_ir_model_access_group_erp_manager ir_model_access_group_erp_manager model_ir_model_access group_erp_manager 1 1 1 1
10 access_ir_model_grid_group_erp_manager ir_model_access_grid_group_erp_manager model_ir_model_grid group_erp_manager 1 1 1 1
access_ir_model_config_group_erp_manager ir_model_config group_erp_manager model_ir_model_config group_erp_manager 1 1 1 1
11 access_ir_model_data_group_erp_manager ir_model_data group_erp_manager model_ir_model_data group_erp_manager 1 1 1 1
12 access_ir_model_fields_group_erp_manager ir_model_fields group_erp_manager model_ir_model_fields group_erp_manager 1 1 1 1
13 access_ir_model_all ir_model_all model_ir_model 1 0 0 0
14 access_ir_model_access_all ir_model_access_all model_ir_model_access 1 0 0 0
15 access_ir_model_grid_all ir_model_access_grid_all model_ir_model_grid 0 0 0 0
access_ir_model_config_all ir_model_config_all model_ir_model_config 1 0 0 0
16 access_ir_model_data_all ir_model_data all model_ir_model_data 1 0 0 0
17 access_ir_model_fields_all ir_model_fields all model_ir_model_fields 1 0 0 0
18 access_ir_module_category_group_user ir_module_category group_user model_ir_module_category group_system 1 0 0 0
44 access_wizard_module_lang_export_group_system wizard_module_lang_export group_system model_wizard_module_lang_export group_system 1 1 1 1
45 access_res_company_group_erp_manager res_company group_erp_manager model_res_company group_erp_manager 1 1 1 1
46 access_res_company_group_user res_company group_user model_res_company 1 0 0 0
47 access_res_config_all res_config all model_res_config 1 0 0 0
48 access_res_config_users_all res_config_users all model_res_config_users 1 0 0 0
49 access_res_country_group_all res_country group_user_all model_res_country 1 0 0 0
50 access_res_country_state_group_all res_country_state group_user_all model_res_country_state 1 0 0 0
51 access_res_country_group_user res_country group_user model_res_country group_partner_manager 1 1 1 1

View File

@ -381,186 +381,4 @@ class OpenERPDispatcher:
pdb.post_mortem(tb[2])
raise OpenERPDispatcherException(e, tb_s)
class GenericXMLRPCRequestHandler(OpenERPDispatcher):
def _dispatch(self, method, params):
try:
service_name = self.path.split("/")[-1]
return self.dispatch(service_name, method, params)
except OpenERPDispatcherException, e:
raise xmlrpclib.Fault(tools.exception_to_unicode(e.exception), e.traceback)
class SSLSocket(object):
def __init__(self, socket):
if not hasattr(socket, 'sock_shutdown'):
from OpenSSL import SSL
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.use_privatekey_file(tools.config['secure_pkey_file'])
ctx.use_certificate_file(tools.config['secure_cert_file'])
self.socket = SSL.Connection(ctx, socket)
else:
self.socket = socket
def shutdown(self, how):
return self.socket.sock_shutdown(how)
def __getattr__(self, name):
return getattr(self.socket, name)
class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
rpc_paths = map(lambda s: '/xmlrpc/%s' % s, GROUPS.get('web-services', {}).keys())
class SecureXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
def setup(self):
self.connection = SSLSocket(self.request)
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer):
def server_bind(self):
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self)
class SecureThreadedXMLRPCServer(SimpleThreadedXMLRPCServer):
def __init__(self, server_address, HandlerClass, logRequests=1):
SimpleThreadedXMLRPCServer.__init__(self, server_address, HandlerClass, logRequests)
self.socket = SSLSocket(socket.socket(self.address_family, self.socket_type))
self.server_bind()
self.server_activate()
class HttpDaemon(threading.Thread):
def __init__(self, interface, port, secure=False):
threading.Thread.__init__(self)
self.__port = port
self.__interface = interface
self.secure = bool(secure)
handler_class = (SimpleXMLRPCRequestHandler, SecureXMLRPCRequestHandler)[self.secure]
server_class = (SimpleThreadedXMLRPCServer, SecureThreadedXMLRPCServer)[self.secure]
if self.secure:
from OpenSSL.SSL import Error as SSLError
else:
class SSLError(Exception): pass
try:
self.server = server_class((interface, port), handler_class, 0)
except SSLError, e:
Logger().notifyChannel('xml-rpc-ssl', LOG_CRITICAL, "Can not load the certificate and/or the private key files")
sys.exit(1)
except Exception, e:
Logger().notifyChannel('xml-rpc', LOG_CRITICAL, "Error occur when starting the server daemon: %s" % (e,))
sys.exit(1)
def attach(self, path, gw):
pass
def stop(self):
self.running = False
if os.name != 'nt':
try:
self.server.socket.shutdown(
hasattr(socket, 'SHUT_RDWR') and socket.SHUT_RDWR or 2)
except socket.error, e:
if e.errno != 57: raise
# OSX, socket shutdowns both sides if any side closes it
# causing an error 57 'Socket is not connected' on shutdown
# of the other side (or something), see
# http://bugs.python.org/issue4397
Logger().notifyChannel(
'server', LOG_DEBUG,
'"%s" when shutting down server socket, '
'this is normal under OS X'%e)
self.server.socket.close()
def run(self):
self.server.register_introspection_functions()
self.running = True
while self.running:
self.server.handle_request()
return True
# If the server need to be run recursively
#
#signal.signal(signal.SIGALRM, self.my_handler)
#signal.alarm(6)
#while True:
# self.server.handle_request()
#signal.alarm(0) # Disable the alarm
import tiny_socket
class TinySocketClientThread(threading.Thread, OpenERPDispatcher):
def __init__(self, sock, threads):
threading.Thread.__init__(self)
self.sock = sock
self.threads = threads
def run(self):
import select
self.running = True
try:
ts = tiny_socket.mysocket(self.sock)
except:
self.sock.close()
self.threads.remove(self)
return False
while self.running:
try:
msg = ts.myreceive()
except:
self.sock.close()
self.threads.remove(self)
return False
try:
result = self.dispatch(msg[0], msg[1], msg[2:])
ts.mysend(result)
except OpenERPDispatcherException, e:
new_e = Exception(tools.exception_to_unicode(e.exception)) # avoid problems of pickeling
ts.mysend(new_e, exception=True, traceback=e.traceback)
self.sock.close()
self.threads.remove(self)
return True
def stop(self):
self.running = False
class TinySocketServerThread(threading.Thread):
def __init__(self, interface, port, secure=False):
threading.Thread.__init__(self)
self.__port = port
self.__interface = interface
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind((self.__interface, self.__port))
self.socket.listen(5)
self.threads = []
def run(self):
import select
try:
self.running = True
while self.running:
(clientsocket, address) = self.socket.accept()
ct = TinySocketClientThread(clientsocket, self.threads)
self.threads.append(ct)
ct.start()
self.socket.close()
except Exception, e:
self.socket.close()
return False
def stop(self):
self.running = False
for t in self.threads:
t.stop()
try:
if hasattr(socket, 'SHUT_RDWR'):
self.socket.shutdown(socket.SHUT_RDWR)
else:
self.socket.shutdown(2)
self.socket.close()
except:
return False
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -304,7 +304,7 @@ def get_pg_type(f):
elif isinstance(f.selection, list) and isinstance(f.selection[0][0], int):
f_size = -1
else:
f_size = getattr(f, 'size', 16)
f_size = getattr(f, 'size', None) or 16
if f_size == -1:
f_type = ('int4', 'INTEGER')

View File

@ -195,9 +195,16 @@ class osv_memory(osv_base, orm.orm_memory):
# put objects in the pool var
#
def createInstance(cls, pool, module, cr):
name = getattr(cls, '_name', cls._inherit)
parent_names = getattr(cls, '_inherit', None)
if parent_names:
if isinstance(parent_names, (str, unicode)):
name = cls._name or parent_names
parent_names = [parent_names]
else:
name = cls._name
if not name:
raise TypeError('_name is mandatory in case of multiple inheritance')
for parent_name in ((type(parent_names)==list) and parent_names or [parent_names]):
parent_class = pool.get(parent_name).__class__
assert pool.get(parent_name), "parent class %s does not exist in module %s !" % (parent_name, module)
@ -209,7 +216,6 @@ class osv_memory(osv_base, orm.orm_memory):
else:
new.extend(cls.__dict__.get(s, []))
nattr[s] = new
name = getattr(cls, '_name', cls._inherit)
cls = type(name, (cls, parent_class), nattr)
obj = object.__new__(cls)
@ -225,6 +231,14 @@ class osv(osv_base, orm.orm):
def createInstance(cls, pool, module, cr):
parent_names = getattr(cls, '_inherit', None)
if parent_names:
if isinstance(parent_names, (str, unicode)):
name = cls._name or parent_names
parent_names = [parent_names]
else:
name = cls._name
if not name:
raise TypeError('_name is mandatory in case of multiple inheritance')
for parent_name in ((type(parent_names)==list) and parent_names or [parent_names]):
parent_class = pool.get(parent_name).__class__
assert pool.get(parent_name), "parent class %s does not exist in module %s !" % (parent_name, module)
@ -247,7 +261,6 @@ class osv(osv_base, orm.orm):
else:
new.extend(cls.__dict__.get(s, []))
nattr[s] = new
name = getattr(cls, '_name', cls._inherit)
cls = type(name, (cls, parent_class), nattr)
obj = object.__new__(cls)
obj.__init__(pool, cr)