merge
bzr revid: nch@tinyerp.com-20081120072929-ogj8bui2nj0gasy9 bzr revid: nch@tinyerp.com-20081128061150-e0espfgn3ipvp2pl
This commit is contained in:
+48
-30
@@ -45,6 +45,9 @@ sys.path.insert(1, _ad)
|
||||
if ad != _ad:
|
||||
sys.path.insert(1, ad)
|
||||
|
||||
# Modules already loaded
|
||||
loaded = []
|
||||
|
||||
class Graph(dict):
|
||||
|
||||
def addNode(self, name, deps):
|
||||
@@ -152,12 +155,15 @@ def get_module_resource(module, *args):
|
||||
def get_modules():
|
||||
"""Returns the list of module names
|
||||
"""
|
||||
def listdir(dir):
|
||||
def clean(name):
|
||||
name = os.path.basename(name)
|
||||
if name[-4:] == '.zip':
|
||||
name = name[:-4]
|
||||
return name
|
||||
return map(clean, os.listdir(dir))
|
||||
|
||||
module_list = os.listdir(ad)
|
||||
module_names = [os.path.basename(m) for m in module_list]
|
||||
module_list += [m for m in os.listdir(_ad) if m not in module_names]
|
||||
|
||||
return module_list
|
||||
return list(set(listdir(ad) + listdir(_ad)))
|
||||
|
||||
def create_graph(module_list, force=None):
|
||||
if not force:
|
||||
@@ -166,8 +172,6 @@ def create_graph(module_list, force=None):
|
||||
packages = []
|
||||
|
||||
for module in module_list:
|
||||
if module[-4:]=='.zip':
|
||||
module = module[:-4]
|
||||
try:
|
||||
mod_path = get_module_path(module)
|
||||
if not mod_path:
|
||||
@@ -184,8 +188,9 @@ def create_graph(module_list, force=None):
|
||||
raise
|
||||
if info.get('installable', True):
|
||||
packages.append((module, info.get('depends', []), info))
|
||||
|
||||
current,later = Set([p for p, dep, data in packages]), Set()
|
||||
|
||||
dependencies = dict([(p, deps) for p, deps, data in packages])
|
||||
current, later = Set([p for p, dep, data in packages]), Set()
|
||||
while packages and current > later:
|
||||
package, deps, datas = packages[0]
|
||||
|
||||
@@ -206,9 +211,10 @@ def create_graph(module_list, force=None):
|
||||
later.add(package)
|
||||
packages.append((package, deps, datas))
|
||||
packages.pop(0)
|
||||
|
||||
|
||||
for package in later:
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'addon:%s:Unmet dependency' % package)
|
||||
unmet_deps = filter(lambda p: p not in graph, dependencies[package])
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'addon:%s:Unmet dependencies: %s' % (package, ', '.join(unmet_deps)))
|
||||
|
||||
return graph
|
||||
|
||||
@@ -221,6 +227,36 @@ def init_module_objects(cr, module_name, obj_list):
|
||||
obj._auto_init(cr, {'module': module_name})
|
||||
cr.commit()
|
||||
|
||||
#
|
||||
# Register module named m, if not already registered
|
||||
#
|
||||
def register_class(m):
|
||||
global loaded
|
||||
if m in loaded:
|
||||
return
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon:%s:registering classes' % m)
|
||||
sys.stdout.flush()
|
||||
loaded.append(m)
|
||||
mod_path = get_module_path(m)
|
||||
if not os.path.isfile(mod_path+'.zip'):
|
||||
imp.load_module(m, *imp.find_module(m))
|
||||
else:
|
||||
import zipimport
|
||||
try:
|
||||
zimp = zipimport.zipimporter(mod_path+'.zip')
|
||||
zimp.load_module(m)
|
||||
except zipimport.ZipImportError:
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'Couldn\'t find module %s' % m)
|
||||
|
||||
def register_classes():
|
||||
return
|
||||
module_list = get_modules()
|
||||
for package in create_graph(module_list):
|
||||
m = package.name
|
||||
register_class(m)
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon:%s:registering classes' % m)
|
||||
sys.stdout.flush()
|
||||
|
||||
def load_module_graph(cr, graph, status=None, **kwargs):
|
||||
# **kwargs is passed directly to convert_xml_import
|
||||
if not status:
|
||||
@@ -232,6 +268,7 @@ def load_module_graph(cr, graph, status=None, **kwargs):
|
||||
for package in graph:
|
||||
status['progress'] = (float(statusi)+0.1)/len(graph)
|
||||
m = package.name
|
||||
register_class(m)
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon:%s' % m)
|
||||
sys.stdout.flush()
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
@@ -298,25 +335,6 @@ def load_module_graph(cr, graph, status=None, **kwargs):
|
||||
pool.get('ir.model.data')._process_end(cr, 1, package_todo)
|
||||
cr.commit()
|
||||
|
||||
def register_classes():
|
||||
module_list = get_modules()
|
||||
for package in create_graph(module_list):
|
||||
m = package.name
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'addon:%s:registering classes' % m)
|
||||
sys.stdout.flush()
|
||||
|
||||
mod_path = get_module_path(m)
|
||||
if not os.path.isfile(mod_path+'.zip'):
|
||||
# XXX must restrict to only addons paths
|
||||
imp.load_module(m, *imp.find_module(m))
|
||||
else:
|
||||
import zipimport
|
||||
try:
|
||||
zimp = zipimport.zipimporter(mod_path+'.zip')
|
||||
zimp.load_module(m)
|
||||
except zipimport.ZipImportError:
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'Couldn\'t find module %s' % m)
|
||||
|
||||
def load_modules(db, force_demo=False, status=None, update_module=False):
|
||||
if not status:
|
||||
status={}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# $Id$
|
||||
#
|
||||
@@ -23,7 +23,7 @@
|
||||
import ir
|
||||
import module
|
||||
import res
|
||||
|
||||
import maintenance
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# $Id$
|
||||
#
|
||||
@@ -32,6 +32,7 @@
|
||||
"base_menu.xml",
|
||||
"security/base_security.xml",
|
||||
"res/res_security.xml",
|
||||
"maintenance/maintenance_security.xml",
|
||||
],
|
||||
"demo_xml" : [
|
||||
"base_demo.xml",
|
||||
@@ -43,9 +44,9 @@
|
||||
"ir/wizard/wizard_menu_view.xml",
|
||||
"ir/ir.xml",
|
||||
"ir/workflow/workflow_view.xml",
|
||||
"module/module_data.xml",
|
||||
"module/module_wizard.xml",
|
||||
"module/module_view.xml",
|
||||
"module/module_data.xml",
|
||||
"module/module_report.xml",
|
||||
"res/res_request_view.xml",
|
||||
"res/res_lang_view.xml",
|
||||
@@ -59,6 +60,7 @@
|
||||
"res/partner/partner_data.xml",
|
||||
"res/ir_property_view.xml",
|
||||
"security/base_security.xml",
|
||||
"maintenance/maintenance_view.xml",
|
||||
"security/ir.model.access.csv",
|
||||
],
|
||||
"active": True,
|
||||
|
||||
@@ -27,6 +27,7 @@ CREATE TABLE ir_model (
|
||||
id serial,
|
||||
model varchar(64) DEFAULT ''::varchar NOT NULL,
|
||||
name varchar(64),
|
||||
state varchar(16),
|
||||
info text,
|
||||
primary key(id)
|
||||
);
|
||||
|
||||
@@ -220,10 +220,15 @@
|
||||
<field name="name">Costa Rica</field>
|
||||
<field name="code">cr</field>
|
||||
</record>
|
||||
<record id="cs" model="res.country">
|
||||
<field name="name">Serbia and Montenegro</field>
|
||||
<field name="code">cs</field>
|
||||
<record id="rs" model="res.country">
|
||||
<field name="name">Serbia</field>
|
||||
<field name="code">rs</field>
|
||||
</record>
|
||||
<record id="me" model="res.country">
|
||||
<field name="name">Montenegro</field>
|
||||
<field name="code">me</field>
|
||||
</record>
|
||||
|
||||
<record id="cu" model="res.country">
|
||||
<field name="name">Cuba</field>
|
||||
<field name="code">cu</field>
|
||||
|
||||
+212
-271
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1134
-1111
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+913
-1017
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1121
-1092
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+965
-962
File diff suppressed because it is too large
Load Diff
+387
-433
File diff suppressed because it is too large
Load Diff
+893
-884
File diff suppressed because it is too large
Load Diff
+1041
-1029
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -70,9 +70,26 @@
|
||||
<field name="number_increment"/>
|
||||
<field name="number_next"/>
|
||||
<separator colspan="4" string="Legend (for prefix, suffix)"/>
|
||||
<label colspan="4" string="Year: %%(year)s"/>
|
||||
<label colspan="4" string="Month: %%(month)s"/>
|
||||
<label colspan="4" string="Day: %%(day)s"/>
|
||||
<group col="8" colspan="4">
|
||||
<group>
|
||||
<label colspan="4" string="Year with century: %%(year)s"/>
|
||||
<label colspan="4" string="Year without century: %%(y)s"/>
|
||||
<label colspan="4" string="Month: %%(month)s"/>
|
||||
<label colspan="4" string="Day: %%(day)s"/>
|
||||
</group>
|
||||
<group>
|
||||
<label colspan="4" string="Day of the year: %%(doy)s"/>
|
||||
<label colspan="4" string="Week of the year: %%(woy)s"/>
|
||||
<label colspan="4" string="Day of the week (0:Monday): %%(weekday)s"/>
|
||||
</group>
|
||||
<group>
|
||||
<label colspan="4" string="Hour 00->24: %%(h24)s"/>
|
||||
<label colspan="4" string="Hour 00->12: %%(h12)s"/>
|
||||
<label colspan="4" string="Minute: %%(min)s"/>
|
||||
<label colspan="4" string="Seconde: %%(sec)s"/>
|
||||
</group>
|
||||
</group>
|
||||
<separator colspan="4" string=""/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
@@ -487,8 +504,8 @@
|
||||
<form string="Attachments">
|
||||
<group colspan="4" col="6">
|
||||
<field name="name" select="1" />
|
||||
<field name="create_uid" select="1"/>
|
||||
<field name="create_date" select="1"/>
|
||||
<field name="create_uid" select="2"/>
|
||||
<field name="create_date" select="2"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Attachment">
|
||||
@@ -499,7 +516,7 @@
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Attached To" colspan="2"/>
|
||||
<field name="res_model" select="1"/>
|
||||
<field name="res_model" select="2"/>
|
||||
<field name="res_id"/>
|
||||
</group>
|
||||
<separator string="Preview" colspan="4"/>
|
||||
@@ -1143,7 +1160,7 @@
|
||||
<field name="sms" colspan="4" attrs="{'readonly':[('state','=','python'), ('state','=','email'), ('state','=','dummy'),('state','=','trigger'), ('state','=','object_create'), ('state','=','object_write'), ('state','=','client_action'), ('state','=','other')]}"/>
|
||||
<field name="message" select="2" colspan="4" attrs="{'readonly':[('state','=','python'), ('state','=','dummy'),('state','=','trigger'), ('state','=','object_create'), ('state','=','object_write'), ('state','=','sms'), ('state','=','client_action'), ('state','=','other')]}" />
|
||||
<newline/>
|
||||
<label colspan="4" string="Access all the fields related to the current object easily just by defining name of the attribute, i.e. [[partner_id.name]] for Invoice Object"/>
|
||||
<label colspan="4" string="Access all the fields related to the current object using expression in double brackets, i.e. [[ object.partner_id.name ]]" align="0.0"/>
|
||||
</page>
|
||||
|
||||
<page string="Create / Write" attrs="{'invisible':[('state','=','python'),('state','=','dummy'),('state','=','trigger'), ('state','=','sms'), ('state','=','email'), ('state','=','client_action'), ('state','=','other')]}">
|
||||
@@ -1162,6 +1179,7 @@
|
||||
<field name="value" colsapan="4"/>
|
||||
</form>
|
||||
</field>
|
||||
<label colspan="4" string="If you use a formula type, use a python expression using the variable 'object'." align="0.0"/>
|
||||
</page>
|
||||
|
||||
<page string="Other Actions" attrs="{'invisible':[('state','!=','other')]}">
|
||||
@@ -1272,7 +1290,7 @@
|
||||
<separator colspan="4" string=""/>
|
||||
<label string="" colspan="2"/>
|
||||
<group colspan="2" col="2">
|
||||
<button icon="gtk-cancel" special="cancel" string="Skip Step"/>
|
||||
<button icon="gtk-cancel" name="button_skip" string="Skip Step" type="object"/>
|
||||
<button icon="gtk-go-forward" name="button_continue" string="Continue" type="object"/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# $Id$
|
||||
#
|
||||
@@ -438,26 +438,12 @@ class actions_server(osv.osv):
|
||||
def merge_message(self, cr, uid, keystr, action, context):
|
||||
logger = netsvc.Logger()
|
||||
def merge(match):
|
||||
|
||||
obj_pool = self.pool.get(action.model_id.model)
|
||||
id = context.get('active_id')
|
||||
obj = obj_pool.browse(cr, uid, id)
|
||||
return eval(match[2:-2], {'object':obj, 'context': context,'time':time})
|
||||
|
||||
field = match.group()
|
||||
field = field.replace('[','')
|
||||
field = field.replace(']','')
|
||||
field = field.strip()
|
||||
|
||||
fields = field.split('.')
|
||||
for field in fields:
|
||||
try:
|
||||
obj = getattr(obj, field)
|
||||
except Exception,e :
|
||||
logger.notifyChannel('Workflow', netsvc.LOG_ERROR, 'Failed to parse : %s' % (match.group()))
|
||||
|
||||
return str(obj)
|
||||
|
||||
com = re.compile('\[\[(.+?)\]\]')
|
||||
com = re.compile('(\[\[.+?\]\])')
|
||||
message = com.sub(merge, keystr)
|
||||
return message
|
||||
|
||||
@@ -490,9 +476,7 @@ class actions_server(osv.osv):
|
||||
address = self.get_field_value(cr, uid, action, context)
|
||||
if not address:
|
||||
raise osv.except_osv(_('Error'), _("Please specify the Partner Email address !"))
|
||||
|
||||
body = self.merge_message(cr, uid, str(action.message), action, context)
|
||||
|
||||
if tools.email_send_attach(user, address, subject, body, debug=False) == True:
|
||||
logger.notifyChannel('email', netsvc.LOG_INFO, 'Email successfully send to : %s' % (address))
|
||||
else:
|
||||
@@ -537,8 +521,9 @@ class actions_server(osv.osv):
|
||||
for exp in action.fields_lines:
|
||||
euq = exp.value
|
||||
if exp.type == 'equation':
|
||||
expr = self.merge_message(cr, uid, euq, action, context)
|
||||
expr = eval(expr)
|
||||
obj_pool = self.pool.get(action.model_id.model)
|
||||
obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
|
||||
expr = eval(euq, {'context':context, 'object': obj})
|
||||
else:
|
||||
expr = exp.value
|
||||
res[exp.col1.name] = expr
|
||||
@@ -550,8 +535,9 @@ class actions_server(osv.osv):
|
||||
for exp in action.fields_lines:
|
||||
euq = exp.value
|
||||
if exp.type == 'equation':
|
||||
expr = self.merge_message(cr, uid, euq, action, context)
|
||||
expr = eval(expr)
|
||||
obj_pool = self.pool.get(action.model_id.model)
|
||||
obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
|
||||
expr = eval(euq, {'context':context, 'object': obj})
|
||||
else:
|
||||
expr = exp.value
|
||||
res[exp.col1.name] = expr
|
||||
@@ -588,26 +574,26 @@ act_window_close()
|
||||
# - if start_type='auto', it will be start on auto starting from start date, and stop on stop date
|
||||
# - if start_type="manual", it will start and stop on manually
|
||||
class ir_actions_todo(osv.osv):
|
||||
_name = 'ir.actions.todo'
|
||||
_name = 'ir.actions.todo'
|
||||
_columns={
|
||||
'name':fields.char('Name',size=64,required=True, select=True),
|
||||
'note':fields.text('Text'),
|
||||
'start_date': fields.datetime('Start Date'),
|
||||
'end_date': fields.datetime('End Date'),
|
||||
'start_date': fields.datetime('Start Date'),
|
||||
'end_date': fields.datetime('End Date'),
|
||||
'action_id':fields.many2one('ir.actions.act_window', 'Action', select=True,required=True, ondelete='cascade'),
|
||||
'sequence':fields.integer('Sequence'),
|
||||
'active': fields.boolean('Active'),
|
||||
'type':fields.selection([('configure', 'Configure'),('service', 'Service'),('other','Other')], string='Type', required=True),
|
||||
'start_on':fields.selection([('at_once', 'At Once'),('auto', 'Auto'),('manual','Manual')], string='Start On'),
|
||||
'groups_id': fields.many2many('res.groups', 'res_groups_act_todo_rel', 'act_todo_id', 'group_id', 'Groups'),
|
||||
'users_id': fields.many2many('res.users', 'res_users_act_todo_rel', 'act_todo_id', 'user_id', 'Users'),
|
||||
'active': fields.boolean('Active'),
|
||||
'type':fields.selection([('configure', 'Configure'),('service', 'Service'),('other','Other')], string='Type', required=True),
|
||||
'start_on':fields.selection([('at_once', 'At Once'),('auto', 'Auto'),('manual','Manual')], string='Start On'),
|
||||
'groups_id': fields.many2many('res.groups', 'res_groups_act_todo_rel', 'act_todo_id', 'group_id', 'Groups'),
|
||||
'users_id': fields.many2many('res.users', 'res_users_act_todo_rel', 'act_todo_id', 'user_id', 'Users'),
|
||||
'state':fields.selection([('open', 'Not Started'),('done', 'Done'),('skip','Skipped'),('cancel','Cancel')], string='State', required=True)
|
||||
}
|
||||
_defaults={
|
||||
'state': lambda *a: 'open',
|
||||
'sequence': lambda *a: 10,
|
||||
'active':lambda *a:True,
|
||||
'type':lambda *a:'configure'
|
||||
'active':lambda *a:True,
|
||||
'type':lambda *a:'configure'
|
||||
}
|
||||
_order="sequence"
|
||||
ir_actions_todo()
|
||||
@@ -651,6 +637,21 @@ class ir_actions_configuration_wizard(osv.osv_memory):
|
||||
'item_id':_get_action,
|
||||
'name':_get_action_name,
|
||||
}
|
||||
def button_next(self,cr,uid,ids,context=None):
|
||||
user_action=self.pool.get('res.users').browse(cr,uid,uid)
|
||||
act_obj=self.pool.get(user_action.menu_id.type)
|
||||
action_ids=act_obj.search(cr,uid,[('name','=',user_action.menu_id.name)])
|
||||
action_open=act_obj.browse(cr,uid,action_ids)[0]
|
||||
if context.get('menu',False):
|
||||
return{
|
||||
'view_type': action_open.view_type,
|
||||
'view_id':action_open.view_id and [action_open.view_id.id] or False,
|
||||
'res_model': action_open.res_model,
|
||||
'type': action_open.type,
|
||||
'domain':action_open.domain
|
||||
}
|
||||
return {'type':'ir.actions.act_window_close'}
|
||||
|
||||
def button_skip(self,cr,uid,ids,context=None):
|
||||
item_obj = self.pool.get('ir.actions.todo')
|
||||
item_id=self.read(cr,uid,ids)[0]['item_id']
|
||||
@@ -666,7 +667,7 @@ class ir_actions_configuration_wizard(osv.osv_memory):
|
||||
'type': 'ir.actions.act_window',
|
||||
'target':'new',
|
||||
}
|
||||
return {'type':'ir.actions.act_window_close'}
|
||||
return self.button_next(cr, uid, ids, context)
|
||||
|
||||
def button_continue(self, cr, uid, ids, context=None):
|
||||
item_obj = self.pool.get('ir.actions.todo')
|
||||
@@ -684,19 +685,7 @@ class ir_actions_configuration_wizard(osv.osv_memory):
|
||||
'type': item.action_id.type,
|
||||
'target':item.action_id.target,
|
||||
}
|
||||
user_action=self.pool.get('res.users').browse(cr,uid,uid)
|
||||
act_obj=self.pool.get(user_action.menu_id.type)
|
||||
action_ids=act_obj.search(cr,uid,[('name','=',user_action.menu_id.name)])
|
||||
action_open=act_obj.browse(cr,uid,action_ids)[0]
|
||||
if context.get('menu',False):
|
||||
return{
|
||||
'view_type': action_open.view_type,
|
||||
'view_id':action_open.view_id and [action_open.view_id.id] or False,
|
||||
'res_model': action_open.res_model,
|
||||
'type': action_open.type,
|
||||
'domain':action_open.domain
|
||||
}
|
||||
return {'type':'ir.actions.act_window_close' }
|
||||
return self.button_next(cr, uid, ids, context)
|
||||
ir_actions_configuration_wizard()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -27,6 +27,7 @@ from osv.orm import except_orm, browse_record
|
||||
|
||||
import time
|
||||
import tools
|
||||
from tools import config
|
||||
import pooler
|
||||
|
||||
def _get_fields_type(self, cr, uid, context=None):
|
||||
@@ -74,7 +75,10 @@ class ir_model(osv.osv):
|
||||
vals['state']='manual'
|
||||
res = super(ir_model,self).create(cr, user, vals, context)
|
||||
if vals.get('state','base')=='manual':
|
||||
pooler.restart_pool(cr.dbname)
|
||||
self.instanciate(cr, user, vals['model'], context)
|
||||
self.pool.get(vals['model']).__init__(self.pool, cr)
|
||||
self.pool.get(vals['model'])._auto_init(cr,{})
|
||||
#pooler.restart_pool(cr.dbname)
|
||||
return res
|
||||
|
||||
def instanciate(self, cr, user, model, context={}):
|
||||
@@ -83,10 +87,7 @@ class ir_model(osv.osv):
|
||||
x_custom_model._name = model
|
||||
x_custom_model._module = False
|
||||
x_custom_model.createInstance(self.pool, '', cr)
|
||||
if 'x_name' in x_custom_model._columns:
|
||||
x_custom_model._rec_name = 'x_name'
|
||||
else:
|
||||
x_custom_model._rec_name = x_custom_model._columns.keys()[0]
|
||||
x_custom_model._rec_name = 'x_name'
|
||||
ir_model()
|
||||
|
||||
|
||||
@@ -561,18 +562,19 @@ class ir_model_data(osv.osv):
|
||||
wf_service.trg_write(uid, model, id, cr)
|
||||
|
||||
cr.commit()
|
||||
for (model,id) in self.unlink_mark.keys():
|
||||
if self.pool.get(model):
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'Deleting %s@%s' % (id, model))
|
||||
try:
|
||||
self.pool.get(model).unlink(cr, uid, [id])
|
||||
if self.unlink_mark[(model,id)]:
|
||||
self.unlink(cr, uid, [self.unlink_mark[(model,id)]])
|
||||
cr.execute('DELETE FROM ir_values WHERE value=%s', (model+','+str(id),))
|
||||
cr.commit()
|
||||
except:
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'Could not delete id: %d of model %s\tThere should be some relation that points to this resource\tYou should manually fix this and restart --update=module' % (id, model))
|
||||
if not config.get('import_partial', False):
|
||||
for (model,id) in self.unlink_mark.keys():
|
||||
if self.pool.get(model):
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'Deleting %s@%s' % (id, model))
|
||||
try:
|
||||
self.pool.get(model).unlink(cr, uid, [id])
|
||||
if self.unlink_mark[(model,id)]:
|
||||
self.unlink(cr, uid, [self.unlink_mark[(model,id)]])
|
||||
cr.execute('DELETE FROM ir_values WHERE value=%s', (model+','+str(id),))
|
||||
cr.commit()
|
||||
except:
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'Could not delete id: %d of model %s\tThere should be some relation that points to this resource\tYou should manually fix this and restart --update=module' % (id, model))
|
||||
return True
|
||||
ir_model_data()
|
||||
|
||||
|
||||
@@ -55,7 +55,19 @@ class ir_sequence(osv.osv):
|
||||
}
|
||||
|
||||
def _process(self, s):
|
||||
return (s or '') % {'year':time.strftime('%Y'), 'month': time.strftime('%m'), 'day':time.strftime('%d')}
|
||||
return (s or '') % {
|
||||
'year':time.strftime('%Y'),
|
||||
'month': time.strftime('%m'),
|
||||
'day':time.strftime('%d'),
|
||||
'y': time.strftime('%y'),
|
||||
'doy': time.strftime('%j'),
|
||||
'woy': time.strftime('%W'),
|
||||
'weekday': time.strftime('%w'),
|
||||
'h24': time.strftime('%H'),
|
||||
'h12': time.strftime('%I'),
|
||||
'min': time.strftime('%M'),
|
||||
'sec': time.strftime('%S'),
|
||||
}
|
||||
|
||||
def get_id(self, cr, uid, sequence_id, test='id=%d'):
|
||||
cr.execute('select id,number_next,number_increment,prefix,suffix,padding from ir_sequence where '+test+' and active=True FOR UPDATE', (sequence_id,))
|
||||
|
||||
@@ -48,7 +48,7 @@ class ir_translation(osv.osv, Cacheable):
|
||||
lang_ids = lang_obj.search(cr, uid, [('translatable', '=', True)],
|
||||
context=context)
|
||||
langs = lang_obj.browse(cr, uid, lang_ids, context=context)
|
||||
res = [(lang.code, lang.name) for lang in langs]
|
||||
res = [(lang.code, unicode(lang.name,'utf-8')) for lang in langs]
|
||||
for lang_dict in tools.scan_languages():
|
||||
if lang_dict not in res:
|
||||
res.append(lang_dict)
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
</field>
|
||||
<label colspan="2" string=""/>
|
||||
<group col="2" colspan="2">
|
||||
<button special="cancel" string="Cancel"/>
|
||||
<button name="menu_create" string="Create Menu" type="object"/>
|
||||
<button special="cancel" string="Cancel" icon="gtk-cancel"/>
|
||||
<button name="menu_create" string="Create Menu" type="object" icon="gtk-ok"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
|
||||
@@ -38,7 +38,7 @@ def graph_get(cr, graph, wkf_id, nested=False, workitem={}):
|
||||
if n['subflow_id'] and nested:
|
||||
cr.execute('select * from wkf where id=%d', (n['subflow_id'],))
|
||||
wkfinfo = cr.dictfetchone()
|
||||
graph2 = pydot.Cluster('subflow'+str(n['subflow_id']), fontsize='12', label = "Subflow: "+n['name']+'\\nOSV: '+wkfinfo['osv'])
|
||||
graph2 = pydot.Cluster('subflow'+str(n['subflow_id']), fontsize='12', label = """\"Subflow: %s\\nOSV: %s\"""" % ( n['name'], wkfinfo['osv']) )
|
||||
(s1,s2) = graph_get(cr, graph2, n['subflow_id'], nested,workitem)
|
||||
graph.add_subgraph(graph2)
|
||||
actfrom[n['id']] = s2
|
||||
@@ -143,12 +143,9 @@ showpage'''
|
||||
showpage'''
|
||||
else:
|
||||
inst_id = inst_id[0]
|
||||
graph = pydot.Dot(fontsize='16', label="""\\\n\\nWorkflow: %s\\n OSV: %s""" % (wkfinfo['name'],wkfinfo['osv']))
|
||||
graph.set('size', '10.7,7.3')
|
||||
graph.set('center', '1')
|
||||
graph.set('ratio', 'auto')
|
||||
graph.set('rotate', '90')
|
||||
graph.set('rankdir', 'LR')
|
||||
graph = pydot.Dot(fontsize='16', label="""\\\n\\nWorkflow: %s\\n OSV: %s""" % (wkfinfo['name'],wkfinfo['osv']),
|
||||
size='10.7, 7.3', center='1', ratio='auto', rotate='90', rankdir='LR'
|
||||
)
|
||||
graph_instance_get(cr, graph, inst_id, data.get('nested', False))
|
||||
ps_string = graph.create(prog='dot', format='ps')
|
||||
except Exception, e:
|
||||
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2004-2008 Tiny SPRL (http://tiny.be) All Rights Reserved.
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# WARNING: This program as such is intended to be used by professional
|
||||
# programmers who take the whole responsability of assessing all potential
|
||||
# consequences resulting from its eventual inadequacies and bugs
|
||||
# End users who are looking for a ready-to-use solution with commercial
|
||||
# garantees and support are strongly adviced to contract a Free Software
|
||||
# Service Company
|
||||
#
|
||||
# This program is Free Software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
###############################################################################
|
||||
|
||||
import maintenance
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
Executable
+111
@@ -0,0 +1,111 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2004-2008 TINY SPRL. (http://tiny.be) All Rights Reserved.
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# WARNING: This program as such is intended to be used by professional
|
||||
# programmers who take the whole responsability of assessing all potential
|
||||
# consequences resulting from its eventual inadequacies and bugs
|
||||
# End users who are looking for a ready-to-use solution with commercial
|
||||
# garantees and support are strongly adviced to contract a Free Software
|
||||
# Service Company
|
||||
#
|
||||
# This program is Free Software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import osv, fields
|
||||
import pooler
|
||||
import time
|
||||
import math
|
||||
|
||||
from tools import config
|
||||
import xmlrpclib
|
||||
|
||||
class maintenance_contract(osv.osv):
|
||||
_name = "maintenance.contract"
|
||||
_description = "Maintenance Contract"
|
||||
_columns = {
|
||||
'name' : fields.char('Contract ID', size=256, required=True),
|
||||
'password' : fields.char('Password', size=64, invisible=True, required=True),
|
||||
'date_start' : fields.date('Starting Date', readonly=True),
|
||||
'date_stop' : fields.date('Ending Date', readonly=True),
|
||||
'modules': fields.text('Covered Modules')
|
||||
}
|
||||
_defaults = {
|
||||
'password' : lambda obj,cr,uid,context={} : '',
|
||||
}
|
||||
def _test_maintenance(self, cr, uid, ids, context):
|
||||
remote_db='trunk'
|
||||
remote_server='localhost'
|
||||
port=8069
|
||||
module_obj=self.pool.get('ir.module.module')
|
||||
contract_obj=self.pool.get('maintenance.contract')
|
||||
module_ids=module_obj.search(cr, uid, [('state','=','installed')])
|
||||
modules=module_obj.read(cr, uid, module_ids, ['name','installed_version'])
|
||||
contract_obj=contract_obj.read(cr, uid, ids[0])
|
||||
local_url = 'http://%s:%d/xmlrpc/common'%(remote_server,port)
|
||||
rpc = xmlrpclib.ServerProxy(local_url)
|
||||
ruid = rpc.login(remote_db, 'admin', 'admin')
|
||||
local_url = 'http://%s:%d/xmlrpc/object'%(remote_server,port)
|
||||
rrpc = xmlrpclib.ServerProxy(local_url)
|
||||
try:
|
||||
result=rrpc.execute(remote_db, ruid, 'admin', 'maintenance.maintenance', 'check_contract' , modules,contract_obj)
|
||||
except:
|
||||
raise osv.except_osv(_('Maintenance Error !'),('''Module Maintenance_Editor is not installed at server : %s Database : %s'''%(remote_server,remote_db)))
|
||||
if context.get('active_id',False):
|
||||
if result['status']=='ko':
|
||||
raise osv.except_osv(_('Maintenance Error !'),('''Maintenance Contract
|
||||
-----------------------------------------------------------
|
||||
You have no valid maintenance contract! If you are using
|
||||
Open ERP, it is highly suggested to take maintenance contract.
|
||||
The maintenance program offers you:
|
||||
* Migrations on new versions,
|
||||
* Bugfix guarantee,
|
||||
* Monthly announces of bugs,
|
||||
* Security alerts,
|
||||
* Access to the customer portal.
|
||||
* Check the maintenance contract (www.openerp.com)'''))
|
||||
elif result['status']=='partial':
|
||||
raise osv.except_osv(_('Maintenance Error !'),('''Maintenance Contract
|
||||
-----------------------------------------------------------
|
||||
You have a maintenance contract, But you installed modules those
|
||||
are not covered by your maintenance contract:
|
||||
'''+','.join(result['modules'])+'''
|
||||
It means we can not offer you the garantee of maintenance on
|
||||
your whole installation.
|
||||
The maintenance program includes:
|
||||
* Migrations on new versions,
|
||||
* Bugfix guarantee,
|
||||
* Monthly announces of bugs,
|
||||
* Security alerts,
|
||||
* Access to the customer portal.
|
||||
|
||||
To include these modules in your maintenance contract, you should
|
||||
extend your contract with the editor. We will review and validate
|
||||
your installed modules.
|
||||
|
||||
* Extend your maintenance to the modules you used.
|
||||
* Check your maintenance contract'''))
|
||||
else:
|
||||
raise osv.except_osv(_('Valid Maintenance Contract !'),('''Your Maintenance Contract is up to date'''))
|
||||
return result
|
||||
|
||||
maintenance_contract()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="0">
|
||||
|
||||
<record model="res.groups" id="group_maintenance_manager">
|
||||
<field name="name">Maintenance Manager</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.menu" id="menu_maintenance_contract">
|
||||
<field eval="[(6,0,[ref('group_maintenance_manager')])]" name="groups_id"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="maintenance_contract_tree_view" model="ir.ui.view">
|
||||
<field name="name">maintenance.contract.tree</field>
|
||||
<field name="model">maintenance.contract</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Maintenance Contract">
|
||||
<field name="name"/>
|
||||
<field name="date_start"/>
|
||||
<field name="date_stop"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="maintenance_contract_form_view" model="ir.ui.view">
|
||||
<field name="name">maintenance.contract.form</field>
|
||||
<field name="model">maintenance.contract</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Maintenance Contract">
|
||||
<separator string="Information" colspan="4"/>
|
||||
<field name="name" select="1"/>
|
||||
<field name="password" password="True"/>
|
||||
<field name="date_start" select="1"/>
|
||||
<field name="date_stop" select="1"/>
|
||||
<button name="_test_maintenance" string="Check Maintenance" type="object" colspan="2"/>
|
||||
<separator string="Covered Modules" colspan="4"/>
|
||||
<field name="modules" nolabel="1" colspan="4"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_maintenance_contract_form" model="ir.actions.act_window">
|
||||
<field name="name">Your Maintenance Contracts</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">maintenance.contract</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
<record id="action_maintenance_contract_form" model="ir.actions.act_window">
|
||||
<field name="name">Encode a New Maintenance Contract</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">maintenance.contract</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form,tree</field>
|
||||
</record>
|
||||
<menuitem
|
||||
name="Maintenance"
|
||||
id="maintenance"
|
||||
parent="base.menu_administration"/>
|
||||
|
||||
<menuitem
|
||||
action="action_maintenance_contract_form"
|
||||
id="menu_maintenance_contract"
|
||||
parent="maintenance"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -573,17 +573,6 @@ class module(osv.osv):
|
||||
categs = categs[1:]
|
||||
self.write(cr, uid, [id], {'category_id': p_id})
|
||||
|
||||
def action_install(self,cr,uid,ids,context=None):
|
||||
for module in self.browse(cr, uid, ids, context):
|
||||
if module.state <> 'uninstalled':
|
||||
continue
|
||||
self.write(cr , uid, [module.id] ,{'state' : 'to install'})
|
||||
self.download(cr, uid, [module.id], context=context)
|
||||
cr.execute("select m.id as id from ir_module_module_dependency d inner join ir_module_module m on (m.name=d.name) where d.module_id=%d and m.state='uninstalled'",(module.id,))
|
||||
dep_ids = map(lambda x:x[0],cr.fetchall())
|
||||
if len(dep_ids):
|
||||
self.action_install(cr,uid,dep_ids,context=context)
|
||||
|
||||
def update_translations(self, cr, uid, ids, filter_lang=None):
|
||||
logger = netsvc.Logger()
|
||||
|
||||
|
||||
@@ -7,5 +7,12 @@
|
||||
<field eval="False" name="active"/>
|
||||
<field eval="'href="([a-zA-Z0-9_]+)-('+version+'.(\\d+)((\\.\\d+)*)([a-z]?)((_(pre|p|beta|alpha|rc)\\d*)*)(-r(\\d+))?)(\.zip)"'" name="filter"/>
|
||||
</record>
|
||||
|
||||
<record id="ir_ui_view_sc_modules0" model="ir.ui.view_sc">
|
||||
<field name="name">Modules</field>
|
||||
<field name="resource">ir.ui.menu</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="res_id" ref="base.menu_module_tree"/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
<para style="P6">[[ module.description ]]</para>
|
||||
<para style="P6">[[ format(module.description or '') ]]</para>
|
||||
<section>
|
||||
<para style="Standard">[[ repeatIn(findobj(module.name) ,'object') ]]</para>
|
||||
<blockTable colWidths="510.0" repeatRows="1" style="Tableau3">
|
||||
@@ -144,14 +144,14 @@
|
||||
<td>
|
||||
<para style="P10">Object: [[ object.model ]]</para>
|
||||
<para style="P11">Description : [[ object.name ]]</para>
|
||||
<para style="P5">[[ objdoc(object.model) ]]</para>
|
||||
<para style="P5">[[ format(objdoc(object.model)) ]]</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
<blockTable colWidths="113.0,397.0" repeatRows="1" style="Tableau4">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P7">[[ repeatIn(findflds(object.model), 'field') ]] [[ field[0] ]]</para>
|
||||
<para style="P7">[[ repeatIn(findflds(object.model), 'field') ]] <i>[[ field[0] ]]</i></para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="P8">[[ field[1].get('string', 'Unknown') ]], [[ field[1]['type'] ]] [[field[1].get('required',False) and ', required']] [[field[1].get('readonly',False) and ', readonly']] </para>
|
||||
|
||||
@@ -37,12 +37,11 @@ class ir_module_reference_print(report_sxw.rml_parse):
|
||||
return modobj.__doc__
|
||||
|
||||
def _object_find(self, module):
|
||||
ids2 = self.pool.get('ir.model.data').search(self.cr, self.uid, [('module','=',module), ('model','=','ir.model')])
|
||||
ids = []
|
||||
for mod in self.pool.get('ir.model.data').browse(self.cr, self.uid, ids2):
|
||||
ids.append(mod.res_id)
|
||||
modobj = self.pool.get('ir.model')
|
||||
if module=='base':
|
||||
ids = modobj.search(self.cr, self.uid, [('model','=like','res%')])
|
||||
ids += modobj.search(self.cr, self.uid, [('model','=like','ir%')])
|
||||
else:
|
||||
ids = modobj.search(self.cr, self.uid, [('model','=like',module+'%')])
|
||||
return modobj.browse(self.cr, self.uid, ids)
|
||||
|
||||
def _fields_find(self, obj):
|
||||
|
||||
@@ -31,11 +31,14 @@ view_form="""<?xml version="1.0"?>
|
||||
<image name="gtk-dialog-info" colspan="2"/>
|
||||
<group colspan="2" col="4">
|
||||
<separator string="Import new language" colspan="4"/>
|
||||
<field name="name"/>
|
||||
<field name="name" width="200"/>
|
||||
<field name="code"/>
|
||||
<field name="data" colspan="3"/>
|
||||
<label string="You have to import a .CSV file wich is encoded in UTF-8.\nPlease check that the first line of your file is:" colspan="4" align="0.0"/>
|
||||
<field name="data" colspan="4"/>
|
||||
<label string="You have to import a .CSV file wich is encoded in UTF-8.\n
|
||||
Please check that the first line of your file is one of the following:" colspan="4" align="0.0"/>
|
||||
<label string="type,name,res_id,src,value" colspan="4"/>
|
||||
<label string="module,type,name,res_id,src,value" colspan="4"/>
|
||||
<label string="You can also import .po files." colspan="4" align="0.0"/>
|
||||
</group>
|
||||
</form>"""
|
||||
|
||||
@@ -54,7 +57,7 @@ class wizard_import_lang(wizard.interface):
|
||||
|
||||
# now we determine the file format
|
||||
fileobj.seek(0)
|
||||
first_line = fileobj.readline().strip()
|
||||
first_line = fileobj.readline().strip().replace('"', '').replace(' ', '')
|
||||
fileformat = first_line.endswith("type,name,res_id,src,value") and 'csv' or 'po'
|
||||
fileobj.seek(0)
|
||||
|
||||
|
||||
@@ -146,5 +146,99 @@ class wizard_info_get(wizard.interface):
|
||||
wizard_info_get('module.upgrade')
|
||||
|
||||
|
||||
class wizard_info_get_simple(wizard.interface):
|
||||
def _get_install(self, cr, uid, data, context):
|
||||
pool=pooler.get_pool(cr.dbname)
|
||||
mod_obj = pool.get('ir.module.module')
|
||||
ids = mod_obj.search(cr, uid, [
|
||||
('state', 'in', ['to upgrade', 'to remove', 'to install'])])
|
||||
res = mod_obj.read(cr, uid, ids, ['name','state'], context)
|
||||
url = mod_obj.download(cr, uid, ids, download=False, context=context)
|
||||
return {'module_info': '\n'.join(map(lambda x: x['name']+' : '+x['state'], res)),
|
||||
'module_download': '\n'.join(url)}
|
||||
|
||||
def _check_upgrade_module(self,cr,uid,data,context):
|
||||
db, pool = pooler.get_db_and_pool(cr.dbname)
|
||||
cr = db.cursor()
|
||||
mod_obj = pool.get('ir.module.module')
|
||||
ids = mod_obj.search(cr, uid, [
|
||||
('state', 'in', ['to upgrade', 'to remove', 'to install'])])
|
||||
if ids and len(ids):
|
||||
return 'next'
|
||||
else:
|
||||
return 'end'
|
||||
|
||||
def _upgrade_module(self, cr, uid, data, context):
|
||||
db, pool = pooler.get_db_and_pool(cr.dbname)
|
||||
cr = db.cursor()
|
||||
mod_obj = pool.get('ir.module.module')
|
||||
ids = mod_obj.search(cr, uid, [('state', 'in', ['to upgrade', 'to remove', 'to install'])])
|
||||
unmet_packages = []
|
||||
mod_dep_obj = pool.get('ir.module.module.dependency')
|
||||
for mod in mod_obj.browse(cr, uid, ids):
|
||||
depends_mod_ids = mod_dep_obj.search(cr, uid, [('module_id', '=', mod.id)])
|
||||
for dep_mod in mod_dep_obj.browse(cr, uid, depends_mod_ids):
|
||||
if dep_mod.state in ('unknown','uninstalled'):
|
||||
unmet_packages.append(dep_mod.name)
|
||||
if len(unmet_packages):
|
||||
raise wizard.except_wizard('Unmet dependency !', 'Following modules are uninstalled or unknown. \n\n'+'\n'.join(unmet_packages))
|
||||
mod_obj.download(cr, uid, ids, context=context)
|
||||
cr.commit()
|
||||
db, pool = pooler.restart_pool(cr.dbname, update_module=True)
|
||||
return {}
|
||||
|
||||
def _config(self, cr, uid, data, context=None):
|
||||
return {
|
||||
'view_type': 'form',
|
||||
"view_mode": 'form',
|
||||
'res_model': 'ir.actions.configuration.wizard',
|
||||
'type': 'ir.actions.act_window',
|
||||
'target':'new',
|
||||
}
|
||||
|
||||
states = {
|
||||
'init': {
|
||||
'actions': [],
|
||||
'result' : {'type': 'choice', 'next_state': _check_upgrade_module }
|
||||
},
|
||||
'next': {
|
||||
'actions': [_get_install],
|
||||
'result': {'type':'form', 'arch':view_form, 'fields': view_field,
|
||||
'state':[
|
||||
('end', 'Cancel', 'gtk-cancel'),
|
||||
('start', 'Start Upgrade', 'gtk-ok', True)
|
||||
]
|
||||
}
|
||||
},
|
||||
'start': {
|
||||
'actions': [_upgrade_module],
|
||||
'result': {'type':'form', 'arch':view_form_end, 'fields': {},
|
||||
'state':[
|
||||
('end', 'Close', 'gtk-close', True),
|
||||
('config', 'Start configuration', 'gtk-ok', True)
|
||||
]
|
||||
}
|
||||
},
|
||||
'end': {
|
||||
'actions': [],
|
||||
'result': {'type':'form', 'arch':view_form_end, 'fields': {},
|
||||
'state':[
|
||||
('end', 'Close', 'gtk-close', True),
|
||||
('config', 'Start configuration', 'gtk-ok', True)
|
||||
]
|
||||
}
|
||||
},
|
||||
'config':{
|
||||
'result': {
|
||||
'type': 'action',
|
||||
'action': _config,
|
||||
'state': 'end',
|
||||
},
|
||||
}
|
||||
}
|
||||
wizard_info_get_simple('module.upgrade.simple')
|
||||
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
||||
@@ -14,19 +14,21 @@
|
||||
|
||||
<xsl:template name="stylesheet">
|
||||
<paraStyle name="title" fontName="Helvetica-Bold" fontSize="22" alignment="center"/>
|
||||
|
||||
|
||||
<blockTableStyle id="products">
|
||||
<blockBackground colorName="grey" start="0,0" stop="-1,0"/>
|
||||
<!--<blockBackground colorName="grey" start="0,0" stop="-1,0"/> -->
|
||||
<lineStyle kind="LINEBELOW" colorName="#000000" start="0,0" stop="-1,0"/>
|
||||
<blockValign value="TOP"/>
|
||||
<blockAlignment value="RIGHT"/>
|
||||
<lineStyle kind="GRID" colorName="black"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,1" stop="-1,-1"/>
|
||||
<!-- <lineStyle kind="GRID" colorName="black"/> -->
|
||||
</blockTableStyle>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="story">
|
||||
<xsl:apply-templates select="report"/>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="report">
|
||||
<xsl:apply-templates select="config"/>
|
||||
<!--<setNextTemplate name="other_pages"/>-->
|
||||
@@ -36,7 +38,7 @@
|
||||
<xsl:value-of select="./config/tableSize"/>
|
||||
</xsl:attribute>
|
||||
</xsl:if>
|
||||
|
||||
|
||||
<xsl:apply-templates select="header"/>
|
||||
<xsl:apply-templates select="lines"/>
|
||||
</blockTable>
|
||||
@@ -53,8 +55,8 @@
|
||||
<tr>
|
||||
<xsl:for-each select="field">
|
||||
<td>
|
||||
<para>
|
||||
<xsl:value-of select="."/>
|
||||
<para><font fontName="Helvetica-Bold" fontSize="9">
|
||||
<xsl:value-of select="."/></font>
|
||||
</para>
|
||||
</td>
|
||||
</xsl:for-each>
|
||||
@@ -79,12 +81,16 @@
|
||||
<xsl:when test="@tree='yes'">
|
||||
<para>
|
||||
<xsl:attribute name="leftIndent"><xsl:value-of select="@space"/></xsl:attribute>
|
||||
<font fontName="Helvetica" fontSize="9">
|
||||
<xsl:value-of select="."/>
|
||||
</font>
|
||||
</para>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<para>
|
||||
<font fontName="Helvetica" fontSize="9">
|
||||
<xsl:value-of select="."/>
|
||||
</font>
|
||||
</para>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
<field name="supplier">1</field>
|
||||
</record>
|
||||
<record id="res_partner_sednacom" model="res.partner">
|
||||
<field name="website">http://www.syleam.fr</field>
|
||||
<field name="name">Syleam</field>
|
||||
<field eval="[(6, 0, [ref('res_partner_category_5')])]" name="category_id"/>
|
||||
</record>
|
||||
@@ -201,6 +202,16 @@
|
||||
<field name="type">default</field>
|
||||
<field name="partner_id" ref="res_partner_10"/>
|
||||
</record>
|
||||
<record id="res_partner_address_3000" model="res.partner.address">
|
||||
<field name="city">Champs sur Marne</field>
|
||||
<field name="name">Laith Jubair</field>
|
||||
<field name="zip">77420</field>
|
||||
<field model="res.country" name="country_id" search="[('name','=','France')]"/>
|
||||
<field name="email">info@axelor.com</field>
|
||||
<field name="phone">+33 1 64 61 04 01</field>
|
||||
<field name="street">12 rue Albert Einstein</field>
|
||||
<field name="partner_id" ref="res_partner_desertic_hispafuentes"/>
|
||||
</record>
|
||||
<record id="res_partner_address_3" model="res.partner.address">
|
||||
<field name="city">Louvain-la-Neuve</field>
|
||||
<field name="name">Thomas Passot</field>
|
||||
@@ -271,6 +282,18 @@
|
||||
<field name="type">default</field>
|
||||
<field name="partner_id" ref="res_partner_2"/>
|
||||
</record>
|
||||
<record id="res_partner_address_11" model="res.partner.address">
|
||||
<field name="city">Alencon</field>
|
||||
<field name="name">Sebastien LANGE</field>
|
||||
<field name="zip">61000</field>
|
||||
<field name="title">M.</field>
|
||||
<field name="email">contact@syleam.fr</field>
|
||||
<field name="street">1 place de l'Église</field>
|
||||
<field name="phone">+33 (0) 2 33 31 22 10</field>
|
||||
<field model="res.country" name="country_id" search="[('name','=','France')]"/>
|
||||
<field name="type">default</field>
|
||||
<field name="partner_id" ref="res_partner_sednacom"/>
|
||||
</record>
|
||||
<record id="res_partner_address_10" model="res.partner.address">
|
||||
<field name="city">Liege</field>
|
||||
<field name="name">Karine Lesbrouffe</field>
|
||||
|
||||
@@ -96,7 +96,7 @@ class users(osv.osv):
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=64, required=True, select=True),
|
||||
'login': fields.char('Login', size=64, required=True),
|
||||
'password': fields.char('Password', size=64, invisible=True),
|
||||
'password': fields.char('Password', size=64, invisible=True, help="Keep empty if you don't want the user to be able to connect on the system."),
|
||||
'signature': fields.text('Signature', size=64),
|
||||
'address_id': fields.many2one('res.partner.address', 'Address'),
|
||||
'active': fields.boolean('Active'),
|
||||
@@ -138,6 +138,10 @@ class users(osv.osv):
|
||||
ids = self.pool.get('ir.actions.act_window').search(cr, uid, [('usage','=','menu')])
|
||||
return ids and ids[0] or False
|
||||
|
||||
def _get_group(self,cr, uid, context={}):
|
||||
ids = self.pool.get('res.groups').search(cr, uid, [('name','=','Employee')])
|
||||
return ids or False
|
||||
|
||||
_defaults = {
|
||||
'password' : lambda obj,cr,uid,context={} : '',
|
||||
'context_lang': lambda *args: 'en_US',
|
||||
@@ -145,6 +149,7 @@ class users(osv.osv):
|
||||
'menu_id': _get_menu,
|
||||
'action_id': _get_menu,
|
||||
'company_id': _get_company,
|
||||
'groups_id': _get_group,
|
||||
}
|
||||
def company_get(self, cr, uid, uid2):
|
||||
company_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.id
|
||||
|
||||
@@ -127,3 +127,4 @@
|
||||
"access_res_config_view_all","res_config_view_all","model_res_config_view",,1,0,0,0
|
||||
"access_res_bank_group_partner_manager","res_bank_group_partner_manager","model_res_bank","group_partner_manager",1,1,1,1
|
||||
"access_res_bank_user","res_bank user","model_res_bank","group_user",1,0,0,0
|
||||
"access_maintenance_group_user","maintenance_contract group_user","model_maintenance_contract","group_maintenance_manager",1,1,1,1
|
||||
|
+22
-21
@@ -28,6 +28,7 @@ import SimpleXMLRPCServer, signal, sys, xmlrpclib
|
||||
import SocketServer
|
||||
import socket
|
||||
import logging
|
||||
import logging.handlers
|
||||
import os
|
||||
|
||||
_service = {}
|
||||
@@ -121,10 +122,15 @@ class Service(object):
|
||||
class LocalService(Service):
|
||||
def __init__(self, name):
|
||||
self.__name = name
|
||||
s = _service[name]
|
||||
self._service = s
|
||||
for m in s._method:
|
||||
setattr(self, m, s._method[m])
|
||||
try:
|
||||
s = _service[name]
|
||||
self._service = s
|
||||
for m in s._method:
|
||||
setattr(self, m, s._method[m])
|
||||
except KeyError, keyError:
|
||||
Logger().notifyChannel('module', LOG_ERROR, 'This service does not exists: %s' % (str(keyError),) )
|
||||
raise
|
||||
|
||||
|
||||
|
||||
class ServiceUnavailable(Exception):
|
||||
@@ -153,6 +159,9 @@ def init_logger():
|
||||
logf = config['logfile']
|
||||
# test if the directories exist, else create them
|
||||
try:
|
||||
dirname = os.path.dirname(logf)
|
||||
if not os.path.isdir(dirname):
|
||||
res = os.makedirs(dirname)
|
||||
handler = logging.handlers.TimedRotatingFileHandler(logf,'D',1,30)
|
||||
except:
|
||||
sys.stderr.write("ERROR: couldn't create the logfile directory\n")
|
||||
@@ -271,24 +280,19 @@ class GenericXMLRPCRequestHandler:
|
||||
raise xmlrpclib.Fault(s, tb_s)
|
||||
|
||||
|
||||
class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler,
|
||||
SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
|
||||
class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
|
||||
SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.rpc_paths = get_rpc_paths()
|
||||
|
||||
|
||||
class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn,
|
||||
SimpleXMLRPCServer.SimpleXMLRPCServer):
|
||||
class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer):
|
||||
|
||||
def server_bind(self):
|
||||
try:
|
||||
self.socket.setsockopt(socket.SOL_SOCKET,
|
||||
socket.SO_REUSEADDR, 1)
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self)
|
||||
except:
|
||||
sys.stderr.write("ERROR: address already in use\n")
|
||||
Logger().notifyChannel('init', LOG_ERROR, 'Address already in use')
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class HttpDaemon(threading.Thread):
|
||||
|
||||
def __init__(self, interface, port, secure=False):
|
||||
@@ -298,22 +302,19 @@ class HttpDaemon(threading.Thread):
|
||||
self.secure = secure
|
||||
if secure:
|
||||
from ssl import SecureXMLRPCServer
|
||||
class SecureXMLRPCRequestHandler(GenericXMLRPCRequestHandler,
|
||||
SecureXMLRPCServer.SecureXMLRPCRequestHandler):
|
||||
SecureXMLRPCServer.SecureXMLRPCRequestHandler.rpc_paths = get_rpc_paths()
|
||||
class SecureThreadedXMLRPCServer(SocketServer.ThreadingMixIn,
|
||||
SecureXMLRPCServer.SecureXMLRPCServer):
|
||||
|
||||
class SecureXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SecureXMLRPCServer.SecureXMLRPCRequestHandler):
|
||||
SecureXMLRPCServer.SecureXMLRPCRequestHandler.rpc_paths = get_rpc_paths()
|
||||
|
||||
class SecureThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SecureXMLRPCServer.SecureXMLRPCServer):
|
||||
def server_bind(self):
|
||||
try:
|
||||
self.socket.setsockopt(socket.SOL_SOCKET,
|
||||
socket.SO_REUSEADDR, 1)
|
||||
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
SecureXMLRPCServer.SecureXMLRPCServer.server_bind(self)
|
||||
except:
|
||||
sys.stderr.write("ERROR: address already in use\n")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
self.server = SecureThreadedXMLRPCServer((interface, port),
|
||||
SecureXMLRPCRequestHandler, 0)
|
||||
else:
|
||||
|
||||
@@ -81,8 +81,6 @@ dispatcher.monitor(signal.SIGINT)
|
||||
#---------------------------------------------------------------
|
||||
# connect to the database and initialize it with base if needed
|
||||
#---------------------------------------------------------------
|
||||
logger.notifyChannel("init", netsvc.LOG_INFO, 'connecting to database')
|
||||
|
||||
import psycopg
|
||||
import pooler
|
||||
|
||||
@@ -129,7 +127,6 @@ import osv, workflow, report, service
|
||||
#----------------------------------------------------------
|
||||
import addons
|
||||
|
||||
addons.register_classes()
|
||||
if tools.config['init'] or tools.config['update']:
|
||||
pooler.get_db_and_pool(tools.config['db_name'], update_module=True)
|
||||
|
||||
@@ -203,7 +200,7 @@ if tools.config['netrpc']:
|
||||
netinterface = tools.config["netinterface"]
|
||||
|
||||
tinySocket = netsvc.TinySocketServerThread(netinterface, netport, False)
|
||||
logger.notifyChannel("web-services", netsvc.LOG_INFO, "starting netrpc service, port "+str(netport))
|
||||
logger.notifyChannel("web-services", netsvc.LOG_INFO, "starting NET-RPC service, port "+str(netport))
|
||||
|
||||
|
||||
def handler(signum, frame):
|
||||
|
||||
+5
-4
@@ -1,7 +1,7 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# $Id$
|
||||
#
|
||||
@@ -160,7 +160,7 @@ class char(_column):
|
||||
u_symb = symb
|
||||
else:
|
||||
u_symb = unicode(symb)
|
||||
return u_symb.encode('utf8')[:self.size]
|
||||
return u_symb[:self.size].encode('utf8')
|
||||
|
||||
|
||||
class text(_column):
|
||||
@@ -678,7 +678,8 @@ class related(function):
|
||||
where += " %s.%s %s '%s' and" % (obj_child._table, self._arg[i], context[0][1], context[0][2])
|
||||
if field_detail[1] in ['integer', 'long', 'float','integer_big']:
|
||||
where += " %s.%s %s '%d' and" % (obj_child._table, self._arg[i], context[0][1], context[0][2])
|
||||
query += where.rstrip('and')
|
||||
if len(where)>10:
|
||||
query += where.rstrip('and')
|
||||
cr.execute(query)
|
||||
ids = []
|
||||
for id in cr.fetchall():
|
||||
@@ -707,7 +708,7 @@ class related(function):
|
||||
else:
|
||||
t_data = t_data[self.arg[i]]
|
||||
if type(t_data) == type(objlst[0]):
|
||||
res[data.id] = t_data.id
|
||||
res[data.id] = (t_data.id,t_data.name)
|
||||
else:
|
||||
res[data.id] = t_data
|
||||
return res
|
||||
|
||||
+62
-50
@@ -116,7 +116,7 @@ class browse_record(object):
|
||||
'''
|
||||
if not context:
|
||||
context = {}
|
||||
assert id, _('Wrong ID for the browse record, got %s, expected an integer.') % str(id)
|
||||
assert id and isinstance(id, (int, long,)), _('Wrong ID for the browse record, got %r, expected an integer.') % (id,)
|
||||
self._list_class = list_class or browse_record_list
|
||||
self._cr = cr
|
||||
self._uid = uid
|
||||
@@ -128,9 +128,12 @@ class browse_record(object):
|
||||
|
||||
cache.setdefault(table._name, {})
|
||||
self._data = cache[table._name]
|
||||
|
||||
if not id in self._data:
|
||||
self._data[id] = {'id': id}
|
||||
|
||||
self._cache = cache
|
||||
pass
|
||||
|
||||
def __getitem__(self, name):
|
||||
if name == 'id':
|
||||
@@ -183,7 +186,7 @@ class browse_record(object):
|
||||
if data[n]:
|
||||
obj = self._table.pool.get(f._obj)
|
||||
compids = False
|
||||
if not f._classic_write:
|
||||
if type(data[n]) in (type([]),type( (1,) )):
|
||||
ids2 = data[n][0]
|
||||
else:
|
||||
ids2 = data[n]
|
||||
@@ -297,17 +300,20 @@ class orm_template(object):
|
||||
_description = None
|
||||
_inherits = {}
|
||||
_table = None
|
||||
_invalids = set()
|
||||
|
||||
def _field_create(self, cr, context={}):
|
||||
cr.execute("SELECT id FROM ir_model_data WHERE name='%s'" % ('model_'+self._name.replace('.','_'),))
|
||||
cr.execute("SELECT id FROM ir_model WHERE model='%s'" % self._name)
|
||||
if not cr.rowcount:
|
||||
cr.execute('SELECT nextval(%s)', ('ir_model_id_seq',))
|
||||
id = cr.fetchone()[0]
|
||||
cr.execute("INSERT INTO ir_model (id,model, name, info) VALUES (%s, %s, %s, %s)", (id, self._name, self._description, self.__doc__))
|
||||
model_id = cr.fetchone()[0]
|
||||
cr.execute("INSERT INTO ir_model (id,model, name, info,state) VALUES (%s, %s, %s, %s,%s)", (model_id, self._name, self._description, self.__doc__, 'base'))
|
||||
if 'module' in context:
|
||||
cr.execute("INSERT INTO ir_model_data (name,date_init,date_update,module,model,res_id) VALUES (%s, now(), now(), %s, %s, %s)", \
|
||||
('model_'+self._name.replace('.','_'), context['module'], 'ir.model', id)
|
||||
('model_'+self._name.replace('.','_'), context['module'], 'ir.model', model_id)
|
||||
)
|
||||
else:
|
||||
model_id = cr.fetchone()[0]
|
||||
cr.commit()
|
||||
|
||||
cr.execute("SELECT * FROM ir_model_fields WHERE model=%s", (self._name,))
|
||||
@@ -315,9 +321,6 @@ class orm_template(object):
|
||||
for rec in cr.dictfetchall():
|
||||
cols[rec['name']] = rec
|
||||
|
||||
cr.execute("SELECT id FROM ir_model WHERE model='%s'" % self._name)
|
||||
model_id = cr.fetchone()[0]
|
||||
|
||||
for (k, f) in self._columns.items():
|
||||
vals = {
|
||||
'model_id': model_id,
|
||||
@@ -648,6 +651,9 @@ class orm_template(object):
|
||||
def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
|
||||
raise _('The read method is not implemented on this object !')
|
||||
|
||||
def get_invalid_fields(self,cr,uid):
|
||||
return list(self._invalids)
|
||||
|
||||
def _validate(self, cr, uid, ids, context=None):
|
||||
context = context or {}
|
||||
lng = context.get('lang', False) or 'en_US'
|
||||
@@ -660,9 +666,12 @@ class orm_template(object):
|
||||
error_msgs.append(
|
||||
_("Error occured while validating the field(s) %s: %s") % (','.join(fields), translated_msg)
|
||||
)
|
||||
self._invalids.update(fields)
|
||||
if error_msgs:
|
||||
cr.rollback()
|
||||
raise except_orm('ValidateError', '\n'.join(error_msgs))
|
||||
else:
|
||||
self._invalids.clear()
|
||||
|
||||
def default_get(self, cr, uid, fields_list, context=None):
|
||||
return {}
|
||||
@@ -1020,6 +1029,9 @@ class orm_template(object):
|
||||
xml += "<newline/>"
|
||||
xml += "</form>"
|
||||
elif view_type == 'tree':
|
||||
_rec_name = self._rec_name
|
||||
if _rec_name not in self._columns:
|
||||
_rec_name = self._columns.keys()[0]
|
||||
xml = '''<?xml version="1.0" encoding="utf-8"?>''' \
|
||||
'''<tree string="%s"><field name="%s"/></tree>''' \
|
||||
% (self._description, self._rec_name)
|
||||
@@ -1095,6 +1107,47 @@ class orm_template(object):
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
raise _('The copy method is not implemented on this object !')
|
||||
|
||||
def read_string(self, cr, uid, id, langs, fields=None, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
res = {}
|
||||
res2 = {}
|
||||
self.pool.get('ir.model.access').check(cr, uid, 'ir.translation', 'read')
|
||||
if not fields:
|
||||
fields = self._columns.keys() + self._inherit_fields.keys()
|
||||
for lang in langs:
|
||||
res[lang] = {'code': lang}
|
||||
for f in fields:
|
||||
if f in self._columns:
|
||||
res_trans = self.pool.get('ir.translation')._get_source(cr, uid, self._name+','+f, 'field', lang)
|
||||
if res_trans:
|
||||
res[lang][f] = res_trans
|
||||
else:
|
||||
res[lang][f] = self._columns[f].string
|
||||
for table in self._inherits:
|
||||
cols = intersect(self._inherit_fields.keys(), fields)
|
||||
res2 = self.pool.get(table).read_string(cr, uid, id, langs, cols, context)
|
||||
for lang in res2:
|
||||
if lang in res:
|
||||
res[lang] = {'code': lang}
|
||||
for f in res2[lang]:
|
||||
res[lang][f] = res2[lang][f]
|
||||
return res
|
||||
|
||||
def write_string(self, cr, uid, id, langs, vals, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
self.pool.get('ir.model.access').check(cr, uid, 'ir.translation', 'write')
|
||||
for lang in langs:
|
||||
for field in vals:
|
||||
if field in self._columns:
|
||||
self.pool.get('ir.translation')._set_ids(cr, uid, self._name+','+field, 'field', lang, [0], vals[field])
|
||||
for table in self._inherits:
|
||||
cols = intersect(self._inherit_fields.keys(), vals)
|
||||
if cols:
|
||||
self.pool.get(table).write_string(cr, uid, id, langs, vals, context)
|
||||
return True
|
||||
|
||||
|
||||
class orm_memory(orm_template):
|
||||
_protected = ['read', 'write', 'create', 'default_get', 'perm_read', 'unlink', 'fields_get', 'fields_view_get', 'search', 'name_get', 'distinct_field_get', 'name_search', 'copy', 'import_data', 'search_count']
|
||||
@@ -2531,47 +2584,6 @@ class orm(orm_template):
|
||||
|
||||
return new_id
|
||||
|
||||
def read_string(self, cr, uid, id, langs, fields=None, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
res = {}
|
||||
res2 = {}
|
||||
self.pool.get('ir.model.access').check(cr, uid, 'ir.translation', 'read')
|
||||
if not fields:
|
||||
fields = self._columns.keys() + self._inherit_fields.keys()
|
||||
for lang in langs:
|
||||
res[lang] = {'code': lang}
|
||||
for f in fields:
|
||||
if f in self._columns:
|
||||
res_trans = self.pool.get('ir.translation')._get_source(cr, uid, self._name+','+f, 'field', lang)
|
||||
if res_trans:
|
||||
res[lang][f] = res_trans
|
||||
else:
|
||||
res[lang][f] = self._columns[f].string
|
||||
for table in self._inherits:
|
||||
cols = intersect(self._inherit_fields.keys(), fields)
|
||||
res2 = self.pool.get(table).read_string(cr, uid, id, langs, cols, context)
|
||||
for lang in res2:
|
||||
if lang in res:
|
||||
res[lang] = {'code': lang}
|
||||
for f in res2[lang]:
|
||||
res[lang][f] = res2[lang][f]
|
||||
return res
|
||||
|
||||
def write_string(self, cr, uid, id, langs, vals, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
self.pool.get('ir.model.access').check(cr, uid, 'ir.translation', 'write')
|
||||
for lang in langs:
|
||||
for field in vals:
|
||||
if field in self._columns:
|
||||
self.pool.get('ir.translation')._set_ids(cr, uid, self._name+','+field, 'field', lang, [0], vals[field])
|
||||
for table in self._inherits:
|
||||
cols = intersect(self._inherit_fields.keys(), vals)
|
||||
if cols:
|
||||
self.pool.get(table).write_string(cr, uid, id, langs, vals, context)
|
||||
return True
|
||||
|
||||
def check_recursion(self, cr, uid, ids, parent=None):
|
||||
if not parent:
|
||||
parent = self._parent_name
|
||||
|
||||
+16
-7
@@ -90,16 +90,14 @@ class osv_pool(netsvc.Service):
|
||||
except psycopg.IntegrityError, inst:
|
||||
for key in self._sql_error.keys():
|
||||
if key in inst[0]:
|
||||
self.abortResponse(1, 'Constraint Error', 'warning',
|
||||
self._sql_error[key])
|
||||
self.abortResponse(1, 'Constraint Error', 'warning', self._sql_error[key])
|
||||
self.abortResponse(1, 'Integrity Error', 'warning', inst[0])
|
||||
except Exception, e:
|
||||
import traceback
|
||||
tb_s = reduce(lambda x, y: x+y, traceback.format_exception(
|
||||
sys.exc_type, sys.exc_value, sys.exc_traceback))
|
||||
tb_s = reduce(lambda x, y: x+y, traceback.format_exception( sys.exc_type, sys.exc_value, sys.exc_traceback))
|
||||
logger = Logger()
|
||||
logger.notifyChannel("web-services", LOG_ERROR,
|
||||
'Exception in call: ' + tb_s)
|
||||
for idx, s in enumerate(tb_s.split('\n')):
|
||||
logger.notifyChannel("web-services", LOG_ERROR, '[%2d]: %s' % (idx, s,))
|
||||
raise
|
||||
|
||||
def execute(self, db, uid, obj, method, *args, **kw):
|
||||
@@ -229,7 +227,18 @@ class osv(orm.orm):
|
||||
if hasattr(new, 'update'):
|
||||
new.update(cls.__dict__.get(s, {}))
|
||||
else:
|
||||
new.extend(cls.__dict__.get(s, []))
|
||||
if s=='_constraints':
|
||||
for c in cls.__dict__.get(s, []):
|
||||
exist = False
|
||||
for c2 in range(len(new)):
|
||||
if new[c2][2]==c[2]:
|
||||
new[c2] = c
|
||||
exist = True
|
||||
break
|
||||
if not exist:
|
||||
new.append(c)
|
||||
else:
|
||||
new.extend(cls.__dict__.get(s, []))
|
||||
nattr[s] = new
|
||||
name = hasattr(cls, '_name') and cls._name or cls._inherit
|
||||
cls = type(name, (cls, parent_class), nattr)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# $Id$
|
||||
#
|
||||
@@ -129,6 +129,7 @@ class report_printscreen_list(report_int):
|
||||
new_doc.childNodes[0].appendChild(config)
|
||||
header = new_doc.createElement("header")
|
||||
|
||||
|
||||
for f in fields_order:
|
||||
field = new_doc.createElement("field")
|
||||
field_txt = new_doc.createTextNode(str(fields[f]['string'] or ''))
|
||||
@@ -143,25 +144,31 @@ class report_printscreen_list(report_int):
|
||||
count = len(fields_order)
|
||||
for i in range(0,count):
|
||||
tsum.append(0)
|
||||
|
||||
|
||||
for line in results:
|
||||
node_line = new_doc.createElement("row")
|
||||
count = -1
|
||||
for f in fields_order:
|
||||
|
||||
count += 1
|
||||
|
||||
if fields[f]['type']=='many2one' and line[f]:
|
||||
line[f] = line[f][1]
|
||||
line[f]= line[f][1]
|
||||
|
||||
if fields[f]['type'] in ('one2many','many2many') and line[f]:
|
||||
line[f] = '( '+str(len(line[f])) + ' )'
|
||||
if fields[f]['type'] == 'float':
|
||||
precision=(('digits' in fields[f]) and fields[f]['digits'][1]) or 2
|
||||
line[f]=round(line[f],precision)
|
||||
line[f]='%.2f'%(line[f])
|
||||
|
||||
col = new_doc.createElement("col")
|
||||
col.setAttribute('para','yes')
|
||||
col.setAttribute('tree','no')
|
||||
if line[f] != None:
|
||||
txt = new_doc.createTextNode(str(line[f] or ''))
|
||||
if temp[count] == 1:
|
||||
tsum[count] = tsum[count] + line[f];
|
||||
tsum[count] = float(tsum[count]) + float(line[f]);
|
||||
|
||||
else:
|
||||
txt = new_doc.createTextNode('/')
|
||||
@@ -176,7 +183,11 @@ class report_printscreen_list(report_int):
|
||||
col.setAttribute('para','yes')
|
||||
col.setAttribute('tree','no')
|
||||
if tsum[f] != None:
|
||||
txt = new_doc.createTextNode(str(tsum[f] or ''))
|
||||
if tsum[f] >= 0.01 :
|
||||
total = '%.2f'%(tsum[f])
|
||||
txt = new_doc.createTextNode(str(total or ''))
|
||||
else :
|
||||
txt = new_doc.createTextNode(str(tsum[f] or ''))
|
||||
else:
|
||||
txt = new_doc.createTextNode('/')
|
||||
if f == 0:
|
||||
@@ -184,8 +195,10 @@ class report_printscreen_list(report_int):
|
||||
|
||||
col.appendChild(txt)
|
||||
node_line.appendChild(col)
|
||||
|
||||
lines.appendChild(node_line)
|
||||
|
||||
|
||||
new_doc.childNodes[0].appendChild(lines)
|
||||
|
||||
styledoc = libxml2.parseFile(os.path.join(tools.config['root_path'],'addons/base/report/custom_new.xsl'))
|
||||
@@ -200,4 +213,3 @@ report_printscreen_list('report.printscreen.list')
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
||||
@@ -385,7 +385,7 @@ class rml_parse(object):
|
||||
def _eval(self, expr):
|
||||
try:
|
||||
res = eval(expr, self.localcontext)
|
||||
if not res:
|
||||
if (res is None) or (res=='') or (res is False):
|
||||
res = ''
|
||||
except Exception,e:
|
||||
import traceback, sys
|
||||
|
||||
@@ -149,7 +149,7 @@ class db(netsvc.Service):
|
||||
try:
|
||||
cr.execute('DROP DATABASE ' + db_name)
|
||||
except:
|
||||
logger.notifyChannel("web-service", netsvc.LOG_ERROR,
|
||||
logger.notifyChannel("web-services", netsvc.LOG_ERROR,
|
||||
'DROP DB: %s failed' % (db_name,))
|
||||
raise
|
||||
else:
|
||||
@@ -163,11 +163,6 @@ class db(netsvc.Service):
|
||||
security.check_super(password)
|
||||
logger = netsvc.Logger()
|
||||
|
||||
if tools.config['db_password']:
|
||||
logger.notifyChannel("web-service", netsvc.LOG_ERROR,
|
||||
'DUMP DB: %s doesn\'t work with password' % (db_name,))
|
||||
raise Exception, "Couldn't dump database with password"
|
||||
|
||||
cmd = ['pg_dump', '--format=c']
|
||||
if tools.config['db_user']:
|
||||
cmd.append('--username=' + tools.config['db_user'])
|
||||
@@ -182,7 +177,7 @@ class db(netsvc.Service):
|
||||
data = stdout.read()
|
||||
res = stdout.close()
|
||||
if res:
|
||||
logger.notifyChannel("web-service", netsvc.LOG_ERROR,
|
||||
logger.notifyChannel("web-services", netsvc.LOG_ERROR,
|
||||
'DUMP DB: %s failed\n%s' % (db_name, data))
|
||||
raise Exception, "Couldn't dump database"
|
||||
logger.notifyChannel("web-services", netsvc.LOG_INFO,
|
||||
@@ -194,15 +189,10 @@ class db(netsvc.Service):
|
||||
logger = netsvc.Logger()
|
||||
|
||||
if self.db_exist(db_name):
|
||||
logger.notifyChannel("web-service", netsvc.LOG_WARNING,
|
||||
logger.notifyChannel("web-services", netsvc.LOG_WARNING,
|
||||
'RESTORE DB: %s already exists' % (db_name,))
|
||||
raise Exception, "Database already exists"
|
||||
|
||||
if tools.config['db_password']:
|
||||
logger.notifyChannel("web-service", netsvc.LOG_ERROR,
|
||||
'RESTORE DB: %s doesn\'t work with password' % (db_name,))
|
||||
raise Exception, "Couldn't restore database with password"
|
||||
|
||||
db = sql_db.db_connect('template1', serialize=1)
|
||||
db.truedb.autocommit()
|
||||
cr = db.cursor()
|
||||
@@ -328,7 +318,7 @@ class common(netsvc.Service):
|
||||
res = security.login(db, login, password)
|
||||
logger = netsvc.Logger()
|
||||
msg = res and 'successful login' or 'bad login or password'
|
||||
logger.notifyChannel("web-service", netsvc.LOG_INFO, "%s from '%s' using database '%s'" % (msg, login, db.lower()))
|
||||
logger.notifyChannel("web-services", netsvc.LOG_INFO, "%s from '%s' using database '%s'" % (msg, login, db.lower()))
|
||||
return res or False
|
||||
|
||||
def about(self, extended=False):
|
||||
@@ -480,7 +470,7 @@ class report_spool(netsvc.Service):
|
||||
tb_s = reduce(lambda x, y: x+y, traceback.format_exception(
|
||||
sys.exc_type, sys.exc_value, sys.exc_traceback))
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel('web-service', netsvc.LOG_ERROR,
|
||||
logger.notifyChannel('web-services', netsvc.LOG_ERROR,
|
||||
'Exception: %s\n%s' % (str(exception), tb_s))
|
||||
self._reports[id]['exception'] = exception
|
||||
self._reports[id]['state'] = True
|
||||
|
||||
Executable → Regular
+21
-13
@@ -1,7 +1,7 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# $Id$
|
||||
#
|
||||
@@ -282,7 +282,7 @@ form: module.record_id""" % (xml_id,)
|
||||
groups_value.append((4, group_id))
|
||||
res['groups_id'] = groups_value
|
||||
|
||||
id = self.pool.get('ir.model.data')._update(cr, self.uid, "ir.actions.report.xml", self.module, res, xml_id, mode=self.mode)
|
||||
id = self.pool.get('ir.model.data')._update(cr, self.uid, "ir.actions.report.xml", self.module, res, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode)
|
||||
self.idref[xml_id] = int(id)
|
||||
if not rec.hasAttribute('menu') or eval(rec.getAttribute('menu')):
|
||||
keyword = str(rec.getAttribute('keyword') or 'client_print_multi')
|
||||
@@ -322,7 +322,7 @@ form: module.record_id""" % (xml_id,)
|
||||
groups_value.append((4, group_id))
|
||||
res['groups_id'] = groups_value
|
||||
|
||||
id = self.pool.get('ir.model.data')._update(cr, self.uid, "ir.actions.wizard", self.module, res, xml_id, mode=self.mode)
|
||||
id = self.pool.get('ir.model.data')._update(cr, self.uid, "ir.actions.wizard", self.module, res, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode)
|
||||
self.idref[xml_id] = int(id)
|
||||
# ir_set
|
||||
if (not rec.hasAttribute('menu') or eval(rec.getAttribute('menu'))) and id:
|
||||
@@ -343,7 +343,7 @@ form: module.record_id""" % (xml_id,)
|
||||
|
||||
res = {'name': name, 'url': url, 'target':target}
|
||||
|
||||
id = self.pool.get('ir.model.data')._update(cr, self.uid, "ir.actions.url", self.module, res, xml_id, mode=self.mode)
|
||||
id = self.pool.get('ir.model.data')._update(cr, self.uid, "ir.actions.url", self.module, res, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode)
|
||||
self.idref[xml_id] = int(id)
|
||||
# ir_set
|
||||
if (not rec.hasAttribute('menu') or eval(rec.getAttribute('menu'))) and id:
|
||||
@@ -375,6 +375,14 @@ form: module.record_id""" % (xml_id,)
|
||||
and rec.getAttribute('auto_refresh').encode('utf-8')
|
||||
# groups_id = rec.hasAttribute('groups') and rec.getAttribute('groups').encode('utf-8')
|
||||
|
||||
# def ref() added because , if context has ref('id') eval wil use this ref
|
||||
|
||||
active_id=str("active_id") # for further reference in client/bin/tools/__init__.py
|
||||
|
||||
def ref(str_id):
|
||||
return self.id_get(cr, None, str_id)
|
||||
context=eval(context)
|
||||
|
||||
res = {
|
||||
'name': name,
|
||||
'type': type,
|
||||
@@ -406,7 +414,7 @@ form: module.record_id""" % (xml_id,)
|
||||
|
||||
if rec.hasAttribute('target'):
|
||||
res['target'] = rec.getAttribute('target')
|
||||
id = self.pool.get('ir.model.data')._update(cr, self.uid, 'ir.actions.act_window', self.module, res, xml_id, mode=self.mode)
|
||||
id = self.pool.get('ir.model.data')._update(cr, self.uid, 'ir.actions.act_window', self.module, res, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode)
|
||||
self.idref[xml_id] = int(id)
|
||||
|
||||
if src_model:
|
||||
@@ -554,7 +562,7 @@ form: module.record_id""" % (xml_id,)
|
||||
|
||||
xml_id = rec.getAttribute('id').encode('utf8')
|
||||
self._test_xml_id(xml_id)
|
||||
pid = self.pool.get('ir.model.data')._update(cr, self.uid, 'ir.ui.menu', self.module, values, xml_id, True, mode=self.mode, res_id=res and res[0] or False)
|
||||
pid = self.pool.get('ir.model.data')._update(cr, self.uid, 'ir.ui.menu', self.module, values, xml_id, noupdate=self.isnoupdate(data_node), mode=self.mode, res_id=res and res[0] or False)
|
||||
|
||||
if rec_id and pid:
|
||||
self.idref[rec_id] = int(pid)
|
||||
@@ -582,7 +590,7 @@ form: module.record_id""" % (xml_id,)
|
||||
rec_src = rec.getAttribute("search").encode('utf8')
|
||||
rec_src_count = rec.getAttribute("count")
|
||||
|
||||
severity = rec.getAttribute("severity").encode('ascii') or netsvc.LOG_ERROR
|
||||
severity = rec.getAttribute("severity").encode('ascii') or netsvc.LOG_ERROR
|
||||
|
||||
rec_string = rec.getAttribute("string").encode('utf8') or 'unknown'
|
||||
|
||||
@@ -744,15 +752,17 @@ form: module.record_id""" % (xml_id,)
|
||||
raise
|
||||
return True
|
||||
|
||||
def __init__(self, cr, module, idref, mode, report=assertion_report(), noupdate = False):
|
||||
def __init__(self, cr, module, idref, mode, report=None, noupdate=False):
|
||||
|
||||
self.logger = netsvc.Logger()
|
||||
self.mode = mode
|
||||
self.module = module
|
||||
self.cr = cr
|
||||
self.idref = idref
|
||||
self.pool = pooler.get_pool(cr.dbname)
|
||||
# self.pool = osv.osv.FakePool(module)
|
||||
self.uid = 1
|
||||
if report is None:
|
||||
report = assertion_report()
|
||||
self.assert_report = report
|
||||
self.noupdate = noupdate
|
||||
self._tags = {
|
||||
@@ -822,7 +832,7 @@ def convert_csv_import(cr, module, fname, csvcontent, idref=None, mode='init',
|
||||
#
|
||||
# xml import/export
|
||||
#
|
||||
def convert_xml_import(cr, module, xmlfile, idref=None, mode='init', noupdate = False, report=None):
|
||||
def convert_xml_import(cr, module, xmlfile, idref=None, mode='init', noupdate=False, report=None):
|
||||
xmlstr = xmlfile.read()
|
||||
xmlfile.seek(0)
|
||||
relaxng_doc = etree.parse(file(os.path.join( config['root_path'], 'import_xml.rng' )))
|
||||
@@ -839,9 +849,7 @@ def convert_xml_import(cr, module, xmlfile, idref=None, mode='init', noupdate =
|
||||
|
||||
if idref is None:
|
||||
idref={}
|
||||
if report is None:
|
||||
report=assertion_report()
|
||||
obj = xml_import(cr, module, idref, mode, report=report, noupdate = noupdate)
|
||||
obj = xml_import(cr, module, idref, mode, report=report, noupdate=noupdate)
|
||||
obj.parse(xmlstr)
|
||||
del obj
|
||||
return True
|
||||
|
||||
+64
-91
@@ -323,19 +323,30 @@ def reverse_enumerate(l):
|
||||
#----------------------------------------------------------
|
||||
# Emails
|
||||
#----------------------------------------------------------
|
||||
def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=None, on_error=False, reply_to=False, tinycrm=False, ssl=False, debug=False,subtype='plain'):
|
||||
def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=None, reply_to=False, attach=None, tinycrm=False, ssl=False, debug=False,subtype='plain'):
|
||||
"""Send an email."""
|
||||
if not email_cc:
|
||||
email_cc=[]
|
||||
if not email_bcc:
|
||||
email_bcc=[]
|
||||
import smtplib
|
||||
from email.MIMEText import MIMEText
|
||||
from email.MIMEBase import MIMEBase
|
||||
from email.MIMEMultipart import MIMEMultipart
|
||||
from email.Header import Header
|
||||
from email.Utils import formatdate, COMMASPACE
|
||||
from email.Utils import formatdate, COMMASPACE
|
||||
from email import Encoders
|
||||
|
||||
if not ssl:
|
||||
ssl = config.get('smtp_ssl', False)
|
||||
|
||||
if not email_cc:
|
||||
email_cc = []
|
||||
if not email_bcc:
|
||||
email_bcc = []
|
||||
|
||||
if not attach:
|
||||
msg = MIMEText(body or '',_subtype=subtype,_charset='utf-8')
|
||||
else:
|
||||
msg = MIMEMultipart()
|
||||
|
||||
msg = MIMEText(body or '',_subtype=subtype,_charset='utf-8')
|
||||
msg['Subject'] = Header(subject.decode('utf8'), 'utf-8')
|
||||
msg['From'] = email_from
|
||||
del msg['Reply-To']
|
||||
@@ -347,8 +358,19 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
|
||||
if email_bcc:
|
||||
msg['Bcc'] = COMMASPACE.join(email_bcc)
|
||||
msg['Date'] = formatdate(localtime=True)
|
||||
|
||||
if tinycrm:
|
||||
msg['Message-Id'] = '<'+str(time.time())+'-tinycrm-'+str(tinycrm)+'@'+socket.gethostname()+'>'
|
||||
msg['Message-Id'] = "<%s-tinycrm-%s@%s>" % (time.time(), tinycrm, socket.gethostname())
|
||||
|
||||
if attach:
|
||||
msg.attach( MIMEText(body or '', _charset='utf-8', _subtype=subtype) )
|
||||
|
||||
for (fname,fcontent) in attach:
|
||||
part = MIMEBase('application', "octet-stream")
|
||||
part.set_payload( fcontent )
|
||||
Encoders.encode_base64(part)
|
||||
part.add_header('Content-Disposition', 'attachment; filename="%s"' % (fname,))
|
||||
msg.attach(part)
|
||||
try:
|
||||
s = smtplib.SMTP()
|
||||
|
||||
@@ -362,78 +384,16 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
|
||||
|
||||
if config['smtp_user'] or config['smtp_password']:
|
||||
s.login(config['smtp_user'], config['smtp_password'])
|
||||
s.sendmail(email_from, flatten([email_to, email_cc, email_bcc]), msg.as_string())
|
||||
s.quit()
|
||||
except Exception, e:
|
||||
import logging
|
||||
logging.getLogger().error(str(e))
|
||||
return True
|
||||
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Emails
|
||||
#----------------------------------------------------------
|
||||
def email_send_attach(email_from, email_to, subject, body, email_cc=None, email_bcc=None, on_error=False, reply_to=False, attach=None, tinycrm=False, ssl=False, debug=False):
|
||||
"""Send an email."""
|
||||
if not email_cc:
|
||||
email_cc=[]
|
||||
if not email_bcc:
|
||||
email_bcc=[]
|
||||
if not attach:
|
||||
attach=[]
|
||||
import smtplib
|
||||
from email.MIMEText import MIMEText
|
||||
from email.MIMEBase import MIMEBase
|
||||
from email.MIMEMultipart import MIMEMultipart
|
||||
from email.Header import Header
|
||||
from email.Utils import formatdate, COMMASPACE
|
||||
from email import Encoders
|
||||
|
||||
msg = MIMEMultipart()
|
||||
|
||||
if not ssl:
|
||||
ssl = config.get('smtp_ssl', False)
|
||||
|
||||
msg['Subject'] = Header(subject.decode('utf8'), 'utf-8')
|
||||
msg['From'] = email_from
|
||||
del msg['Reply-To']
|
||||
if reply_to:
|
||||
msg['Reply-To'] = reply_to
|
||||
msg['To'] = COMMASPACE.join(email_to)
|
||||
if email_cc:
|
||||
msg['Cc'] = COMMASPACE.join(email_cc)
|
||||
if email_bcc:
|
||||
msg['Bcc'] = COMMASPACE.join(email_bcc)
|
||||
if tinycrm:
|
||||
msg['Message-Id'] = '<'+str(time.time())+'-tinycrm-'+str(tinycrm)+'@'+socket.gethostname()+'>'
|
||||
msg['Date'] = formatdate(localtime=True)
|
||||
msg.attach( MIMEText(body or '', _charset='utf-8', _subtype="html"))
|
||||
for (fname,fcontent) in attach:
|
||||
part = MIMEBase('application', "octet-stream")
|
||||
part.set_payload( fcontent )
|
||||
Encoders.encode_base64(part)
|
||||
part.add_header('Content-Disposition', 'attachment; filename="%s"' % (fname,))
|
||||
msg.attach(part)
|
||||
try:
|
||||
s = smtplib.SMTP()
|
||||
|
||||
if debug:
|
||||
s.debuglevel = 5
|
||||
s.connect(config['smtp_server'], config['smtp_port'])
|
||||
if ssl:
|
||||
s.ehlo()
|
||||
s.starttls()
|
||||
s.ehlo()
|
||||
|
||||
if config['smtp_user'] or config['smtp_password']:
|
||||
s.login(config['smtp_user'], config['smtp_password'])
|
||||
s.sendmail(email_from, flatten([email_to, email_cc, email_bcc]), msg.as_string())
|
||||
s.sendmail(email_from,
|
||||
flatten([email_to, email_cc, email_bcc]),
|
||||
msg.as_string()
|
||||
)
|
||||
s.quit()
|
||||
except Exception, e:
|
||||
import logging
|
||||
logging.getLogger().error(str(e))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
#----------------------------------------------------------
|
||||
@@ -642,23 +602,34 @@ def to_xml(s):
|
||||
|
||||
def get_languages():
|
||||
languages={
|
||||
'zh_CN': 'Chinese (CN)',
|
||||
'zh_TW': 'Chinese (TW)',
|
||||
'cs_CZ': 'Czech',
|
||||
'de_DE': 'Deutsch',
|
||||
'es_AR': 'Español (Argentina)',
|
||||
'es_ES': 'Español (España)',
|
||||
'fr_FR': 'Français',
|
||||
'fr_CH': 'Français (Suisse)',
|
||||
'en_EN': 'English (default)',
|
||||
'hu_HU': 'Hungarian',
|
||||
'it_IT': 'Italiano',
|
||||
'pt_BR': 'Portugese (Brasil)',
|
||||
'pt_PT': 'Portugese (Portugal)',
|
||||
'nl_NL': 'Nederlands',
|
||||
'ro_RO': 'Romanian',
|
||||
'ru_RU': 'Russian',
|
||||
'sv_SE': 'Swedish',
|
||||
'bg_BG': u'Bulgarian / български',
|
||||
'ca_ES': u'Catalan / Català',
|
||||
'cs_CZ': u'Czech / Čeština',
|
||||
'de_DE': u'German / Deutsch',
|
||||
'en_CA': u'English (CA)',
|
||||
'en_EN': u'English (default)',
|
||||
'en_GB': u'English (UK)',
|
||||
'en_US': u'English (US)',
|
||||
'es_AR': u'Spanish (AR) / Español (AR)',
|
||||
'es_ES': u'Spanish / Español',
|
||||
'et_ET': u'Estonian / Eesti keel',
|
||||
'fr_BE': u'French (BE) / Français (BE)',
|
||||
'fr_CH': u'French (CH) / Français (CH)',
|
||||
'fr_FR': u'French / Français',
|
||||
'hr_HR': u'Croatian / hrvatski jezik',
|
||||
'hu_HU': u'Hungarian / Magyar',
|
||||
'it_IT': u'Italian / Italiano',
|
||||
'lt_LT': u'Lithuanian / Lietuvių kalba',
|
||||
'nl_NL': u'Dutch / Nederlands',
|
||||
'pt_BR': u'Portugese (BR) / português (BR)',
|
||||
'pt_PT': u'Portugese / português',
|
||||
'ro_RO': u'Romanian / limba română',
|
||||
'ru_RU': u'Russian / русский язык',
|
||||
'sl_SL': u'Slovenian / slovenščina',
|
||||
'sv_SE': u'Swedish / svenska',
|
||||
'uk_UK': u'Ukrainian / украї́нська мо́ва',
|
||||
'zh_CN': u'Chinese (CN) / 简体中文' ,
|
||||
'zh_TW': u'Chinese (TW) / 正體字',
|
||||
}
|
||||
return languages
|
||||
|
||||
@@ -666,7 +637,9 @@ def scan_languages():
|
||||
import glob
|
||||
file_list = [os.path.splitext(os.path.basename(f))[0] for f in glob.glob(os.path.join(config['root_path'],'addons', 'base', 'i18n', '*.po'))]
|
||||
lang_dict = get_languages()
|
||||
return [(lang, lang_dict.get(lang, lang)) for lang in file_list]
|
||||
ret = [(lang, lang_dict.get(lang, lang)) for lang in file_list]
|
||||
ret.sort(key=lambda k:k[1])
|
||||
return ret
|
||||
|
||||
|
||||
def get_user_companies(cr, user):
|
||||
|
||||
@@ -100,18 +100,15 @@ class TinyPoFile(object):
|
||||
else:
|
||||
tmp_tnrs = []
|
||||
line = None
|
||||
while not line:
|
||||
while (not line):
|
||||
if 0 == len(self.lines):
|
||||
raise StopIteration()
|
||||
line = self.lines.pop(0).strip()
|
||||
|
||||
while line.startswith('#'):
|
||||
if line.startswith('#:'):
|
||||
if line.startswith('#:'):
|
||||
tmp_tnrs.append( line[2:].strip().split(':') )
|
||||
line = self.lines.pop(0).strip()
|
||||
while not line:
|
||||
# allow empty lines between comments and msgid
|
||||
line = self.lines.pop(0).strip()
|
||||
if line.startswith('#'):
|
||||
line = None
|
||||
|
||||
if not line.startswith('msgid'):
|
||||
raise Exception("malformed file: bad line: %s" % line)
|
||||
source = unquote(line[6:])
|
||||
|
||||
@@ -96,6 +96,12 @@ def _execute(cr, workitem, activity, ident, stack):
|
||||
if activity['kind']=='dummy':
|
||||
if workitem['state']=='active':
|
||||
_state_set(cr, workitem, activity, 'complete', ident)
|
||||
if activity['action_id']:
|
||||
print 'ICI'
|
||||
res2 = wkf_expr.execute_action(cr, ident, workitem, activity)
|
||||
if res2:
|
||||
stack.append(res2)
|
||||
result=res2
|
||||
elif activity['kind']=='function':
|
||||
if workitem['state']=='active':
|
||||
_state_set(cr, workitem, activity, 'running', ident)
|
||||
|
||||
@@ -35,7 +35,8 @@ import glob
|
||||
from stat import ST_MODE
|
||||
|
||||
from distutils.core import setup, Command
|
||||
from distutils.command.install_scripts import install_scripts
|
||||
from distutils.command.install import install
|
||||
#from distutils.command.install_scripts import install_scripts
|
||||
from distutils.file_util import copy_file
|
||||
|
||||
if os.name == 'nt':
|
||||
@@ -147,24 +148,26 @@ def data_files():
|
||||
|
||||
check_modules()
|
||||
|
||||
# create startup script
|
||||
start_script = \
|
||||
"#!/bin/sh\n\
|
||||
cd %s/lib/python%s/site-packages/openerp-server\n\
|
||||
exec %s ./openerp-server.py $@\n" % (sys.prefix, py_short_version, sys.executable)
|
||||
# write script
|
||||
f = open('openerp-server', 'w')
|
||||
f.write(start_script)
|
||||
f.close()
|
||||
|
||||
class openerp_server_install(install):
|
||||
def run(self):
|
||||
# create startup script
|
||||
start_script = "#!/bin/sh\ncd %s\nexec %s ./openerp-server.py $@\n" % (opj(self.install_libbase, "openerp-server"), sys.executable)
|
||||
# write script
|
||||
f = open('openerp-server', 'w')
|
||||
f.write(start_script)
|
||||
f.close()
|
||||
|
||||
install.run(self)
|
||||
|
||||
options = {
|
||||
"py2exe": {
|
||||
"compressed": 0,
|
||||
"compressed": 1,
|
||||
"optimize": 2,
|
||||
"packages": ["lxml", "lxml.builder", "lxml._elementpath", "lxml.etree",
|
||||
"lxml.objectify", "decimal", "xml", "xml.dom", "xml.xpath",
|
||||
"encodings","mx.DateTime","wizard","pychart","PIL", "pyparsing",
|
||||
"pydot","asyncore","asynchat", "reportlab"],
|
||||
"pydot","asyncore","asynchat", "reportlab", "vobject", "HTMLParser"],
|
||||
"excludes" : ["Tkconstants","Tkinter","tcl"],
|
||||
}
|
||||
}
|
||||
@@ -179,6 +182,7 @@ setup(name = name,
|
||||
classifiers = filter(None, classifiers.split("\n")),
|
||||
license = license,
|
||||
data_files = data_files(),
|
||||
cmdclass = { 'install' : openerp_server_install },
|
||||
scripts = ['openerp-server'],
|
||||
packages = ['openerp-server',
|
||||
'openerp-server.addons',
|
||||
|
||||
Reference in New Issue
Block a user