2009-10-20 10:52:23 +00:00
# -*- coding: utf-8 -*-
2006-12-07 13:41:40 +00:00
##############################################################################
2009-10-30 12:33:59 +00:00
#
2009-10-14 12:32:15 +00:00
# OpenERP, Open Source Management Solution
2011-07-06 15:40:01 +00:00
# Copyright (C) 2004-2011 OpenERP S.A. <http://www.openerp.com>
2008-06-16 11:00:21 +00:00
#
2008-11-03 18:27:16 +00:00
# This program is free software: you can redistribute it and/or modify
2009-10-14 12:32:15 +00:00
# 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.
2006-12-07 13:41:40 +00:00
#
2008-11-03 18:27:16 +00:00
# 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
2009-10-14 12:32:15 +00:00
# GNU Affero General Public License for more details.
2006-12-07 13:41:40 +00:00
#
2009-10-14 12:32:15 +00:00
# You should have received a copy of the GNU Affero General Public License
2009-10-30 12:33:59 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2006-12-07 13:41:40 +00:00
#
##############################################################################
2012-01-18 11:12:26 +00:00
2011-06-30 11:51:34 +00:00
import logging
2010-10-01 11:25:52 +00:00
import os
2011-06-30 11:51:34 +00:00
import re
2012-12-10 15:27:23 +00:00
from socket import gethostname
2011-06-30 11:51:34 +00:00
import time
2012-08-31 13:53:09 +00:00
from openerp import SUPERUSER_ID
2012-12-10 15:27:23 +00:00
from openerp import netsvc , tools
from openerp . osv import fields , osv
from openerp . report . report_sxw import report_sxw , report_rml
from openerp . tools . config import config
from openerp . tools . safe_eval import safe_eval as eval
from openerp . tools . translate import _
2006-12-07 13:41:40 +00:00
2012-01-24 11:47:30 +00:00
_logger = logging . getLogger ( __name__ )
2006-12-07 13:41:40 +00:00
class actions ( osv . osv ) :
2008-07-22 14:24:36 +00:00
_name = ' ir.actions.actions '
_table = ' ir_actions '
2010-12-10 22:42:58 +00:00
_order = ' name '
2008-07-22 14:24:36 +00:00
_columns = {
2012-08-22 13:41:09 +00:00
' name ' : fields . char ( ' Name ' , size = 64 , required = True ) ,
2012-11-27 07:30:12 +00:00
' type ' : fields . char ( ' Action Type ' , required = True , size = 32 ) ,
2008-07-22 14:24:36 +00:00
' usage ' : fields . char ( ' Action Usage ' , size = 32 ) ,
2012-09-24 14:57:50 +00:00
' help ' : fields . text ( ' Action description ' ,
help = ' Optional help text for the users with a description of the target view, such as its usage and purpose. ' ,
translate = True ) ,
2008-07-22 14:24:36 +00:00
}
_defaults = {
' usage ' : lambda * a : False ,
}
2006-12-07 13:41:40 +00:00
actions ( )
class report_xml ( osv . osv ) :
2007-09-07 14:02:45 +00:00
2008-07-22 14:24:36 +00:00
def _report_content ( self , cursor , user , ids , name , arg , context = None ) :
res = { }
for report in self . browse ( cursor , user , ids , context = context ) :
data = report [ name + ' _data ' ]
if not data and report [ name [ : - 8 ] ] :
2011-01-04 10:13:35 +00:00
fp = None
2008-07-22 14:24:36 +00:00
try :
fp = tools . file_open ( report [ name [ : - 8 ] ] , mode = ' rb ' )
data = fp . read ( )
except :
data = False
2011-01-04 10:13:35 +00:00
finally :
if fp :
fp . close ( )
2008-07-22 14:24:36 +00:00
res [ report . id ] = data
return res
2007-09-07 14:02:45 +00:00
2008-07-22 14:24:36 +00:00
def _report_content_inv ( self , cursor , user , id , name , value , arg , context = None ) :
self . write ( cursor , user , id , { name + ' _data ' : value } , context = context )
2007-09-07 14:02:45 +00:00
2008-07-22 14:24:36 +00:00
def _report_sxw ( self , cursor , user , ids , name , arg , context = None ) :
res = { }
for report in self . browse ( cursor , user , ids , context = context ) :
if report . report_rml :
res [ report . id ] = report . report_rml . replace ( ' .rml ' , ' .sxw ' )
else :
res [ report . id ] = False
return res
2007-09-07 14:02:45 +00:00
2010-10-01 11:25:52 +00:00
def register_all ( self , cr ) :
""" Report registration handler that may be overridden by subclasses to
add their own kinds of report services .
Loads all reports with no manual loaders ( auto == True ) and
registers the appropriate services to implement them .
"""
opj = os . path . join
cr . execute ( " SELECT * FROM ir_act_report_xml WHERE auto= %s ORDER BY id " , ( True , ) )
result = cr . dictfetchall ( )
svcs = netsvc . Service . _services
for r in result :
if svcs . has_key ( ' report. ' + r [ ' report_name ' ] ) :
continue
if r [ ' report_rml ' ] or r [ ' report_rml_content_data ' ] :
report_sxw ( ' report. ' + r [ ' report_name ' ] , r [ ' model ' ] ,
opj ( ' addons ' , r [ ' report_rml ' ] or ' / ' ) , header = r [ ' header ' ] )
if r [ ' report_xsl ' ] :
report_rml ( ' report. ' + r [ ' report_name ' ] , r [ ' model ' ] ,
opj ( ' addons ' , r [ ' report_xml ' ] ) ,
r [ ' report_xsl ' ] and opj ( ' addons ' , r [ ' report_xsl ' ] ) )
2008-07-22 14:24:36 +00:00
_name = ' ir.actions.report.xml '
2012-09-24 14:57:50 +00:00
_inherit = ' ir.actions.actions '
2008-07-22 14:24:36 +00:00
_table = ' ir_act_report_xml '
_sequence = ' ir_actions_id_seq '
2010-12-10 22:42:58 +00:00
_order = ' name '
2008-07-22 14:24:36 +00:00
_columns = {
' name ' : fields . char ( ' Name ' , size = 64 , required = True , translate = True ) ,
2008-08-21 13:49:55 +00:00
' model ' : fields . char ( ' Object ' , size = 64 , required = True ) ,
2010-07-21 07:13:32 +00:00
' type ' : fields . char ( ' Action Type ' , size = 32 , required = True ) ,
' report_name ' : fields . char ( ' Service Name ' , size = 64 , required = True ) ,
2008-07-22 14:24:36 +00:00
' usage ' : fields . char ( ' Action Usage ' , size = 32 ) ,
2010-10-01 11:25:52 +00:00
' report_type ' : fields . char ( ' Report Type ' , size = 32 , required = True , help = " Report Type, e.g. pdf, html, raw, sxw, odt, html2html, mako2html, ... " ) ,
2008-09-04 00:22:48 +00:00
' groups_id ' : fields . many2many ( ' res.groups ' , ' res_groups_report_rel ' , ' uid ' , ' gid ' , ' Groups ' ) ,
2012-04-23 11:32:57 +00:00
' multi ' : fields . boolean ( ' On Multiple Doc. ' , help = " If set to true, the action will not be displayed on the right toolbar of a form view. " ) ,
2012-04-23 11:26:47 +00:00
' attachment ' : fields . char ( ' Save as Attachment Prefix ' , size = 128 , help = ' This is the filename of the attachment used to store the printing result. Keep empty to not save the printed reports. You can use a python expression with the object and time variables. ' ) ,
2010-07-21 07:22:52 +00:00
' attachment_use ' : fields . boolean ( ' Reload from Attachment ' , help = ' If you check this, then the second time the user prints with same attachment name, it returns the previous report. ' ) ,
2012-04-23 11:32:57 +00:00
' auto ' : fields . boolean ( ' Custom Python Parser ' ) ,
2010-07-21 07:13:32 +00:00
2012-04-23 11:32:57 +00:00
' header ' : fields . boolean ( ' Add RML Header ' , help = " Add or not the corporate RML header " ) ,
2010-07-21 07:13:32 +00:00
2012-04-23 11:32:57 +00:00
' report_xsl ' : fields . char ( ' XSL Path ' , size = 256 ) ,
' report_xml ' : fields . char ( ' XML Path ' , size = 256 , help = ' ' ) ,
2010-07-21 07:13:32 +00:00
2010-10-08 14:23:01 +00:00
# Pending deprecation... to be replaced by report_file as this object will become the default report object (not so specific to RML anymore)
2012-04-23 11:32:57 +00:00
' report_rml ' : fields . char ( ' Main Report File Path ' , size = 256 , help = " The path to the main report file (depending on Report Type) or NULL if the content is in another data field " ) ,
2010-10-08 14:23:01 +00:00
# temporary related field as report_rml is pending deprecation - this field will replace report_rml after v6.0
2012-04-23 11:32:57 +00:00
' report_file ' : fields . related ( ' report_rml ' , type = " char " , size = 256 , required = False , readonly = False , string = ' Report File ' , help = " The path to the main report file (depending on Report Type) or NULL if the content is in another field " , store = True ) ,
2010-10-08 14:23:01 +00:00
2012-04-23 11:32:57 +00:00
' report_sxw ' : fields . function ( _report_sxw , type = ' char ' , string = ' SXW Path ' ) ,
' report_sxw_content_data ' : fields . binary ( ' SXW Content ' ) ,
' report_rml_content_data ' : fields . binary ( ' RML Content ' ) ,
2012-05-10 09:35:27 +00:00
' report_sxw_content ' : fields . function ( _report_content , fnct_inv = _report_content_inv , type = ' binary ' , string = ' SXW Content ' , ) ,
2012-04-23 11:32:57 +00:00
' report_rml_content ' : fields . function ( _report_content , fnct_inv = _report_content_inv , type = ' binary ' , string = ' RML Content ' ) ,
2010-07-21 07:13:32 +00:00
2008-07-22 14:24:36 +00:00
}
_defaults = {
2012-11-02 09:47:05 +00:00
' type ' : ' ir.actions.report.xml ' ,
' multi ' : False ,
' auto ' : True ,
' header ' : True ,
' report_sxw_content ' : False ,
' report_type ' : ' pdf ' ,
' attachment ' : False ,
2008-07-22 14:24:36 +00:00
}
2007-07-31 14:08:58 +00:00
2006-12-07 13:41:40 +00:00
report_xml ( )
class act_window ( osv . osv ) :
2008-07-22 14:24:36 +00:00
_name = ' ir.actions.act_window '
_table = ' ir_act_window '
2012-09-24 14:57:50 +00:00
_inherit = ' ir.actions.actions '
2008-07-22 14:24:36 +00:00
_sequence = ' ir_actions_id_seq '
2010-12-10 22:42:58 +00:00
_order = ' name '
2009-10-30 12:33:59 +00:00
2010-11-23 13:52:24 +00:00
def _check_model ( self , cr , uid , ids , context = None ) :
2009-03-16 17:49:01 +00:00
for action in self . browse ( cr , uid , ids , context ) :
if not self . pool . get ( action . res_model ) :
return False
if action . src_model and not self . pool . get ( action . src_model ) :
return False
return True
2010-11-18 16:47:21 +00:00
def _invalid_model_msg ( self , cr , uid , ids , context = None ) :
return _ ( ' Invalid model name in the action definition. ' )
2011-03-29 11:53:09 +00:00
2009-03-16 17:49:01 +00:00
_constraints = [
2010-11-18 16:47:21 +00:00
( _check_model , _invalid_model_msg , [ ' res_model ' , ' src_model ' ] )
2009-03-16 17:49:01 +00:00
]
2008-09-18 14:02:05 +00:00
2010-11-23 13:52:24 +00:00
def _views_get_fnc ( self , cr , uid , ids , name , arg , context = None ) :
2011-07-14 10:38:07 +00:00
""" Returns an ordered list of the specific view modes that should be
2011-04-01 12:48:52 +00:00
enabled when displaying the result of this action , along with the
ID of the specific view to use for each mode , if any were required .
This function hides the logic of determining the precedence between
the view_modes string , the view_ids o2m , and the view_id m2o that can
be set on the action .
: rtype : dict in the form { action_id : list of pairs ( tuples ) }
: return : { action_id : [ ( view_id , view_mode ) , . . . ] , . . . } , where view_mode
is one of the possible values for ir . ui . view . type and view_id
is the ID of a specific view to use for this mode , or False for
the default one .
"""
res = { }
2008-07-22 14:24:36 +00:00
for act in self . browse ( cr , uid , ids ) :
2011-04-01 12:48:52 +00:00
res [ act . id ] = [ ( view . view_id . id , view . view_mode ) for view in act . view_ids ]
view_ids_modes = [ view . view_mode for view in act . view_ids ]
2008-11-17 16:56:01 +00:00
modes = act . view_mode . split ( ' , ' )
2011-04-01 12:48:52 +00:00
missing_modes = [ mode for mode in modes if mode not in view_ids_modes ]
if missing_modes :
if act . view_id and act . view_id . type in missing_modes :
# reorder missing modes to put view_id first if present
missing_modes . remove ( act . view_id . type )
2008-07-22 14:24:36 +00:00
res [ act . id ] . append ( ( act . view_id . id , act . view_id . type ) )
2011-04-01 12:48:52 +00:00
res [ act . id ] . extend ( [ ( False , mode ) for mode in missing_modes ] )
2008-07-22 14:24:36 +00:00
return res
2007-05-15 13:27:39 +00:00
2010-11-23 13:52:24 +00:00
def _search_view ( self , cr , uid , ids , name , arg , context = None ) :
2009-09-17 07:27:12 +00:00
res = { }
2010-11-23 13:52:24 +00:00
for act in self . browse ( cr , uid , ids , context = context ) :
2012-06-09 12:40:45 +00:00
field_get = self . pool . get ( act . res_model ) . fields_view_get ( cr , uid ,
act . search_view_id and act . search_view_id . id or False ,
' search ' , context = context )
res [ act . id ] = str ( field_get )
2009-09-17 07:27:12 +00:00
return res
2008-07-22 14:24:36 +00:00
_columns = {
' name ' : fields . char ( ' Action Name ' , size = 64 , translate = True ) ,
' type ' : fields . char ( ' Action Type ' , size = 32 , required = True ) ,
' view_id ' : fields . many2one ( ' ir.ui.view ' , ' View Ref. ' , ondelete = ' cascade ' ) ,
2010-07-06 07:06:58 +00:00
' domain ' : fields . char ( ' Domain Value ' , size = 250 ,
2010-07-05 17:57:59 +00:00
help = " Optional domain filtering of the destination data, as a Python expression " ) ,
2010-07-06 07:06:58 +00:00
' context ' : fields . char ( ' Context Value ' , size = 250 , required = True ,
2010-07-05 17:57:59 +00:00
help = " Context dictionary as Python expression, empty by default (Default: {} ) " ) ,
2012-06-27 12:41:36 +00:00
' res_id ' : fields . integer ( ' Record ID ' , help = " Database ID of record to open in form view, when ``view_mode`` is set to ' form ' only " ) ,
' res_model ' : fields . char ( ' Destination Model ' , size = 64 , required = True ,
2010-07-05 17:57:59 +00:00
help = " Model name of the object to open in the view window " ) ,
2012-06-27 12:41:36 +00:00
' src_model ' : fields . char ( ' Source Model ' , size = 64 ,
2010-07-05 17:57:59 +00:00
help = " Optional model name of the objects on which this action should be visible " ) ,
2012-08-11 18:22:50 +00:00
' target ' : fields . selection ( [ ( ' current ' , ' Current Window ' ) , ( ' new ' , ' New Window ' ) , ( ' inline ' , ' Inline Edit ' ) , ( ' inlineview ' , ' Inline View ' ) ] , ' Target Window ' ) ,
2010-07-05 17:57:59 +00:00
' view_mode ' : fields . char ( ' View Mode ' , size = 250 , required = True ,
help = " Comma-separated list of allowed view modes, such as ' form ' , ' tree ' , ' calendar ' , etc. (Default: tree,form) " ) ,
2012-08-11 18:22:50 +00:00
' view_type ' : fields . selection ( ( ( ' tree ' , ' Tree ' ) , ( ' form ' , ' Form ' ) ) , string = ' View Type ' , required = True ,
help = " View type: Tree type to use for the tree view, set to ' tree ' for a hierarchical tree view, or ' form ' for a regular list view " ) ,
2011-11-08 21:55:55 +00:00
' usage ' : fields . char ( ' Action Usage ' , size = 32 ,
help = " Used to filter menu and home actions from the user form. " ) ,
2008-07-22 14:24:36 +00:00
' view_ids ' : fields . one2many ( ' ir.actions.act_window.view ' , ' act_window_id ' , ' Views ' ) ,
2012-01-04 13:30:27 +00:00
' views ' : fields . function ( _views_get_fnc , type = ' binary ' , string = ' Views ' ,
2011-04-01 12:48:52 +00:00
help = " This function field computes the ordered list of views that should be enabled " \
" when displaying the result of an action, federating view mode, views and " \
" reference view. The result is returned as an ordered list of pairs (view_id,view_mode). " ) ,
2008-07-22 14:24:36 +00:00
' limit ' : fields . integer ( ' Limit ' , help = ' Default limit for the list view ' ) ,
' auto_refresh ' : fields . integer ( ' Auto-Refresh ' ,
help = ' Add an auto-refresh on the view ' ) ,
2008-09-18 14:02:05 +00:00
' groups_id ' : fields . many2many ( ' res.groups ' , ' ir_act_window_group_rel ' ,
' act_id ' , ' gid ' , ' Groups ' ) ,
2009-09-17 07:27:12 +00:00
' search_view_id ' : fields . many2one ( ' ir.ui.view ' , ' Search View Ref. ' ) ,
' filter ' : fields . boolean ( ' Filter ' ) ,
2010-02-19 13:46:56 +00:00
' auto_search ' : fields . boolean ( ' Auto Search ' ) ,
2012-01-04 13:30:27 +00:00
' search_view ' : fields . function ( _search_view , type = ' text ' , string = ' Search View ' ) ,
2010-10-15 14:07:29 +00:00
' multi ' : fields . boolean ( ' Action on Multiple Doc. ' , help = " If set to true, the action will not be displayed on the right toolbar of a form view " ) ,
2008-07-22 14:24:36 +00:00
}
2010-10-15 14:07:29 +00:00
2008-07-22 14:24:36 +00:00
_defaults = {
2012-11-02 09:47:05 +00:00
' type ' : ' ir.actions.act_window ' ,
' view_type ' : ' form ' ,
' view_mode ' : ' tree,form ' ,
' context ' : ' {} ' ,
' limit ' : 80 ,
' target ' : ' current ' ,
' auto_refresh ' : 0 ,
' auto_search ' : True ,
2010-10-15 14:07:29 +00:00
' multi ' : False ,
2008-07-22 14:24:36 +00:00
}
2010-09-27 05:46:42 +00:00
2010-11-25 16:57:20 +00:00
def for_xml_id ( self , cr , uid , module , xml_id , context = None ) :
""" Returns the act_window object created for the provided xml_id
: param module : the module the act_window originates in
: param xml_id : the namespace - less id of the action ( the @id
attribute from the XML file )
: return : A read ( ) view of the ir . actions . act_window
"""
dataobj = self . pool . get ( ' ir.model.data ' )
2012-08-31 13:53:09 +00:00
data_id = dataobj . _get_id ( cr , SUPERUSER_ID , module , xml_id )
2010-11-25 16:57:20 +00:00
res_id = dataobj . browse ( cr , uid , data_id , context ) . res_id
return self . read ( cr , uid , res_id , [ ] , context )
2006-12-07 13:41:40 +00:00
act_window ( )
2011-12-06 14:12:04 +00:00
VIEW_TYPES = [
( ' tree ' , ' Tree ' ) ,
( ' form ' , ' Form ' ) ,
( ' graph ' , ' Graph ' ) ,
( ' calendar ' , ' Calendar ' ) ,
( ' gantt ' , ' Gantt ' ) ,
( ' kanban ' , ' Kanban ' ) ]
2007-05-15 13:27:39 +00:00
class act_window_view ( osv . osv ) :
2008-07-22 14:24:36 +00:00
_name = ' ir.actions.act_window.view '
_table = ' ir_act_window_view '
_rec_name = ' view_id '
2011-04-01 12:48:52 +00:00
_order = ' sequence '
2008-07-22 14:24:36 +00:00
_columns = {
' sequence ' : fields . integer ( ' Sequence ' ) ,
' view_id ' : fields . many2one ( ' ir.ui.view ' , ' View ' ) ,
2011-12-06 14:12:04 +00:00
' view_mode ' : fields . selection ( VIEW_TYPES , string = ' View Type ' , required = True ) ,
2008-07-22 14:24:36 +00:00
' act_window_id ' : fields . many2one ( ' ir.actions.act_window ' , ' Action ' , ondelete = ' cascade ' ) ,
2009-01-26 17:40:29 +00:00
' multi ' : fields . boolean ( ' On Multiple Doc. ' ,
help = " If set to true, the action will not be displayed on the right toolbar of a form view. " ) ,
2008-07-22 14:24:36 +00:00
}
_defaults = {
2012-11-02 09:47:05 +00:00
' multi ' : False ,
2008-07-22 14:24:36 +00:00
}
2011-04-01 12:48:52 +00:00
def _auto_init ( self , cr , context = None ) :
super ( act_window_view , self ) . _auto_init ( cr , context )
cr . execute ( ' SELECT indexname FROM pg_indexes WHERE indexname = \' act_window_view_unique_mode_per_action \' ' )
if not cr . fetchone ( ) :
cr . execute ( ' CREATE UNIQUE INDEX act_window_view_unique_mode_per_action ON ir_act_window_view (act_window_id, view_mode) ' )
2007-05-15 13:27:39 +00:00
act_window_view ( )
2006-12-07 13:41:40 +00:00
class act_wizard ( osv . osv ) :
2008-07-22 14:24:36 +00:00
_name = ' ir.actions.wizard '
2009-01-26 15:47:04 +00:00
_inherit = ' ir.actions.actions '
2008-07-22 14:24:36 +00:00
_table = ' ir_act_wizard '
_sequence = ' ir_actions_id_seq '
2010-12-10 22:42:58 +00:00
_order = ' name '
2008-07-22 14:24:36 +00:00
_columns = {
2009-01-26 17:40:29 +00:00
' name ' : fields . char ( ' Wizard Info ' , size = 64 , required = True , translate = True ) ,
' type ' : fields . char ( ' Action Type ' , size = 32 , required = True ) ,
' wiz_name ' : fields . char ( ' Wizard Name ' , size = 64 , required = True ) ,
' multi ' : fields . boolean ( ' Action on Multiple Doc. ' , help = " If set to true, the wizard will not be displayed on the right toolbar of a form view. " ) ,
2008-10-08 14:12:08 +00:00
' groups_id ' : fields . many2many ( ' res.groups ' , ' res_groups_wizard_rel ' , ' uid ' , ' gid ' , ' Groups ' ) ,
' model ' : fields . char ( ' Object ' , size = 64 ) ,
2008-07-22 14:24:36 +00:00
}
_defaults = {
2012-11-02 09:47:05 +00:00
' type ' : ' ir.actions.wizard ' ,
' multi ' : False ,
2008-07-22 14:24:36 +00:00
}
2006-12-07 13:41:40 +00:00
act_wizard ( )
2007-10-25 18:20:12 +00:00
class act_url ( osv . osv ) :
2012-06-08 10:17:10 +00:00
_name = ' ir.actions.act_url '
2008-07-22 14:24:36 +00:00
_table = ' ir_act_url '
2012-09-24 14:57:50 +00:00
_inherit = ' ir.actions.actions '
2008-07-22 14:24:36 +00:00
_sequence = ' ir_actions_id_seq '
2010-12-10 22:42:58 +00:00
_order = ' name '
2008-07-22 14:24:36 +00:00
_columns = {
' name ' : fields . char ( ' Action Name ' , size = 64 , translate = True ) ,
' type ' : fields . char ( ' Action Type ' , size = 32 , required = True ) ,
2009-01-26 17:40:29 +00:00
' url ' : fields . text ( ' Action URL ' , required = True ) ,
2008-07-22 14:24:36 +00:00
' target ' : fields . selection ( (
( ' new ' , ' New Window ' ) ,
( ' self ' , ' This Window ' ) ) ,
' Action Target ' , required = True
)
}
_defaults = {
2012-11-02 09:47:05 +00:00
' type ' : ' ir.actions.act_url ' ,
' target ' : ' new '
2008-07-22 14:24:36 +00:00
}
2007-10-25 18:20:12 +00:00
act_url ( )
2010-11-23 13:52:24 +00:00
def model_get ( self , cr , uid , context = None ) :
2008-08-14 06:00:47 +00:00
wkf_pool = self . pool . get ( ' workflow ' )
ids = wkf_pool . search ( cr , uid , [ ] )
osvs = wkf_pool . read ( cr , uid , ids , [ ' osv ' ] )
2008-09-18 14:02:05 +00:00
2008-08-14 06:00:47 +00:00
res = [ ]
mpool = self . pool . get ( ' ir.model ' )
for osv in osvs :
model = osv . get ( ' osv ' )
id = mpool . search ( cr , uid , [ ( ' model ' , ' = ' , model ) ] )
name = mpool . read ( cr , uid , id ) [ 0 ] [ ' name ' ]
res . append ( ( model , name ) )
2008-09-18 14:02:05 +00:00
2008-08-14 06:00:47 +00:00
return res
2008-08-19 11:23:03 +00:00
2008-08-20 10:21:43 +00:00
class ir_model_fields ( osv . osv ) :
_inherit = ' ir.model.fields '
2008-10-28 23:15:42 +00:00
_rec_name = ' field_description '
2008-08-20 10:21:43 +00:00
_columns = {
2008-12-01 15:13:51 +00:00
' complete_name ' : fields . char ( ' Complete Name ' , size = 64 , select = 1 ) ,
2008-08-20 10:21:43 +00:00
}
ir_model_fields ( )
2008-08-20 11:15:20 +00:00
2008-08-25 10:55:15 +00:00
class server_object_lines ( osv . osv ) :
_name = ' ir.server.object.lines '
_sequence = ' ir_actions_id_seq '
_columns = {
' server_id ' : fields . many2one ( ' ir.actions.server ' , ' Object Mapping ' ) ,
' col1 ' : fields . many2one ( ' ir.model.fields ' , ' Destination ' , required = True ) ,
2011-07-22 13:17:23 +00:00
' value ' : fields . text ( ' Value ' , required = True , help = " Expression containing a value specification. \n "
" When Formula type is selected, this field may be a Python expression "
" that can use the same values as for the condition field on the server action. \n "
" If Value type is selected, the value will be used directly without evaluation. " ) ,
2008-08-25 10:55:15 +00:00
' type ' : fields . selection ( [
( ' value ' , ' Value ' ) ,
( ' equation ' , ' Formula ' )
] , ' Type ' , required = True , size = 32 , change_default = True ) ,
}
_defaults = {
2012-11-02 09:47:05 +00:00
' type ' : ' equation ' ,
2008-08-25 10:55:15 +00:00
}
server_object_lines ( )
2008-08-19 12:30:13 +00:00
##
2008-06-15 00:25:47 +00:00
# Actions that are run on the server side
#
class actions_server ( osv . osv ) :
2008-12-19 05:37:16 +00:00
2010-11-23 13:52:24 +00:00
def _select_signals ( self , cr , uid , context = None ) :
2011-08-11 14:34:34 +00:00
cr . execute ( """ SELECT distinct w.osv, t.signal FROM wkf w, wkf_activity a, wkf_transition t
WHERE w . id = a . wkf_id AND
( t . act_from = a . id OR t . act_to = a . id ) AND
t . signal IS NOT NULL """ )
2008-12-15 13:49:12 +00:00
result = cr . fetchall ( ) or [ ]
res = [ ]
for rs in result :
2009-12-02 18:20:21 +00:00
if rs [ 0 ] is not None and rs [ 1 ] is not None :
2011-08-11 14:34:34 +00:00
line = rs [ 1 ] , " %s - ( %s ) " % ( rs [ 1 ] , rs [ 0 ] )
2010-03-11 14:12:46 +00:00
res . append ( line )
2008-12-15 13:49:12 +00:00
return res
2010-04-21 08:53:38 +00:00
2010-11-23 13:52:24 +00:00
def _select_objects ( self , cr , uid , context = None ) :
2010-03-11 14:12:46 +00:00
model_pool = self . pool . get ( ' ir.model ' )
ids = model_pool . search ( cr , uid , [ ( ' name ' , ' not ilike ' , ' . ' ) ] )
res = model_pool . read ( cr , uid , ids , [ ' model ' , ' name ' ] )
return [ ( r [ ' model ' ] , r [ ' name ' ] ) for r in res ] + [ ( ' ' , ' ' ) ]
2010-04-21 08:53:38 +00:00
2010-11-23 13:52:24 +00:00
def change_object ( self , cr , uid , ids , copy_object , state , context = None ) :
2011-06-08 08:40:20 +00:00
if state == ' object_copy ' and copy_object :
2011-09-16 10:14:32 +00:00
if context is None :
context = { }
2010-03-11 14:12:46 +00:00
model_pool = self . pool . get ( ' ir.model ' )
model = copy_object . split ( ' , ' ) [ 0 ]
mid = model_pool . search ( cr , uid , [ ( ' model ' , ' = ' , model ) ] )
return {
2011-09-16 10:14:32 +00:00
' value ' : { ' srcmodel_id ' : mid [ 0 ] } ,
' context ' : context
2010-03-11 14:12:46 +00:00
}
else :
return { }
2008-12-19 05:37:16 +00:00
2008-07-22 14:24:36 +00:00
_name = ' ir.actions.server '
_table = ' ir_act_server '
2012-09-24 14:57:50 +00:00
_inherit = ' ir.actions.actions '
2008-07-22 14:24:36 +00:00
_sequence = ' ir_actions_id_seq '
2010-12-10 22:42:58 +00:00
_order = ' sequence,name '
2008-07-22 14:24:36 +00:00
_columns = {
2011-07-22 13:17:23 +00:00
' name ' : fields . char ( ' Action Name ' , required = True , size = 64 , translate = True ) ,
' condition ' : fields . char ( ' Condition ' , size = 256 , required = True ,
help = " Condition that is tested before the action is executed, "
" and prevent execution if it is not verified. \n "
" Example: object.list_price > 5000 \n "
" It is a Python expression that can use the following values: \n "
" - self: ORM model of the record on which the action is triggered \n "
" - object or obj: browse_record of the record on which the action is triggered \n "
" - pool: ORM model pool (i.e. self.pool) \n "
" - time: Python time module \n "
" - cr: database cursor \n "
" - uid: current user id \n "
" - context: current context " ) ,
2008-07-22 14:24:36 +00:00
' state ' : fields . selection ( [
2008-12-04 23:58:43 +00:00
( ' client_action ' , ' Client Action ' ) ,
2008-07-22 14:24:36 +00:00
( ' dummy ' , ' Dummy ' ) ,
2008-12-17 11:40:21 +00:00
( ' loop ' , ' Iteration ' ) ,
2008-12-16 10:18:09 +00:00
( ' code ' , ' Python Code ' ) ,
2008-07-22 14:24:36 +00:00
( ' trigger ' , ' Trigger ' ) ,
( ' email ' , ' Email ' ) ,
( ' sms ' , ' SMS ' ) ,
( ' object_create ' , ' Create Object ' ) ,
2010-03-11 14:12:46 +00:00
( ' object_copy ' , ' Copy Object ' ) ,
2008-07-22 14:24:36 +00:00
( ' object_write ' , ' Write Object ' ) ,
2008-12-13 06:30:50 +00:00
( ' other ' , ' Multi Actions ' ) ,
2009-01-26 17:40:29 +00:00
] , ' Action Type ' , required = True , size = 32 , help = " Type of the Action that is to be executed " ) ,
2011-07-22 13:17:23 +00:00
' code ' : fields . text ( ' Python Code ' , help = " Python code to be executed if condition is met. \n "
" It is a Python block that can use the same values as for the condition field " ) ,
2009-01-26 17:40:29 +00:00
' sequence ' : fields . integer ( ' Sequence ' , help = " Important when you deal with multiple actions, the execution order will be decided based on this, low number is higher priority. " ) ,
2012-03-01 04:27:45 +00:00
' model_id ' : fields . many2one ( ' ir.model ' , ' Object ' , required = True , help = " Select the object on which the action will work (read, write, create). " , ondelete = ' cascade ' ) ,
2009-01-26 17:40:29 +00:00
' action_id ' : fields . many2one ( ' ir.actions.actions ' , ' Client Action ' , help = " Select the Action Window, Report, Wizard to be executed. " ) ,
2011-08-11 14:34:34 +00:00
' trigger_name ' : fields . selection ( _select_signals , string = ' Trigger Signal ' , size = 128 , help = " The workflow signal to trigger " ) ,
' wkf_model_id ' : fields . many2one ( ' ir.model ' , ' Target Object ' , help = " The object that should receive the workflow signal (must have an associated workflow) " ) ,
' trigger_obj_id ' : fields . many2one ( ' ir.model.fields ' , ' Relation Field ' , help = " The field on the current object that links to the target object record (must be a many2one, or an integer field with the record ID) " ) ,
2011-07-22 13:17:23 +00:00
' email ' : fields . char ( ' Email Address ' , size = 512 , help = " Expression that returns the email address to send to. Can be based on the same values as for the condition field. \n "
" Example: object.invoice_address_id.email, or ' me@example.com ' " ) ,
' subject ' : fields . char ( ' Subject ' , size = 1024 , translate = True , help = " Email subject, may contain expressions enclosed in double brackets based on the same values as those "
" available in the condition field, e.g. `Hello [[ object.partner_id.name ]]` " ) ,
' message ' : fields . text ( ' Message ' , translate = True , help = " Email contents, may contain expressions enclosed in double brackets based on the same values as those "
" available in the condition field, e.g. `Dear [[ object.partner_id.name ]]` " ) ,
2009-01-26 17:40:29 +00:00
' mobile ' : fields . char ( ' Mobile No ' , size = 512 , help = " Provides fields that be used to fetch the mobile number, e.g. you select the invoice, then `object.invoice_address_id.mobile` is the field which gives the correct mobile number " ) ,
2008-09-10 12:55:55 +00:00
' sms ' : fields . char ( ' SMS ' , size = 160 , translate = True ) ,
2009-01-26 17:40:29 +00:00
' child_ids ' : fields . many2many ( ' ir.actions.server ' , ' rel_server_actions ' , ' server_id ' , ' action_id ' , ' Other Actions ' ) ,
2008-07-22 14:24:36 +00:00
' usage ' : fields . char ( ' Action Usage ' , size = 32 ) ,
2008-12-13 06:30:50 +00:00
' type ' : fields . char ( ' Action Type ' , size = 32 , required = True ) ,
2009-01-26 17:40:29 +00:00
' srcmodel_id ' : fields . many2one ( ' ir.model ' , ' Model ' , help = " Object in which you want to create / write the object. If it is empty then refer to the Object field. " ) ,
' fields_lines ' : fields . one2many ( ' ir.server.object.lines ' , ' server_id ' , ' Field Mappings. ' ) ,
' record_id ' : fields . many2one ( ' ir.model.fields ' , ' Create Id ' , help = " Provide the field name where the record id is stored after the create operations. If it is empty, you can not track the new record. " ) ,
' write_id ' : fields . char ( ' Write Id ' , size = 256 , help = " Provide the field name that the record id refers to for the write operation. If it is empty it will refer to the active id of the object. " ) ,
' loop_action ' : fields . many2one ( ' ir.actions.server ' , ' Loop Action ' , help = " Select the action that will be executed. Loop action will not be avaliable inside loop. " ) ,
' expression ' : fields . char ( ' Loop Expression ' , size = 512 , help = " Enter the field/expression that will return the list. E.g. select the sale order in Object, and you can have loop on the sales order line. Expression = `object.order_line`. " ) ,
2010-03-11 14:12:46 +00:00
' copy_object ' : fields . reference ( ' Copy Of ' , selection = _select_objects , size = 256 ) ,
2008-07-22 14:24:36 +00:00
}
_defaults = {
2012-11-02 09:47:05 +00:00
' state ' : ' dummy ' ,
' condition ' : ' True ' ,
' type ' : ' ir.actions.server ' ,
' sequence ' : 5 ,
' code ' : """ # You can use the following variables:
2011-07-22 13:17:23 +00:00
# - self: ORM model of the record on which the action is triggered
2011-09-16 14:13:58 +00:00
# - object: browse_record of the record on which the action is triggered if there is one, otherwise None
2011-07-22 13:17:23 +00:00
# - pool: ORM model pool (i.e. self.pool)
# - time: Python time module
# - cr: database cursor
# - uid: current user id
# - context: current context
2008-12-16 10:18:09 +00:00
# If you plan to return an action, assign: action = {...}
""" ,
2008-07-22 14:24:36 +00:00
}
2008-09-18 14:02:05 +00:00
2008-12-11 11:32:08 +00:00
def get_email ( self , cr , uid , action , context ) :
2008-08-21 09:04:40 +00:00
obj_pool = self . pool . get ( action . model_id . model )
id = context . get ( ' active_id ' )
obj = obj_pool . browse ( cr , uid , id )
2008-09-18 14:02:05 +00:00
2008-08-21 10:36:17 +00:00
fields = None
2008-09-18 14:02:05 +00:00
2008-12-11 11:32:08 +00:00
if ' / ' in action . email . complete_name :
fields = action . email . complete_name . split ( ' / ' )
elif ' . ' in action . email . complete_name :
fields = action . email . complete_name . split ( ' . ' )
for field in fields :
try :
obj = getattr ( obj , field )
2010-10-11 09:37:09 +00:00
except Exception :
2012-01-24 11:47:30 +00:00
_logger . exception ( ' Failed to parse: %s ' , field )
2008-12-11 11:32:08 +00:00
return obj
def get_mobile ( self , cr , uid , action , context ) :
obj_pool = self . pool . get ( action . model_id . model )
id = context . get ( ' active_id ' )
obj = obj_pool . browse ( cr , uid , id )
fields = None
if ' / ' in action . mobile . complete_name :
fields = action . mobile . complete_name . split ( ' / ' )
elif ' . ' in action . mobile . complete_name :
fields = action . mobile . complete_name . split ( ' . ' )
2008-09-18 14:02:05 +00:00
2008-08-21 09:04:40 +00:00
for field in fields :
2008-08-21 10:36:17 +00:00
try :
obj = getattr ( obj , field )
2010-10-11 09:37:09 +00:00
except Exception :
2012-01-24 11:47:30 +00:00
_logger . exception ( ' Failed to parse: %s ' , field )
2008-09-18 14:02:05 +00:00
2008-08-21 09:04:40 +00:00
return obj
2008-08-14 06:00:47 +00:00
2010-09-21 13:14:37 +00:00
def merge_message ( self , cr , uid , keystr , action , context = None ) :
if context is None :
context = { }
2011-08-27 21:36:28 +00:00
2011-08-27 21:37:51 +00:00
def merge ( match ) :
2008-08-21 10:36:17 +00:00
obj_pool = self . pool . get ( action . model_id . model )
id = context . get ( ' active_id ' )
obj = obj_pool . browse ( cr , uid , id )
2008-12-11 11:32:08 +00:00
exp = str ( match . group ( ) [ 2 : - 2 ] ) . strip ( )
2010-09-21 13:14:37 +00:00
result = eval ( exp ,
{
' object ' : obj ,
' context ' : dict ( context ) , # copy context to prevent side-effects of eval
' time ' : time ,
} )
2008-12-13 12:42:04 +00:00
if result in ( None , False ) :
return str ( " -------- " )
2010-01-27 14:42:27 +00:00
return tools . ustr ( result )
2009-10-30 12:33:59 +00:00
2008-11-26 23:52:20 +00:00
com = re . compile ( ' ( \ [ \ [.+? \ ] \ ]) ' )
2008-08-25 13:11:10 +00:00
message = com . sub ( merge , keystr )
2009-10-30 12:33:59 +00:00
2008-08-21 10:36:17 +00:00
return message
2008-09-18 14:02:05 +00:00
2008-07-22 14:24:36 +00:00
# Context should contains:
# ids : original ids
# id : current id of the object
# OUT:
2012-02-12 11:45:09 +00:00
# False : Finished correctly
2008-07-22 14:24:36 +00:00
# ACTION_ID : Action to launch
2009-10-30 12:33:59 +00:00
2010-09-21 13:14:37 +00:00
# FIXME: refactor all the eval() calls in run()!
def run ( self , cr , uid , ids , context = None ) :
if context is None :
context = { }
2011-08-01 11:45:43 +00:00
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid )
2008-07-22 14:24:36 +00:00
for action in self . browse ( cr , uid , ids , context ) :
2011-09-12 14:44:11 +00:00
obj = None
2008-12-16 19:26:08 +00:00
obj_pool = self . pool . get ( action . model_id . model )
2011-09-12 14:44:11 +00:00
if context . get ( ' active_model ' ) == action . model_id . model and context . get ( ' active_id ' ) :
obj = obj_pool . browse ( cr , uid , context [ ' active_id ' ] , context = context )
2008-12-16 19:26:08 +00:00
cxt = {
2011-07-22 13:17:23 +00:00
' self ' : obj_pool ,
2009-10-30 12:33:59 +00:00
' object ' : obj ,
2011-08-29 12:36:25 +00:00
' obj ' : obj ,
' pool ' : self . pool ,
2011-08-22 10:00:07 +00:00
' time ' : time ,
2011-07-22 13:17:23 +00:00
' cr ' : cr ,
' context ' : dict ( context ) , # copy context to prevent side-effects of eval
2011-08-22 10:00:07 +00:00
' uid ' : uid ,
' user ' : user
2008-12-16 19:26:08 +00:00
}
expr = eval ( str ( action . condition ) , cxt )
if not expr :
continue
2009-10-30 12:33:59 +00:00
2008-12-04 23:58:43 +00:00
if action . state == ' client_action ' :
if not action . action_id :
2009-10-30 12:33:59 +00:00
raise osv . except_osv ( _ ( ' Error ' ) , _ ( " Please specify an action to launch ! " ) )
2009-12-02 18:20:21 +00:00
return self . pool . get ( action . action_id . type ) \
. read ( cr , uid , action . action_id . id , context = context )
2008-12-16 19:26:08 +00:00
2010-06-25 09:22:56 +00:00
if action . state == ' code ' :
2011-07-22 13:17:23 +00:00
eval ( action . code , cxt , mode = " exec " , nocopy = True ) # nocopy allows to return 'action'
2011-08-23 14:49:42 +00:00
if ' action ' in cxt :
return cxt [ ' action ' ]
2008-09-18 14:02:05 +00:00
2008-07-23 16:33:28 +00:00
if action . state == ' email ' :
2011-08-01 11:45:43 +00:00
email_from = config [ ' email_from ' ]
2008-12-17 11:40:21 +00:00
address = str ( action . email )
try :
address = eval ( str ( action . email ) , cxt )
except :
pass
2009-10-30 12:33:59 +00:00
2008-10-22 11:25:13 +00:00
if not address :
2012-01-24 11:47:30 +00:00
_logger . info ( ' No partner email address specified, not sending any email. ' )
2009-09-17 07:27:12 +00:00
continue
2010-04-21 08:53:38 +00:00
2011-08-29 12:36:25 +00:00
if not email_from :
2012-01-24 11:47:30 +00:00
_logger . debug ( ' --email-from command line option is not specified, using a fallback value instead. ' )
2012-08-10 08:23:44 +00:00
if user . email :
email_from = user . email
2011-08-29 12:36:25 +00:00
else :
email_from = " %s @ %s " % ( user . login , gethostname ( ) )
2010-01-18 15:28:03 +00:00
subject = self . merge_message ( cr , uid , action . subject , action , context )
body = self . merge_message ( cr , uid , action . message , action , context )
2010-04-21 08:53:38 +00:00
2011-07-20 10:18:22 +00:00
ir_mail_server = self . pool . get ( ' ir.mail_server ' )
2011-08-29 12:36:25 +00:00
msg = ir_mail_server . build_email ( email_from , [ address ] , subject , body )
2011-07-20 10:18:22 +00:00
res_email = ir_mail_server . send_email ( cr , uid , msg )
2011-03-31 09:33:42 +00:00
if res_email :
2012-01-24 11:47:30 +00:00
_logger . info ( ' Email successfully sent to: %s ' , address )
2008-07-23 16:33:28 +00:00
else :
2012-01-24 11:47:30 +00:00
_logger . warning ( ' Failed to send email to: %s ' , address )
2008-08-14 08:40:46 +00:00
2008-08-14 06:00:47 +00:00
if action . state == ' trigger ' :
2008-08-14 08:40:46 +00:00
wf_service = netsvc . LocalService ( " workflow " )
2008-12-12 11:48:54 +00:00
model = action . wkf_model_id . model
2011-08-11 14:34:34 +00:00
m2o_field_name = action . trigger_obj_id . name
target_id = obj_pool . read ( cr , uid , context . get ( ' active_id ' ) , [ m2o_field_name ] ) [ m2o_field_name ]
target_id = target_id [ 0 ] if isinstance ( target_id , tuple ) else target_id
wf_service . trg_validate ( uid , model , int ( target_id ) , action . trigger_name , cr )
2008-09-18 14:02:05 +00:00
2008-08-06 09:01:54 +00:00
if action . state == ' sms ' :
2008-09-10 07:16:19 +00:00
#TODO: set the user and password from the system
# for the sms gateway user / password
2010-02-10 11:06:47 +00:00
# USE smsclient module from extra-addons
2012-01-24 11:47:30 +00:00
_logger . warning ( ' SMS Facility has not been implemented yet. Use smsclient module! ' )
2009-10-30 12:33:59 +00:00
2008-08-14 06:00:47 +00:00
if action . state == ' other ' :
2008-12-16 19:26:08 +00:00
res = [ ]
2008-08-14 08:40:46 +00:00
for act in action . child_ids :
2008-12-18 05:22:28 +00:00
context [ ' active_id ' ] = context [ ' active_ids ' ] [ 0 ]
2008-12-12 11:48:54 +00:00
result = self . run ( cr , uid , [ act . id ] , context )
if result :
2008-12-16 19:26:08 +00:00
res . append ( result )
2008-12-12 11:48:54 +00:00
return res
2009-10-30 12:33:59 +00:00
2008-12-17 11:40:21 +00:00
if action . state == ' loop ' :
expr = eval ( str ( action . expression ) , cxt )
context [ ' object ' ] = obj
for i in expr :
context [ ' active_id ' ] = i . id
2012-12-14 13:25:33 +00:00
self . run ( cr , uid , [ action . loop_action . id ] , context )
2009-10-30 12:33:59 +00:00
2008-08-25 13:11:10 +00:00
if action . state == ' object_write ' :
res = { }
for exp in action . fields_lines :
euq = exp . value
if exp . type == ' equation ' :
2008-12-17 11:40:21 +00:00
expr = eval ( euq , cxt )
2008-08-25 13:11:10 +00:00
else :
expr = exp . value
res [ exp . col1 . name ] = expr
2008-09-18 14:02:05 +00:00
2008-12-17 11:40:21 +00:00
if not action . write_id :
2008-12-12 05:07:38 +00:00
if not action . srcmodel_id :
obj_pool = self . pool . get ( action . model_id . model )
obj_pool . write ( cr , uid , [ context . get ( ' active_id ' ) ] , res )
else :
2008-12-17 11:40:21 +00:00
write_id = context . get ( ' active_id ' )
2008-12-12 05:07:38 +00:00
obj_pool = self . pool . get ( action . srcmodel_id . model )
2008-12-17 11:40:21 +00:00
obj_pool . write ( cr , uid , [ write_id ] , res )
2009-10-30 12:33:59 +00:00
2008-12-17 11:40:21 +00:00
elif action . write_id :
2008-12-11 15:01:47 +00:00
obj_pool = self . pool . get ( action . srcmodel_id . model )
2008-12-17 11:40:21 +00:00
rec = self . pool . get ( action . model_id . model ) . browse ( cr , uid , context . get ( ' active_id ' ) )
id = eval ( action . write_id , { ' object ' : rec } )
2008-12-18 06:31:14 +00:00
try :
id = int ( id )
except :
raise osv . except_osv ( _ ( ' Error ' ) , _ ( " Problem in configuration `Record Id` in Server Action! " ) )
2009-10-30 12:33:59 +00:00
2008-12-17 11:40:21 +00:00
if type ( id ) != type ( 1 ) :
raise osv . except_osv ( _ ( ' Error ' ) , _ ( " Problem in configuration `Record Id` in Server Action! " ) )
write_id = id
2008-12-16 19:26:08 +00:00
obj_pool . write ( cr , uid , [ write_id ] , res )
2008-12-17 11:40:21 +00:00
2008-08-25 13:11:10 +00:00
if action . state == ' object_create ' :
2008-08-26 08:51:10 +00:00
res = { }
for exp in action . fields_lines :
euq = exp . value
if exp . type == ' equation ' :
2011-07-22 13:17:23 +00:00
expr = eval ( euq , cxt )
2008-08-26 08:51:10 +00:00
else :
expr = exp . value
res [ exp . col1 . name ] = expr
2008-09-18 14:02:05 +00:00
2008-12-11 15:01:47 +00:00
obj_pool = self . pool . get ( action . srcmodel_id . model )
res_id = obj_pool . create ( cr , uid , res )
2008-12-16 19:26:08 +00:00
if action . record_id :
self . pool . get ( action . model_id . model ) . write ( cr , uid , [ context . get ( ' active_id ' ) ] , { action . record_id . name : res_id } )
2010-04-21 08:53:38 +00:00
2010-03-11 14:12:46 +00:00
if action . state == ' object_copy ' :
res = { }
for exp in action . fields_lines :
euq = exp . value
if exp . type == ' equation ' :
2011-07-22 13:17:23 +00:00
expr = eval ( euq , cxt )
2010-03-11 14:12:46 +00:00
else :
expr = exp . value
res [ exp . col1 . name ] = expr
model = action . copy_object . split ( ' , ' ) [ 0 ]
cid = action . copy_object . split ( ' , ' ) [ 1 ]
obj_pool = self . pool . get ( model )
2012-12-14 13:25:33 +00:00
obj_pool . copy ( cr , uid , int ( cid ) , res )
2008-09-18 14:02:05 +00:00
2008-07-22 14:24:36 +00:00
return False
2008-12-17 11:40:21 +00:00
2008-06-15 00:25:47 +00:00
actions_server ( )
2008-06-15 14:59:23 +00:00
class act_window_close ( osv . osv ) :
2008-07-22 14:24:36 +00:00
_name = ' ir.actions.act_window_close '
2009-01-26 15:47:04 +00:00
_inherit = ' ir.actions.actions '
2008-07-22 14:24:36 +00:00
_table = ' ir_actions '
_defaults = {
2012-11-02 09:47:05 +00:00
' type ' : ' ir.actions.act_window_close ' ,
2008-07-22 14:24:36 +00:00
}
2008-06-15 14:59:23 +00:00
act_window_close ( )
2008-09-29 08:49:06 +00:00
# This model use to register action services.
2010-04-18 20:07:32 +00:00
TODO_STATES = [ ( ' open ' , ' To Do ' ) ,
2011-07-29 14:26:22 +00:00
( ' done ' , ' Done ' ) ]
2011-10-02 11:51:31 +00:00
TODO_TYPES = [ ( ' manual ' , ' Launch Manually ' ) , ( ' once ' , ' Launch Manually Once ' ) ,
2011-07-29 14:26:22 +00:00
( ' automatic ' , ' Launch Automatically ' ) ]
2008-09-29 08:49:06 +00:00
class ir_actions_todo ( osv . osv ) :
2011-07-01 13:08:40 +00:00
"""
Configuration Wizards
"""
2009-10-30 12:33:59 +00:00
_name = ' ir.actions.todo '
2011-07-01 13:08:40 +00:00
_description = " Configuration Wizards "
2008-09-29 08:49:06 +00:00
_columns = {
2009-12-07 10:17:40 +00:00
' action_id ' : fields . many2one (
2012-08-04 21:53:00 +00:00
' ir.actions.actions ' , ' Action ' , select = True , required = True ) ,
2009-12-07 10:17:40 +00:00
' sequence ' : fields . integer ( ' Sequence ' ) ,
2012-10-12 12:24:19 +00:00
' state ' : fields . selection ( TODO_STATES , string = ' Status ' , required = True ) ,
2011-07-06 15:40:01 +00:00
' name ' : fields . char ( ' Name ' , size = 64 ) ,
2011-07-14 10:38:07 +00:00
' type ' : fields . selection ( TODO_TYPES , ' Type ' , required = True ,
2011-08-04 11:55:01 +00:00
help = """ Manual: Launched manually.
2011-10-02 11:51:31 +00:00
Automatic : Runs whenever the system is reconfigured .
2012-02-12 11:45:09 +00:00
Launch Manually Once : after having been launched manually , it sets automatically to Done . """ ),
2011-07-06 15:40:01 +00:00
' groups_id ' : fields . many2many ( ' res.groups ' , ' res_groups_action_rel ' , ' uid ' , ' gid ' , ' Groups ' ) ,
' note ' : fields . text ( ' Text ' , translate = True ) ,
2008-09-29 08:49:06 +00:00
}
_defaults = {
2010-09-23 10:53:45 +00:00
' state ' : ' open ' ,
' sequence ' : 10 ,
2011-07-29 14:26:22 +00:00
' type ' : ' manual ' ,
2008-09-29 08:49:06 +00:00
}
2012-08-04 21:53:00 +00:00
_order = " sequence,id "
2010-08-23 06:43:09 +00:00
2010-08-30 13:04:48 +00:00
def action_launch ( self , cr , uid , ids , context = None ) :
""" Launch Action of Wizard """
wizard_id = ids and ids [ 0 ] or False
wizard = self . browse ( cr , uid , wizard_id , context = context )
2011-10-02 11:51:31 +00:00
if wizard . type in ( ' automatic ' , ' once ' ) :
2011-07-29 14:51:06 +00:00
wizard . write ( { ' state ' : ' done ' } )
2011-07-18 12:39:07 +00:00
2011-08-06 01:52:21 +00:00
# Load action
2012-08-04 21:53:00 +00:00
act_type = self . pool . get ( ' ir.actions.actions ' ) . read ( cr , uid , wizard . action_id . id , [ ' type ' ] , context = context )
res = self . pool . get ( act_type [ ' type ' ] ) . read ( cr , uid , wizard . action_id . id , [ ] , context = context )
if act_type < > ' ir.actions.act_window ' :
return res
2011-08-06 01:52:21 +00:00
res . setdefault ( ' context ' , ' {} ' )
2011-07-18 10:18:12 +00:00
res [ ' nodestroy ' ] = True
2011-06-28 11:31:31 +00:00
2011-07-06 15:40:01 +00:00
# Open a specific record when res_id is provided in the context
2011-08-06 01:52:21 +00:00
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context = context )
ctx = eval ( res [ ' context ' ] , { ' user ' : user } )
if ctx . get ( ' res_id ' ) :
res . update ( { ' res_id ' : ctx . pop ( ' res_id ' ) } )
# disable log for automatic wizards
if wizard . type == ' automatic ' :
ctx . update ( { ' disable_log ' : True } )
res . update ( { ' context ' : ctx } )
2010-08-30 13:04:48 +00:00
return res
2010-08-23 06:43:09 +00:00
def action_open ( self , cr , uid , ids , context = None ) :
""" Sets configuration wizard in TODO state """
return self . write ( cr , uid , ids , { ' state ' : ' open ' } , context = context )
2011-07-14 10:38:07 +00:00
def progress ( self , cr , uid , context = None ) :
""" Returns a dict with 3 keys { todo, done, total}.
These keys all map to integers and provide the number of todos
marked as open , the total number of todos and the number of
todos not open ( which is basically a shortcut to total - todo )
: rtype : dict
"""
user_groups = set ( map (
lambda x : x . id ,
self . pool [ ' res.users ' ] . browse ( cr , uid , [ uid ] , context = context ) [ 0 ] . groups_id ) )
def groups_match ( todo ) :
""" Checks if the todo ' s groups match those of the current user
"""
return not todo . groups_id \
or bool ( user_groups . intersection ( (
group . id for group in todo . groups_id ) ) )
done = filter (
groups_match ,
self . browse ( cr , uid ,
2011-10-02 11:51:31 +00:00
self . search ( cr , uid , [ ( ' state ' , ' != ' , ' open ' ) ] , context = context ) ,
2011-07-14 10:38:07 +00:00
context = context ) )
total = filter (
groups_match ,
self . browse ( cr , uid ,
2011-10-02 11:51:31 +00:00
self . search ( cr , uid , [ ] , context = context ) ,
2011-07-14 10:38:07 +00:00
context = context ) )
return {
' done ' : len ( done ) ,
' total ' : len ( total ) ,
' todo ' : len ( total ) - len ( done )
}
2008-09-29 08:49:06 +00:00
ir_actions_todo ( )
2011-06-30 11:51:34 +00:00
class act_client ( osv . osv ) :
_name = ' ir.actions.client '
_inherit = ' ir.actions.actions '
_table = ' ir_act_client '
_sequence = ' ir_actions_id_seq '
_order = ' name '
2011-08-04 08:54:55 +00:00
def _get_params ( self , cr , uid , ids , field_name , arg , context ) :
2012-08-21 15:45:55 +00:00
result = { }
for record in self . browse ( cr , uid , ids , context = context ) :
result [ record . id ] = record . params_store and eval ( record . params_store , { ' uid ' : uid } ) or False
return result
2011-06-30 11:51:34 +00:00
2011-08-25 12:30:49 +00:00
def _set_params ( self , cr , uid , id , field_name , field_value , arg , context ) :
2012-08-04 21:53:00 +00:00
if isinstance ( field_value , dict ) :
self . write ( cr , uid , id , { ' params_store ' : repr ( field_value ) } , context = context )
else :
self . write ( cr , uid , id , { ' params_store ' : field_value } , context = context )
2011-06-30 11:51:34 +00:00
_columns = {
2012-08-22 13:34:06 +00:00
' name ' : fields . char ( ' Action Name ' , required = True , size = 64 , translate = True ) ,
2011-06-30 11:51:34 +00:00
' tag ' : fields . char ( ' Client action tag ' , size = 64 , required = True ,
help = " An arbitrary string, interpreted by the client "
" according to its own needs and wishes. There "
" is no central tag repository across clients. " ) ,
2012-08-22 13:34:06 +00:00
' res_model ' : fields . char ( ' Destination Model ' , size = 64 ,
help = " Optional model, mostly used for needactions. " ) ,
2012-08-23 14:35:25 +00:00
' context ' : fields . char ( ' Context Value ' , size = 250 , required = True ,
help = " Context dictionary as Python expression, empty by default (Default: {} ) " ) ,
2011-08-04 08:54:55 +00:00
' params ' : fields . function ( _get_params , fnct_inv = _set_params ,
2012-01-04 13:30:27 +00:00
type = ' binary ' ,
2011-06-30 11:51:34 +00:00
string = " Supplementary arguments " ,
help = " Arguments sent to the client along with "
" the view tag " ) ,
2011-08-04 08:54:55 +00:00
' params_store ' : fields . binary ( " Params storage " , readonly = True )
2011-06-30 11:51:34 +00:00
}
_defaults = {
' type ' : ' ir.actions.client ' ,
2012-08-23 14:35:25 +00:00
' context ' : ' {} ' ,
2008-10-08 14:12:08 +00:00
2011-06-30 11:51:34 +00:00
}
act_client ( )
2008-10-08 14:12:08 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: