Merged with main trunk

bzr revid: hda@tinyerp.com-20100505131038-k4or5j9x5zkxl5ac
This commit is contained in:
HDA (OpenERP) 2010-05-05 18:40:38 +05:30
commit 15171f62d1
23 changed files with 351 additions and 326 deletions

View File

@ -640,10 +640,20 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs):
def load_test(cr, module_name, id_map, mode):
cr.commit()
try:
_load_data(cr, module_name, id_map, mode, 'test')
finally:
cr.rollback()
if not tools.config.options['test-disable']:
try:
_load_data(cr, module_name, id_map, mode, 'test')
except Exception, e:
if tools.config.options['test-continue']:
logger.notifyChannel('ERROR', netsvc.LOG_TEST, e)
pass
else:
raise
finally:
if tools.config.options['test-rollback']:
cr.rollback()
else:
cr.commit()
def _load_data(cr, module_name, id_map, mode, kind):
noupdate = (kind == 'demo')
@ -757,6 +767,15 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs):
return has_updates
def load_modules(db, force_demo=False, status=None, update_module=False):
def check_module_name(cr, mods, state):
for mod in mods:
id = modobj.search(cr, 1, ['&', ('state', '=', state), ('name', '=', mod)])
if id:
getattr(modobj, states[state])(cr, 1, id)
elif mod != 'all':
logger.notifyChannel('init', netsvc.LOG_WARNING, 'module %s: invalid module name!' % (mod))
if not status:
status = {}
cr = db.cursor()
@ -787,21 +806,16 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
return
if update_module:
modobj = pool.get('ir.module.module')
states = {'installed': 'button_upgrade', 'uninstalled': 'button_install'}
logger.notifyChannel('init', netsvc.LOG_INFO, 'updating modules list')
if ('base' in tools.config['init']) or ('base' in tools.config['update']):
modobj.update_list(cr, 1)
mods = [k for k in tools.config['init'] if tools.config['init'][k]]
if mods:
ids = modobj.search(cr, 1, ['&', ('state', '=', 'uninstalled'), ('name', 'in', mods)])
if ids:
modobj.button_install(cr, 1, ids)
check_module_name(cr, mods, 'uninstalled')
mods = [k for k in tools.config['update'] if tools.config['update'][k]]
if mods:
ids = modobj.search(cr, 1, ['&', ('state', '=', 'installed'), ('name', 'in', mods)])
if ids:
modobj.button_upgrade(cr, 1, ids)
check_module_name(cr, mods, 'installed')
cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base'))

View File

@ -7,14 +7,14 @@ 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-02-07 05:09+0000\n"
"PO-Revision-Date: 2010-05-02 05:54+0000\n"
"Last-Translator: Jordi Esteve - http://www.zikzakmedia.com "
"<jesteve@zikzakmedia.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-04-17 03:49+0000\n"
"X-Launchpad-Export-Date: 2010-05-03 04:02+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
@ -109,7 +109,7 @@ msgid ""
msgstr ""
"Escolliu entre la \"Interfície simplificada\" o \"Interfície estesa\".\n"
"Si esteu examinant o utilitzant OpenERP per la primera vegada,\n"
"us suggerim per utilitzar la interfície simplificada, que té menys\n"
"us suggerim que utilitzeu la interfície simplificada, que té menys\n"
"opcions i camps però és més fàcil d'entendre. Més tard podreu\n"
"canviar a la vista estesa.\n"
" "
@ -388,8 +388,8 @@ msgid ""
"If you check this, then the second time the user prints with same attachment "
"name, it returns the previous report."
msgstr ""
"Si marca aquesta opció, quan l'usuari imprimeixi el mateix nom d'adjunt per "
"segona vegada, tornarà l'informe anterior."
"Si marqueu aquesta opció, quan l'usuari imprimeixi el mateix nom d'adjunt "
"per segona vegada, obtindrá l'informe anterior."
#. module: base
#: help:res.lang,iso_code:0
@ -433,7 +433,7 @@ msgid ""
"The ISO country code in two chars.\n"
"You can use this field for quick search."
msgstr ""
"EL codi ISO del país en dos caràcters.\n"
"EL codi ISO del país de dos caràcters.\n"
"Podeu utilitzar aquest camp per la cerca ràpida."
#. module: base
@ -474,7 +474,7 @@ msgstr "Interfície estesa"
#: code:addons/base/ir/ir_model.py:0
#, python-format
msgid "Custom fields must have a name that starts with 'x_' !"
msgstr "Els camps personalitzats han de tenir un nom que comença con 'x_'!"
msgstr "Els camps personalitzats han de tenir un nom que comenci amb 'x_'!"
#. module: base
#: help:ir.actions.server,action_id:0
@ -913,7 +913,7 @@ msgstr "STOCK_MISSING_IMAGE"
#. module: base
#: view:res.users:0
msgid "Define New Users"
msgstr "Defineix nous usuaris"
msgstr "Definiu nous usuaris"
#. module: base
#: selection:ir.ui.menu,icon:0
@ -1489,7 +1489,7 @@ msgstr "Menú"
#. module: base
#: field:res.currency,rate:0
msgid "Current Rate"
msgstr "Tasa"
msgstr "Taxa"
#. module: base
#: selection:module.lang.install,init,lang:0
@ -3124,7 +3124,7 @@ msgid ""
"any."
msgstr ""
"L'usuari intern que s'encarrega de comunicar-se amb aquesta empresa, si "
"n'hi ha."
"n'hi hagués."
#. module: base
#: field:res.partner,parent_id:0
@ -5073,8 +5073,8 @@ msgstr "Islàndia"
#: view:res.users:0
msgid "Roles are used to defined available actions, provided by workflows."
msgstr ""
"Els rols s'utilitzen per definir les accions disponibles, de les que "
"proveeixen els fluxos."
"Els rols s'utilitzen per definir les accions disponibles dins d'un flux de "
"treball."
#. module: base
#: model:res.country,name:base.de
@ -5437,7 +5437,7 @@ msgstr "Dia de l'any: %(doy)s"
#. module: base
#: model:res.country,name:base.nt
msgid "Neutral Zone"
msgstr "Zona Neutral"
msgstr "Zona neutral"
#. module: base
#: view:ir.model:0
@ -5828,7 +5828,7 @@ msgstr "Companyia per defecte per objecte"
#. module: base
#: view:ir.actions.configuration.wizard:0
msgid "Next Configuration Step"
msgstr "Següent pas configuració"
msgstr "Següent pas de la configuració"
#. module: base
#: field:res.groups,comment:0
@ -6645,8 +6645,8 @@ msgid ""
"Access all the fields related to the current object using expression in "
"double brackets, i.e. [[ object.partner_id.name ]]"
msgstr ""
"Accedeix a tots els camps relacionats amb l'objecte actual mitjançant una "
"expressió en claudàtors dobles, per exemple [[ object.partner_id.name ]]"
"Podeu accedir a tots els camps relacionats amb l'objecte actual mitjançant "
"una expressió en claudàtors dobles, per exemple [[ object.partner_id.name ]]"
#. module: base
#: field:res.request.history,body:0
@ -8088,7 +8088,7 @@ msgstr ""
#. module: base
#: wizard_view:module.lang.install,init:0
msgid "Choose a language to install:"
msgstr "Selecciona un idioma per instal·lar:"
msgstr "Seleccioneu un idioma a instal·lar:"
#. module: base
#: model:res.country,name:base.lk

View File

@ -7,14 +7,14 @@ 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-02-07 05:11+0000\n"
"PO-Revision-Date: 2010-05-02 05:52+0000\n"
"Last-Translator: Jordi Esteve - http://www.zikzakmedia.com "
"<jesteve@zikzakmedia.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-04-17 03:52+0000\n"
"X-Launchpad-Export-Date: 2010-05-03 04:03+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
@ -389,7 +389,7 @@ msgid ""
"name, it returns the previous report."
msgstr ""
"Si marca esta opción, cuando el usuario imprima el mismo nombre de adjunto "
"por segunda vez, devolverá el informe anterior."
"por segunda vez, obtendrá el informe anterior."
#. module: base
#: help:res.lang,iso_code:0
@ -434,8 +434,8 @@ msgid ""
"The ISO country code in two chars.\n"
"You can use this field for quick search."
msgstr ""
"EL código ISO del país en dos caracteres.\n"
"Puede usar este campo para la búsqueda rápida."
"EL código ISO del país de dos caracteres.\n"
"Puede utilizar este campo para la búsqueda rápida."
#. module: base
#: selection:workflow.activity,join_mode:0
@ -3127,7 +3127,8 @@ msgid ""
"The internal user that is in charge of communicating with this partner if "
"any."
msgstr ""
"El usuario interno que se encarga de comunicarse con esta empresa si hay."
"El usuario interno que se encarga de comunicarse con esta empresa, si los "
"hubiera."
#. module: base
#: field:res.partner,parent_id:0
@ -5076,8 +5077,8 @@ msgstr "Islandia"
#: view:res.users:0
msgid "Roles are used to defined available actions, provided by workflows."
msgstr ""
"Los roles se utilizan para definir las acciones disponibles, que son "
"proporcionadas por los flujos."
"Los roles se utilizan para definir las acciones disponibles dentro de un "
"flujo de trabajo."
#. module: base
#: model:res.country,name:base.de
@ -5830,7 +5831,7 @@ msgstr "Compañía por defecto por objeto"
#. module: base
#: view:ir.actions.configuration.wizard:0
msgid "Next Configuration Step"
msgstr "Siguiente paso configuración"
msgstr "Siguiente paso de la configuración"
#. module: base
#: field:res.groups,comment:0

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-04-26 04:29+0000\n"
"PO-Revision-Date: 2010-05-03 14:18+0000\n"
"Last-Translator: goranc <goranc@gmail.com>\n"
"Language-Team: openerp-translators\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-04-27 03:37+0000\n"
"X-Launchpad-Export-Date: 2010-05-05 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"

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-03-31 05:14+0000\n"
"Last-Translator: OpenERP Administrators <Unknown>\n"
"PO-Revision-Date: 2010-04-29 04:41+0000\n"
"Last-Translator: eLBati - albatos.com <lorenzo.battistini@albatos.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-04-17 03:51+0000\n"
"X-Launchpad-Export-Date: 2010-04-30 03:50+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
@ -422,7 +422,7 @@ msgstr "Colombia"
#. module: base
#: view:ir.module.module:0
msgid "Schedule Upgrade"
msgstr "Aggiornamento Programmazione"
msgstr "Pianifica l'aggiornamento"
#. module: base
#: field:ir.actions.report.custom,report_id:0

View File

@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: openobject-server\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-04-26 04:24+0000\n"
"PO-Revision-Date: 2010-05-03 14:46+0000\n"
"Last-Translator: Harry (Open ERP) <hmo@tinyerp.com>\n"
"Language-Team: Japanese <ja@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-04-27 03:37+0000\n"
"X-Launchpad-Export-Date: 2010-05-05 03:47+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-04-26 04:22+0000\n"
"PO-Revision-Date: 2010-05-03 14:48+0000\n"
"Last-Translator: Anders Wallenquist <anders.wallenquist@vertel.se>\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-04-27 03:37+0000\n"
"X-Launchpad-Export-Date: 2010-05-05 03:47+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-04-26 04:19+0000\n"
"PO-Revision-Date: 2010-05-03 14:29+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-04-27 03:37+0000\n"
"X-Launchpad-Export-Date: 2010-05-05 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base

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-04-26 04:28+0000\n"
"PO-Revision-Date: 2010-05-03 14:47+0000\n"
"Last-Translator: OpenERP Administrators <Unknown>\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-04-27 03:37+0000\n"
"X-Launchpad-Export-Date: 2010-05-05 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base

View File

@ -1147,67 +1147,51 @@
<!-- Rules -->
<record id="view_rule_group_form" model="ir.ui.view">
<record id="view_rule_form" model="ir.ui.view">
<field name="name">Record rules</field>
<field name="model">ir.rule.group</field>
<field name="model">ir.rule</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Record rules">
<field name="model_id" select="1"/>
<field name="global" select="1"/>
<field colspan="4" name="name"/>
<group col="6" colspan="4" expand="1">
<field colspan="6" name="rules" nolabel="1"/>
<label align="0.0" colspan="6" string="The rule is satisfied if all test are True (AND)"/>
<label align="0.0" colspan="6" string="Multiple rules on same objects are joined using operator OR"/>
<separator colspan="4" string="Combination of rules"/>
<label align="0.0" angle="2" colspan="4" string="1. Global rules are combined together with a logical AND operator, and with the result of the following steps"/>
<label align="0.0" angle="2" colspan="4" string="2. Group-specific rules are combined together with a logical AND operator"/>
<label align="0.0" angle="2" colspan="4" string="3. If user belongs to several groups, the results from step 2 are combined with logical OR operator"/>
<label align="0.0" angle="2" colspan="4" string="Example: GLOBAL_RULE_1 AND GLOBAL_RULE_2 AND ( (GROUP_A_RULE_1 AND GROUP_A_RULE_2) OR (GROUP_B_RULE_1 AND GROUP_B_RULE_2) )"/>
<group col="2" colspan="2">
<separator colspan="2" string="General"/>
<field colspan="4" name="name"/>
<field name="model_id" select="1"/>
</group>
<group col="4" colspan="2">
<separator colspan="4" string="Access Rights"/>
<field name="perm_read"/>
<field name="perm_write"/>
<field name="perm_create"/>
<field name="perm_unlink"/>
</group>
<separator colspan="4" string="Domain Setup"/>
<group colspan="4">
<field name="domain_force" colspan="4"/>
</group>
<separator colspan="4" string="Groups (no group = global)"/>
<group colspan="4" expand="1">
<field name="global" select="1"/>
<field name="groups" select="1" nolabel="1" colspan="4"/>
</group>
</form>
</field>
</record>
<record id="view_rule_group_tree" model="ir.ui.view">
<record id="view_rule_tree" model="ir.ui.view">
<field name="name">Record rules</field>
<field name="model">ir.rule.group</field>
<field name="model">ir.rule</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Record rules">
<field name="model_id"/>
<field name="name"/>
<field name="global"/>
</tree>
</field>
</record>
<record id="view_rule_form" model="ir.ui.view">
<field name="name">Rule Definition</field>
<field name="model">ir.rule</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Test">
<separator colspan="4" string="Simple domain setup"/>
<group col="6" colspan="4">
<field name="field_id"/>
<field name="operator"/>
<field name="operand"/>
</group>
<separator colspan="4" string="Manual domain setup"/>
<field name="domain_force"/>
<label colspan="4" string="If you don't force the domain, it will use the simple domain setup"/>
<newline/>
<field name="perm_read"/>
<field name="perm_write"/>
<field name="perm_create"/>
<field name="perm_unlink"/>
</form>
</field>
</record>
<record id="view_rule_tree" model="ir.ui.view">
<field name="name">Rules</field>
<field name="model">ir.rule</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Test">
<field name="domain"/>
<field name="perm_read"/>
<field name="perm_write"/>
<field name="perm_create"/>
@ -1215,22 +1199,20 @@
</tree>
</field>
</record>
<record id="action_rule" model="ir.actions.act_window">
<field name="name">Record Rules</field>
<field name="res_model">ir.rule.group</field>
<field name="res_model">ir.rule</field>
<field name="view_type">form</field>
<field name="view_id" ref="view_rule_group_tree"/>
<field name="view_id" ref="view_rule_tree"/>
</record>
<menuitem action="action_rule" id="menu_action_rule" parent="base.menu_security"/>
<record id="property_rule_group" model="ir.rule.group">
<record id="property_rule" model="ir.rule">
<field name="name">Property multi-company</field>
<field model="ir.model" name="model_id" ref="model_ir_property"/>
<field eval="True" name="global"/>
</record>
<record id="property_rule" model="ir.rule">
<field name="domain_force">['|',('company_id','child_of',user.company_id.id),('company_id','=',False)]</field>
<field name="rule_group" ref="property_rule_group"/>
</record>
<!--server action view-->

View File

@ -191,7 +191,7 @@ class act_window(osv.osv):
return s.encode('utf8')
return s
for act in self.browse(cr, uid, ids):
fields_from_fields_get = self.pool.get(act.res_model).fields_get(cr, uid)
fields_from_fields_get = self.pool.get(act.res_model).fields_get(cr, uid, context=context)
search_view_id = False
if act.search_view_id:
search_view_id = act.search_view_id.id

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/>.
#
##############################################################################
import logging
@ -80,7 +80,7 @@ class ir_model(osv.osv):
if context:
context.pop('__last_update', None)
return super(ir_model,self).write(cr, user, ids, vals, context)
def create(self, cr, user, vals, context=None):
if context and context.get('manual',False):
vals['state']='manual'
@ -226,7 +226,7 @@ class ir_model_fields(osv.osv):
'domain': fields.char('Domain', size=256),
'groups': fields.many2many('res.groups', 'ir_model_fields_group_rel', 'field_id', 'group_id', 'Groups'),
'view_load': fields.boolean('View Auto-Load'),
'selectable': fields.boolean('Selectable'),
'selectable': fields.boolean('Selectable'),
}
_rec_name='field_description'
_defaults = {
@ -278,7 +278,7 @@ class ir_model_fields(osv.osv):
self.pool.get(vals['model'])._auto_init(cr, ctx)
return res
ir_model_fields()
class ir_model_access(osv.osv):
@ -378,6 +378,7 @@ class ir_model_access(osv.osv):
'create': _('You can not create this kind of document! (%s)'),
'unlink': _('You can not delete this document! (%s)'),
}
raise except_orm(_('AccessError'), msgs[mode] % model_name )
return r

View File

@ -23,154 +23,121 @@ from osv import fields,osv
import time
import tools
class ir_rule_group(osv.osv):
_name = 'ir.rule.group'
_columns = {
'name': fields.char('Name', size=128, select=1),
'model_id': fields.many2one('ir.model', 'Object',select=1, required=True),
'global': fields.boolean('Global', select=1, help="Make the rule global, otherwise it needs to be put on a group"),
'rules': fields.one2many('ir.rule', 'rule_group', 'Tests', help="The rule is satisfied if at least one test is True"),
'groups': fields.many2many('res.groups', 'group_rule_group_rel', 'rule_group_id', 'group_id', 'Groups'),
'users': fields.many2many('res.users', 'user_rule_group_rel', 'rule_group_id', 'user_id', 'Users'),
}
_order = 'model_id, global DESC'
_defaults={
'global': lambda *a: True,
}
ir_rule_group()
class ir_rule(osv.osv):
_name = 'ir.rule'
_rec_name = 'field_id'
def _operand(self,cr,uid,context):
def get(object, level=3, recur=None, root_tech='', root=''):
res = []
if not recur:
recur = []
fields = self.pool.get(object).fields_get(cr,uid)
key = fields.keys()
key.sort()
for k in key:
if fields[k]['type'] in ('many2one'):
res.append((root_tech+'.'+k+'.id',
root+'/'+fields[k]['string']))
elif fields[k]['type'] in ('many2many', 'one2many'):
res.append(('\',\'.join(map(lambda x: str(x.id), '+root_tech+'.'+k+'))',
root+'/'+fields[k]['string']))
else:
res.append((root_tech+'.'+k,
root+'/'+fields[k]['string']))
if (fields[k]['type'] in recur) and (level>0):
res.extend(get(fields[k]['relation'], level-1,
recur, root_tech+'.'+k, root+'/'+fields[k]['string']))
return res
res = [("False", "False"), ("True", "True"), ("user.id", "User")]
res += get('res.users', level=1,
recur=['many2one'], root_tech='user', root='User')
return res
def _domain_force_get(self, cr, uid, ids, field_name, arg, context={}):
res = {}
for rule in self.browse(cr, uid, ids, context):
eval_user_data = {'user': self.pool.get('res.users').browse(cr, 1, uid),
'time':time}
if rule.domain_force:
res[rule.id] = eval(rule.domain_force, eval_user_data)
else:
if rule.operand and rule.operand.startswith('user.') and rule.operand.count('.') > 1:
#Need to check user.field.field1.field2(if field is False,it will break the chain)
op = rule.operand[5:]
rule.operand = rule.operand[:5+len(op[:op.find('.')])] +' and '+ rule.operand + ' or False'
if rule.operator in ('in', 'child_of'):
dom = eval("[('%s', '%s', [%s])]" % (rule.field_id.name, rule.operator,
eval(rule.operand,eval_user_data)), eval_user_data)
else:
dom = eval("[('%s', '%s', %s)]" % (rule.field_id.name, rule.operator,
rule.operand), eval_user_data)
res[rule.id] = dom
res[rule.id] = eval(rule.domain_force, eval_user_data)
return res
def _get_value(self, cr, uid, ids, field_name, arg, context={}):
res = {}
for rule in self.browse(cr, uid, ids, context):
if not rule.groups:
res[rule.id] = True
else:
res[rule.id] = False
return res
def _check_model_obj(self, cr, uid, ids, context={}):
model_obj = self.pool.get('ir.model')
for rule in self.browse(cr, uid, ids, context):
model = model_obj.browse(cr, uid, rule.model_id.id, context).model
obj = self.pool.get(model)
if isinstance(obj, osv.osv_memory):
return False
return True
_columns = {
'field_id': fields.many2one('ir.model.fields', 'Field',domain= "[('model_id','=', parent.model_id)]", select=1),
'operator':fields.selection((('=', '='), ('<>', '<>'), ('<=', '<='), ('>=', '>='), ('in', 'in'), ('child_of', 'child_of')), 'Operator'),
'operand':fields.selection(_operand,'Operand', size=64),
'rule_group': fields.many2one('ir.rule.group', 'Group', select=2, required=True, ondelete="cascade"),
'domain_force': fields.char('Force Domain', size=250),
'name': fields.char('Name', size=128, select=1),
'model_id': fields.many2one('ir.model', 'Object',select=1, required=True),
'global': fields.function(_get_value, method=True, 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'),
'domain_force': fields.char('Domain', size=250),
'domain': fields.function(_domain_force_get, method=True, string='Domain', type='char', size=250),
'perm_read': fields.boolean('Read Access'),
'perm_write': fields.boolean('Write Access'),
'perm_create': fields.boolean('Create Access'),
'perm_unlink': fields.boolean('Delete Access')
'perm_read': fields.boolean('Apply For Read'),
'perm_write': fields.boolean('Apply For Write'),
'perm_create': fields.boolean('Apply For Create'),
'perm_unlink': fields.boolean('Apply For Delete')
}
_order = 'model_id DESC'
_defaults = {
'perm_read': lambda *a: True,
'perm_write': lambda *a: True,
'perm_create': lambda *a: True,
'perm_unlink': lambda *a: True,
'perm_read': True,
'perm_write': True,
'perm_create': True,
'perm_unlink': True,
'global': True,
}
_sql_constraints = [
('no_access_rights', 'CHECK (perm_read!=False or perm_write!=False or perm_create!=False or perm_unlink!=False)', 'Rule must have atleast one checked access right'),
('no_access_rights', 'CHECK (perm_read!=False or perm_write!=False or perm_create!=False or perm_unlink!=False)', 'Rule must have at least one checked access right'),
]
_constraints = [
(_check_model_obj, 'Rules are not supported for osv_memory objects !', ['model_id'])
]
def onchange_all(self, cr, uid, ids, field_id, operator, operand):
if not (field_id or operator or operand):
return {}
def domain_create(self, cr, uid, rule_ids):
dom = ['&'] * (len(rule_ids)-1)
for rule in self.browse(cr, uid, rule_ids):
dom += rule.domain
return dom
@tools.cache()
def _compute_domain(self, cr, uid, model_name, mode="read"):
group_rule = {}
global_rules = []
def domain_get(self, cr, uid, model_name, mode='read', context={}):
if uid == 1:
return [], [], ['"'+self.pool.get(model_name)._table+'"']
return None
cr.execute("""SELECT r.id
FROM ir_rule r
JOIN (ir_rule_group g
JOIN ir_model m ON (g.model_id = m.id))
ON (g.id = r.rule_group)
JOIN ir_model m ON (r.model_id = m.id)
WHERE m.model = %s
AND r.perm_""" + mode + """
AND (g.id IN (SELECT rule_group_id FROM group_rule_group_rel g_rel
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)
WHERE u_rel.uid = %s) OR g.global)""", (model_name, uid))
WHERE u_rel.uid = %s) OR r.global)""", (model_name, uid))
ids = map(lambda x: x[0], cr.fetchall())
dom = []
for rule in self.browse(cr, uid, ids):
dom += rule.domain
d1,d2,tables = self.pool.get(model_name)._where_calc(cr, uid, dom, active_test=False)
return d1, d2, tables
domain_get = tools.cache()(domain_get)
for group in rule.groups:
group_rule.setdefault(group.id, []).append(rule.id)
if not rule.groups:
global_rules.append(rule.id)
dom = self.domain_create(cr, uid, global_rules)
dom += ['|'] * (len(group_rule)-1)
for value in group_rule.values():
dom += self.domain_create(cr, uid, value)
return dom
def domain_get(self, cr, uid, model_name, mode='read', context={}):
dom = self._compute_domain(cr, uid, model_name, mode=mode)
if dom:
return self.pool.get(model_name)._where_calc(cr, uid, dom, active_test=False)
return [], [], ['"'+self.pool.get(model_name)._table+'"']
def unlink(self, cr, uid, ids, context=None):
res = super(ir_rule, self).unlink(cr, uid, ids, context=context)
# Restart the cache on the domain_get method of ir.rule
self.domain_get.clear_cache(cr.dbname)
# Restart the cache on the _compute_domain method of ir.rule
self._compute_domain.clear_cache(cr.dbname)
return res
def create(self, cr, user, vals, context=None):
res = super(ir_rule, self).create(cr, user, vals, context=context)
# Restart the cache on the domain_get method of ir.rule
self.domain_get.clear_cache(cr.dbname)
# Restart the cache on the _compute_domain method of ir.rule
self._compute_domain.clear_cache(cr.dbname)
return res
def write(self, cr, uid, ids, vals, context=None):
if not context:
context={}
res = super(ir_rule, self).write(cr, uid, ids, vals, context=context)
# Restart the cache on the domain_get method
self.domain_get.clear_cache(cr.dbname)
# Restart the cache on the _compute_domain method
self._compute_domain.clear_cache(cr.dbname)
return res
ir_rule()

View File

@ -86,7 +86,7 @@ class CountryState(osv.osv):
args = []
if not context:
context = {}
ids = self.search(cr, user, [('code', '=', name)] + args, limit=limit,
ids = self.search(cr, user, [('code', 'ilike', name)] + args, limit=limit,
context=context)
if not ids:
ids = self.search(cr, user, [('name', operator, name)] + args,

View File

@ -34,7 +34,7 @@ class groups(osv.osv):
_columns = {
'name': fields.char('Group Name', size=64, required=True),
'model_access': fields.one2many('ir.model.access', 'group_id', 'Access Controls'),
'rule_groups': fields.many2many('ir.rule.group', 'group_rule_group_rel',
'rule_groups': fields.many2many('ir.rule', 'rule_group_rel',
'group_id', 'rule_group_id', 'Rules', domain="[('global', '<>', True)]"),
'menu_access': fields.many2many('ir.ui.menu', 'ir_ui_menu_group_rel', 'gid', 'menu_id', 'Access Menu'),
'comment' : fields.text('Comment',size=250),
@ -47,7 +47,7 @@ class groups(osv.osv):
group_name = self.read(cr, uid, [id], ['name'])[0]['name']
default.update({'name': group_name +' (copy)'})
return super(groups, self).copy(cr, uid, id, default, context)
def write(self, cr, uid, ids, vals, context=None):
if 'name' in vals:
if vals['name'].startswith('-'):
@ -185,7 +185,6 @@ class users(osv.osv):
'menu_id': fields.many2one('ir.actions.actions', 'Menu Action'),
'groups_id': fields.many2many('res.groups', 'res_groups_users_rel', 'uid', 'gid', 'Groups'),
'roles_id': fields.many2many('res.roles', 'res_roles_users_rel', 'uid', 'rid', 'Roles'),
'rules_id': fields.many2many('ir.rule.group', 'user_rule_group_rel', 'user_id', 'rule_group_id', 'Rules'),
'company_id': fields.many2one('res.company', 'Company', required=True,
help="The company this user is currently working for."),
'company_ids':fields.many2many('res.company','res_company_users_rel','user_id','cid','Companies'),

View File

@ -72,37 +72,24 @@
</record>
<record model="ir.rule.group" id="res_partner_address_rule_group">
<record model="ir.rule" id="res_partner_address_rule">
<field name="name">res.partner.address company</field>
<field name="model_id" ref="model_res_partner_address"/>
<field name="global" eval="True"/>
</record>
<record model="ir.rule" id="res_partner_address_comp_rule">
<field name="field_id" search="[('model','=','res.partner.address'),('name','=','company_id')]" model="ir.model.fields"/>
<field name="rule_group" ref="res_partner_address_rule_group"/>
<field name="domain_force">[('company_id','child_of',[user.company_id.id])]</field>
</record>
<record model="ir.rule.group" id="res_partner_rule_group">
<record model="ir.rule" id="res_partner_rule">
<field name="name">res.partner company</field>
<field name="model_id" ref="model_res_partner"/>
<field name="global" eval="True"/>
</record>
<record model="ir.rule" id="res_partner_comp_rule">
<field name="field_id" search="[('model','=','res.partner'),('name','=','company_id')]" model="ir.model.fields"/>
<field name="rule_group" ref="res_partner_rule_group"/>
<field name="domain_force">[('company_id','child_of',[user.company_id.id])]</field>
</record>
<record model="ir.rule.group" id="multi_company_default_rule_group">
<record model="ir.rule" id="multi_company_default_rule">
<field name="name">Multi_company_default company</field>
<field name="model_id" ref="model_multi_company_default"/>
<field name="global" eval="True"/>
</record>
<record model="ir.rule" id="multi_company_default_comp_rule">
<field name="field_id" search="[('model','=','multi_company.default'),('name','=','company_id')]" model="ir.model.fields"/>
<field name="rule_group" ref="multi_company_default_rule_group"/>
<field name="domain_force">[('company_id','child_of',[user.company_id.id])]</field>
</record>

View File

@ -23,9 +23,7 @@
"access_ir_report_custom_group_system","ir_report_custom group_system","model_ir_report_custom",,1,0,0,0
"access_ir_report_custom_fields_group_system","ir_report_custom_fields group_system","model_ir_report_custom_fields",,1,0,0,0
"access_ir_rule_group_user","ir_rule group_user","model_ir_rule",,1,0,0,0
"access_ir_rule_group_group_user","ir_rule_group group_user","model_ir_rule_group",,1,0,0,0
"access_ir_rule_group_erp_manager","ir_rule group_erp_manager","model_ir_rule","group_erp_manager",1,1,1,1
"access_ir_rule_group_group_erp_manager","ir_rule_group group_erp_manager","model_ir_rule_group","group_erp_manager",1,1,1,1
"access_ir_sequence_group_user","ir_sequence group_user","model_ir_sequence",,1,1,1,1
"access_ir_sequence_type_group_user","ir_sequence_type group_user","model_ir_sequence_type",,1,0,0,0
"access_ir_translation_group_system","ir_translation group_system","model_ir_translation",,1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
23 access_ir_report_custom_group_system ir_report_custom group_system model_ir_report_custom 1 0 0 0
24 access_ir_report_custom_fields_group_system ir_report_custom_fields group_system model_ir_report_custom_fields 1 0 0 0
25 access_ir_rule_group_user ir_rule group_user model_ir_rule 1 0 0 0
access_ir_rule_group_group_user ir_rule_group group_user model_ir_rule_group 1 0 0 0
26 access_ir_rule_group_erp_manager ir_rule group_erp_manager model_ir_rule group_erp_manager 1 1 1 1
access_ir_rule_group_group_erp_manager ir_rule_group group_erp_manager model_ir_rule_group group_erp_manager 1 1 1 1
27 access_ir_sequence_group_user ir_sequence group_user model_ir_sequence 1 1 1 1
28 access_ir_sequence_type_group_user ir_sequence_type group_user model_ir_sequence_type 1 0 0 0
29 access_ir_translation_group_system ir_translation group_system model_ir_translation 1 1 1 1

View File

@ -26,6 +26,17 @@ import os
import sys
import glob
def load_information_from_description_file(module):
"""
:param module: The name of the module (sale, purchase, ...)
"""
for filename in ['__openerp__.py', '__terp__.py']:
description_file = os.path.join(module, filename)
if os.path.isfile(description_file):
return eval(file(description_file).read())
return {}
if len(sys.argv) == 2 and (sys.argv[1] in ['-h', '--help']):
print >>sys.stderr, 'Usage: module_graph.py [module1 module2 module3]\n\tWhen no module is specified, all modules in current directory are used'
sys.exit(1)
@ -41,7 +52,7 @@ print 'digraph G {'
while len(modules):
f = modules.pop(0)
done.append(f)
info = addons.load_information_from_description_file(f)
info = load_information_from_description_file(f)
if info.get('installable', True):
for name in info['depends']:
if name not in done+modules:

View File

@ -656,6 +656,11 @@ class function(_column):
self._symbol_f = float._symbol_f
self._symbol_set = float._symbol_set
if type == 'boolean':
self._symbol_c = boolean._symbol_c
self._symbol_f = boolean._symbol_f
self._symbol_set = boolean._symbol_set
def digits_change(self, cr):
if self.digits_compute:
t = self.digits_compute(cr)

View File

@ -1139,6 +1139,25 @@ class orm_template(object):
return s.encode('utf8')
return s
# return True if node can be displayed to current user
def check_group(node):
if node.get('groups'):
groups = node.get('groups').split(',')
can_see = False
access_pool = self.pool.get('ir.model.access')
for group in groups:
can_see = can_see or access_pool.check_groups(cr, user, group)
if can_see:
break
if not can_see:
node.set('invisible', '1')
if 'attrs' in node.attrib:
del(node.attrib['attrs']) #avoid making field visible later
del(node.attrib['groups'])
return can_see
else:
return True
if node.tag in ('field', 'node', 'arrow'):
if node.get('object'):
attrs = {}
@ -1185,15 +1204,18 @@ class orm_template(object):
}
attrs = {'views': views}
if node.get('widget') and node.get('widget') == 'selection':
if not check_group(node):
attrs['selection'] = []
# We can not use the 'string' domain has it is defined according to the record !
dom = []
if column._domain and not isinstance(column._domain, (str, unicode)):
dom = column._domain
dom += eval(node.get('domain','[]'), {'uid':user, 'time':time})
context.update(eval(node.get('context','{}')))
attrs['selection'] = self.pool.get(relation).name_search(cr, user, '', dom, context=context,limit=None)
if (node.get('required') and not int(node.get('required'))) or not column.required:
attrs['selection'].append((False,''))
else:
dom = []
if column._domain and not isinstance(column._domain, (str, unicode)):
dom = column._domain
dom += eval(node.get('domain','[]'), {'uid':user, 'time':time})
context.update(eval(node.get('context','{}')))
attrs['selection'] = self.pool.get(relation)._name_search(cr, user, '', dom, context=context, limit=None, name_get_uid=1)
if (node.get('required') and not int(node.get('required'))) or not column.required:
attrs['selection'].append((False,''))
fields[node.get('name')] = attrs
elif node.tag in ('form', 'tree'):
@ -1207,15 +1229,7 @@ class orm_template(object):
fields[node.get(additional_field)] = {}
if 'groups' in node.attrib:
if node.get('groups'):
groups = node.get('groups').split(',')
readonly = False
access_pool = self.pool.get('ir.model.access')
for group in groups:
readonly = readonly or access_pool.check_groups(cr, user, group)
if not readonly:
node.set('invisible', '1')
del(node.attrib['groups'])
check_group(node)
# translate view
if ('lang' in context) and not result:
@ -1725,6 +1739,7 @@ class orm_memory(orm_template):
def read(self, cr, user, ids, fields_to_read=None, context=None, load='_classic_read'):
if not context:
context = {}
self.pool.get('ir.model.access').check(cr, user, self._name, 'read', context=context)
if not fields_to_read:
fields_to_read = self._columns.keys()
result = []
@ -1754,6 +1769,7 @@ class orm_memory(orm_template):
def write(self, cr, user, ids, vals, context=None):
if not ids:
return True
self.pool.get('ir.model.access').check(cr, user, self._name, 'write', context=context)
vals2 = {}
upd_todo = []
for field in vals:
@ -1772,6 +1788,7 @@ class orm_memory(orm_template):
return id_new
def create(self, cr, user, vals, context=None):
self.pool.get('ir.model.access').check(cr, user, self._name, 'create', context=context)
self.vaccum(cr, user)
self.next_id += 1
id_new = self.next_id
@ -1923,6 +1940,7 @@ class orm_memory(orm_template):
return res or []
def unlink(self, cr, uid, ids, context=None):
self.pool.get('ir.model.access').check(cr, uid, self._name, 'unlink', context=context)
for id in ids:
if id in self.datas:
del self.datas[id]
@ -3225,7 +3243,7 @@ class orm(orm_template):
"""
if not context:
context = {}
self.pool.get('ir.model.access').check(cr, user, self._name, 'create')
self.pool.get('ir.model.access').check(cr, user, self._name, 'create', context=context)
default = []
@ -3282,7 +3300,7 @@ class orm(orm_template):
record_id = tocreate[table].pop('id', None)
if record_id is None:
if record_id is None or not record_id:
record_id = self.pool.get(table).create(cr, user, tocreate[table], context=context)
else:
self.pool.get(table).write(cr, user, [record_id], tocreate[table], context=context)
@ -3649,6 +3667,20 @@ class orm(orm_template):
return [(r['id'], tools.ustr(r[self._rec_name])) for r in self.read(cr, user, ids,
[self._rec_name], context, load='_classic_write')]
# private implementation of name_search, allows passing a dedicated user for the name_get part to
# solve some access rights issues
def _name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=100, name_get_uid=None):
if not args:
args = []
if not context:
context = {}
args = args[:]
if name:
args += [(self._rec_name, operator, name)]
ids = self.search(cr, user, args, limit=limit, context=context)
res = self.name_get(cr, name_get_uid or user, ids, context)
return res
def name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=100):
"""
@ -3664,16 +3696,7 @@ class orm(orm_template):
This method is equivalent of search() on name + name_get()
"""
if not args:
args = []
if not context:
context = {}
args = args[:]
if name:
args += [(self._rec_name, operator, name)]
ids = self.search(cr, user, args, limit=limit, context=context)
res = self.name_get(cr, user, ids, context)
return res
return self._name_search(cr, user, name, args, operator, context, limit)
def copy_data(self, cr, uid, id, default=None, context=None):
"""

View File

@ -82,6 +82,9 @@ class configmanager(object):
'login_message': False,
'list_db' : True,
'timezone' : False, # to override the default TZ
'test-disable' : False,
'test-rollback' : True,
'test-continue' : False
}
self.misc = {}
@ -134,7 +137,17 @@ class configmanager(object):
default="server.pkey",
help="specify the private key file for the SSL connection")
parser.add_option_group(group)
# Testing Group
group = optparse.OptionGroup(parser, "Testing Configuration")
group.add_option("--test-disable", action="store_true", dest="test_disable",
default=False, help="Disable loading test files.")
group.add_option("--test-no-rollback", action="store_false", dest="test_rollback",
default=True, help="Don't rollback after running test.")
group.add_option("--test-continue", action="store_true", dest="test_continue",
default=False, help="Display exception but then test should continue.")
parser.add_option_group(group)
# Logging Group
group = optparse.OptionGroup(parser, "Logging Configuration")
group.add_option("--logfile", dest="logfile", help="file where the server log will be stored")
@ -274,6 +287,9 @@ class configmanager(object):
self.options['init'] = opt.init and dict.fromkeys(opt.init.split(','), 1) or {}
self.options["demo"] = not opt.without_demo and self.options['init'] or {}
self.options["test-disable"] = opt.test_disable
self.options["test-rollback"] = opt.test_rollback
self.options["test-continue"] = opt.test_continue
self.options['update'] = opt.update and dict.fromkeys(opt.update.split(','), 1) or {}
self.options['translate_modules'] = opt.translate_modules and map(lambda m: m.strip(), opt.translate_modules.split(',')) or ['all']

View File

@ -254,38 +254,48 @@ class YamlInterpreter(object):
b = bool(value)
else:
b = default
return b
def process_record(self, node):
record, fields = node.items()[0]
self.validate_xml_id(record.id)
if self.isnoupdate(record) and self.mode != 'init':
id = self.pool.get('ir.model.data')._update_dummy(self.cr, self.uid, record.model, self.module, record.id)
# check if the resource already existed at the last update
if id:
self.id_map[record] = int(id)
return None
else:
if not self._coerce_bool(record.forcecreate):
return None
return b
def create_osv_memory_record(self, record, fields):
model = self.get_model(record.model)
record_dict = self._create_record(model, fields)
self.logger.debug("RECORD_DICT %s" % record_dict)
id = self.pool.get('ir.model.data')._update(self.cr, self.uid, record.model, \
self.module, record_dict, record.id, noupdate=self.isnoupdate(record), mode=self.mode)
self.id_map[record.id] = int(id)
if config.get('import_partial', False):
self.cr.commit()
id_new=model.create(self.cr, self.uid, record_dict, context=self.context)
self.id_map[record.id] = int(id_new)
return record_dict
def process_record(self, node):
import osv
record, fields = node.items()[0]
model = self.get_model(record.model)
if isinstance(model, osv.osv.osv_memory):
record_dict=self.create_osv_memory_record(record, fields)
else:
self.validate_xml_id(record.id)
if self.isnoupdate(record) and self.mode != 'init':
id = self.pool.get('ir.model.data')._update_dummy(self.cr, self.uid, record.model, self.module, record.id)
# check if the resource already existed at the last update
if id:
self.id_map[record] = int(id)
return None
else:
if not self._coerce_bool(record.forcecreate):
return None
record_dict = self._create_record(model, fields)
self.logger.debug("RECORD_DICT %s" % record_dict)
id = self.pool.get('ir.model.data')._update(self.cr, self.uid, record.model, \
self.module, record_dict, record.id, noupdate=self.isnoupdate(record), mode=self.mode)
self.id_map[record.id] = int(id)
if config.get('import_partial'):
self.cr.commit()
def _create_record(self, model, fields):
record_dict = {}
for field_name, expression in fields.items():
field_value = self._eval_field(model, field_name, expression)
record_dict[field_name] = field_value
return record_dict
return record_dict
def process_ref(self, node, column=None):
if node.search:
if node.model:
@ -307,10 +317,10 @@ class YamlInterpreter(object):
else:
value = None
return value
def process_eval(self, node):
return eval(node.expression, self.eval_context)
def _eval_field(self, model, field_name, expression):
# TODO this should be refactored as something like model.get_field() in bin/osv
if field_name in model._columns:
@ -390,6 +400,10 @@ class YamlInterpreter(object):
uid = workflow.uid
else:
uid = self.uid
self.cr.execute('select distinct signal from wkf_transition')
signals=[x['signal'] for x in self.cr.dictfetchall()]
if workflow.action not in signals:
raise YamlImportException('Incorrect action %s. No such action defined' % workflow.action)
wf_service = netsvc.LocalService("workflow")
wf_service.trg_validate(uid, workflow.model, id, workflow.action, self.cr)
@ -528,15 +542,19 @@ class YamlInterpreter(object):
'tree_but_open', 'Menuitem', [('ir.ui.menu', int(parent_id))], action, True, True, xml_id=node.id)
def process_act_window(self, node):
assert getattr(node, 'id'), "Attribute %s of act_window is empty !" % ('id',)
assert getattr(node, 'name'), "Attribute %s of act_window is empty !" % ('name',)
assert getattr(node, 'res_model'), "Attribute %s of act_window is empty !" % ('res_model',)
self.validate_xml_id(node.id)
view_id = False
if node.view:
view_id = self.get_id(node.view)
context = eval(node.context, self.eval_context)
if not node.context:
node.context={}
context = eval(str(node.context), self.eval_context)
values = {
'name': node.name,
'type': type or 'ir.actions.act_window',
'type': node.type or 'ir.actions.act_window',
'view_id': view_id,
'domain': node.domain,
'context': context,
@ -566,13 +584,17 @@ class YamlInterpreter(object):
# TODO add remove ir.model.data
def process_delete(self, node):
if len(node.search):
ids = self.pool.get(node.model).search(self.cr, self.uid, eval(node.search, self.eval_context))
assert getattr(node, 'model'), "Attribute %s of delete tag is empty !" % ('model',)
if self.pool.get(node.model):
if len(node.search):
ids = self.pool.get(node.model).search(self.cr, self.uid, eval(node.search, self.eval_context))
else:
ids = [self.get_id(node.id)]
if len(ids):
self.pool.get(node.model).unlink(self.cr, self.uid, ids)
self.pool.get('ir.model.data')._unlink(self.cr, self.uid, node.model, ids)
else:
ids = [self.get_id(node.id)]
if len(ids):
self.pool.get(node.model).unlink(self.cr, self.uid, ids)
self.pool.get('ir.model.data')._unlink(self.cr, self.uid, node.model, ids)
self.logger.log(logging.TEST, "Record not deleted.")
def process_url(self, node):
self.validate_xml_id(node.id)
@ -649,6 +671,8 @@ class YamlInterpreter(object):
"""
Processes a Yaml string. Custom tags are interpreted by 'process_' instance methods.
"""
yaml_tag.add_constructors()
is_preceded_by_comment = False
for node in yaml.load(yaml_string):
is_preceded_by_comment = self._log(node, is_preceded_by_comment)

View File

@ -48,9 +48,7 @@ class Workflow(YamlTag):
super(Workflow, self).__init__(**kwargs)
class ActWindow(YamlTag):
def __init__(self, model, action, **kwargs):
self.model = model
self.action = action
def __init__(self, **kwargs):
super(ActWindow, self).__init__(**kwargs)
class Function(YamlTag):
@ -67,10 +65,7 @@ class Report(YamlTag):
super(Report, self).__init__(**kwargs)
class Delete(YamlTag):
def __init__(self, model, id, search, **kwargs):
self.model = model
self.id = id
self.search = search
def __init__(self, **kwargs):
super(Delete, self).__init__(**kwargs)
class Context(YamlTag):
@ -156,17 +151,19 @@ def ir_set_constructor(loader, node):
# Registers constructors for custom tags.
# Constructors are actually defined globally: do not redefined them in another
# class/file/package. This means that module recorder need import this file.
yaml.add_constructor(u"!assert", assert_constructor)
yaml.add_constructor(u"!record", record_constructor)
yaml.add_constructor(u"!python", python_constructor)
yaml.add_constructor(u"!menuitem", menuitem_constructor)
yaml.add_constructor(u"!workflow", workflow_constructor)
yaml.add_constructor(u"!act_window", act_window_constructor)
yaml.add_constructor(u"!function", function_constructor)
yaml.add_constructor(u"!report", report_constructor)
yaml.add_constructor(u"!context", context_constructor)
yaml.add_constructor(u"!delete", delete_constructor)
yaml.add_constructor(u"!url", url_constructor)
yaml.add_constructor(u"!eval", eval_constructor)
yaml.add_multi_constructor(u"!ref", ref_constructor)
yaml.add_constructor(u"!ir_set", ir_set_constructor)
def add_constructors():
yaml.add_constructor(u"!assert", assert_constructor)
yaml.add_constructor(u"!record", record_constructor)
yaml.add_constructor(u"!python", python_constructor)
yaml.add_constructor(u"!menuitem", menuitem_constructor)
yaml.add_constructor(u"!workflow", workflow_constructor)
yaml.add_constructor(u"!act_window", act_window_constructor)
yaml.add_constructor(u"!function", function_constructor)
yaml.add_constructor(u"!report", report_constructor)
yaml.add_constructor(u"!context", context_constructor)
yaml.add_constructor(u"!delete", delete_constructor)
yaml.add_constructor(u"!url", url_constructor)
yaml.add_constructor(u"!eval", eval_constructor)
yaml.add_multi_constructor(u"!ref", ref_constructor)
yaml.add_constructor(u"!ir_set", ir_set_constructor)
add_constructors()