Merge commit 'origin/master' into mdv-gpl3-py26
Conflicts: bin/addons/__init__.py bin/addons/base/ir/ir_cron.py bin/addons/base/rng/view.rng bzr revid: p_christ@hol.gr-20090304073610-2ss5ju4lyyue79qv bzr revid: p_christ@hol.gr-20090308214750-0bgr6yj85f8ixpjp bzr revid: p_christ@hol.gr-20090312075024-1rqeqam5ipfofb9m
This commit is contained in:
commit
7cb394f380
|
@ -1,3 +1,5 @@
|
|||
./bin/addons/*
|
||||
./bin/filestore*
|
||||
|
||||
*.pyc
|
||||
.*.swp
|
||||
.bzrignore
|
||||
bin/addons/*
|
||||
bin/filestore*
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
import os, sys, imp
|
||||
from os.path import join as opj
|
||||
import itertools
|
||||
# from sets import Set
|
||||
import zipimport
|
||||
|
||||
import osv
|
||||
|
@ -69,6 +68,26 @@ class Graph(dict):
|
|||
father.addChild(name)
|
||||
else:
|
||||
Node(name, self)
|
||||
|
||||
def update_from_db(self, cr):
|
||||
# update the graph with values from the database (if exist)
|
||||
## First, we set the default values for each package in graph
|
||||
additional_data = dict.fromkeys(self.keys(), {'id': 0, 'state': 'uninstalled', 'dbdemo': False, 'installed_version': None})
|
||||
## Then we get the values from the database
|
||||
cr.execute('SELECT name, id, state, demo AS dbdemo, latest_version AS installed_version'
|
||||
' FROM ir_module_module'
|
||||
' WHERE name in (%s)' % (','.join(['%s'] * len(self))),
|
||||
additional_data.keys()
|
||||
)
|
||||
|
||||
## and we update the default values with values from the database
|
||||
additional_data.update(dict([(x.pop('name'), x) for x in cr.dictfetchall()]))
|
||||
|
||||
for package in self.values():
|
||||
for k, v in additional_data[package.name].items():
|
||||
setattr(package, k, v)
|
||||
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
level = 0
|
||||
|
@ -80,9 +99,7 @@ class Graph(dict):
|
|||
yield module
|
||||
level += 1
|
||||
|
||||
|
||||
class Singleton(object):
|
||||
|
||||
def __new__(cls, name, graph):
|
||||
if name in graph:
|
||||
inst = graph[name]
|
||||
|
@ -97,57 +114,53 @@ class Node(Singleton):
|
|||
|
||||
def __init__(self, name, graph):
|
||||
self.graph = graph
|
||||
if not hasattr(self, 'childs'):
|
||||
self.childs = []
|
||||
if not hasattr(self, 'children'):
|
||||
self.children = []
|
||||
if not hasattr(self, 'depth'):
|
||||
self.depth = 0
|
||||
|
||||
def addChild(self, name):
|
||||
node = Node(name, self.graph)
|
||||
node.depth = self.depth + 1
|
||||
if node not in self.childs:
|
||||
self.childs.append(node)
|
||||
if node not in self.children:
|
||||
self.children.append(node)
|
||||
for attr in ('init', 'update', 'demo'):
|
||||
if hasattr(self, attr):
|
||||
setattr(node, attr, True)
|
||||
self.childs.sort(lambda x, y: cmp(x.name, y.name))
|
||||
|
||||
def hasChild(self, name):
|
||||
return Node(name, self.graph) in self.childs or \
|
||||
bool([c for c in self.childs if c.hasChild(name)])
|
||||
self.children.sort(lambda x, y: cmp(x.name, y.name))
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
super(Singleton, self).__setattr__(name, value)
|
||||
if name in ('init', 'update', 'demo'):
|
||||
tools.config[name][self.name] = 1
|
||||
for child in self.childs:
|
||||
for child in self.children:
|
||||
setattr(child, name, value)
|
||||
if name == 'depth':
|
||||
for child in self.childs:
|
||||
for child in self.children:
|
||||
setattr(child, name, value + 1)
|
||||
|
||||
def __iter__(self):
|
||||
return itertools.chain(iter(self.childs), *map(iter, self.childs))
|
||||
|
||||
return itertools.chain(iter(self.children), *map(iter, self.children))
|
||||
|
||||
def __str__(self):
|
||||
return self._pprint()
|
||||
|
||||
def _pprint(self, depth=0):
|
||||
s = '%s\n' % self.name
|
||||
for c in self.childs:
|
||||
for c in self.children:
|
||||
s += '%s`-> %s' % (' ' * depth, c._pprint(depth+1))
|
||||
return s
|
||||
|
||||
|
||||
def get_module_path(module):
|
||||
def get_module_path(module, downloaded=False):
|
||||
"""Return the path of the given module."""
|
||||
|
||||
if os.path.exists(opj(ad, module)) or os.path.exists(opj(ad, '%s.zip' % module)):
|
||||
return opj(ad, module)
|
||||
|
||||
if os.path.exists(opj(_ad, module)) or os.path.exists(opj(_ad, '%s.zip' % module)):
|
||||
return opj(_ad, module)
|
||||
|
||||
if downloaded:
|
||||
return opj(_ad, module)
|
||||
logger.notifyChannel('init', netsvc.LOG_WARNING, 'module %s: module not found' % (module,))
|
||||
return False
|
||||
|
||||
|
@ -334,6 +347,8 @@ def upgrade_graph(graph, cr, module_list, force=None):
|
|||
packages.append((package, deps, data))
|
||||
packages.pop(0)
|
||||
|
||||
graph.update_from_db(cr)
|
||||
|
||||
for package in later:
|
||||
unmet_deps = filter(lambda p: p not in graph, dependencies[package])
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'module %s: Unmet dependencies: %s' % (package, ', '.join(unmet_deps)))
|
||||
|
@ -552,24 +567,6 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs):
|
|||
statusi = 0
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
|
||||
|
||||
# update the graph with values from the database (if exist)
|
||||
## First, we set the default values for each package in graph
|
||||
additional_data = dict.fromkeys([p.name for p in graph], {'id': 0, 'state': 'uninstalled', 'dbdemo': False, 'installed_version': None})
|
||||
## Then we get the values from the database
|
||||
cr.execute('SELECT name, id, state, demo AS dbdemo, latest_version AS installed_version'
|
||||
' FROM ir_module_module'
|
||||
' WHERE name in (%s)' % (','.join(['%s'] * len(graph))),
|
||||
additional_data.keys()
|
||||
)
|
||||
|
||||
## and we update the default values with values from the database
|
||||
additional_data.update(dict([(x.pop('name'), x) for x in cr.dictfetchall()]))
|
||||
|
||||
for package in graph:
|
||||
for k, v in additional_data[package.name].items():
|
||||
setattr(package, k, v)
|
||||
|
||||
migrations = MigrationManager(cr, graph)
|
||||
|
||||
has_updates = False
|
||||
|
@ -596,14 +593,16 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs):
|
|||
|
||||
idref = {}
|
||||
status['progress'] = (float(statusi)+0.4) / len(graph)
|
||||
|
||||
mode = 'update'
|
||||
if hasattr(package, 'init') or package.state == 'to install':
|
||||
mode = 'init'
|
||||
|
||||
if hasattr(package, 'init') or hasattr(package, 'update') or package.state in ('to install', 'to upgrade'):
|
||||
has_updates = True
|
||||
init_module_objects(cr, m, modules)
|
||||
for kind in ('init', 'update'):
|
||||
for filename in package.data.get('%s_xml' % kind, []):
|
||||
mode = 'update'
|
||||
if hasattr(package, 'init') or package.state == 'to install':
|
||||
mode = 'init'
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: loading %s' % (m, filename))
|
||||
name, ext = os.path.splitext(filename)
|
||||
fp = tools.file_open(opj(m, filename))
|
||||
|
@ -648,9 +647,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, **kwargs):
|
|||
if hasattr(package, kind):
|
||||
delattr(package, kind)
|
||||
|
||||
|
||||
statusi += 1
|
||||
|
||||
|
||||
cr.execute('select model from ir_model where state=%s', ('manual',))
|
||||
for model in cr.dictfetchall():
|
||||
|
@ -750,7 +747,7 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
|
|||
cr.execute('delete from ir_model_data where noupdate=%s and module=%s', (False, mod_name,))
|
||||
cr.commit()
|
||||
#
|
||||
# TODO: remove menu without actions of childs
|
||||
# TODO: remove menu without actions of children
|
||||
#
|
||||
while True:
|
||||
cr.execute('''delete from
|
||||
|
@ -774,4 +771,3 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
|
|||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ create table ir_values
|
|||
id serial,
|
||||
name varchar(128) not null,
|
||||
key varchar(128) not null,
|
||||
key2 varchar(128) not null,
|
||||
key2 varchar(256) not null,
|
||||
model varchar(128) not null,
|
||||
value text,
|
||||
meta text default NULL,
|
||||
|
@ -55,7 +55,7 @@ CREATE TABLE ir_model_fields (
|
|||
CREATE TABLE ir_actions (
|
||||
id serial NOT NULL,
|
||||
name varchar(64) DEFAULT ''::varchar NOT NULL,
|
||||
"type" varchar(64) DEFAULT 'window'::varchar NOT NULL,
|
||||
"type" varchar(32) DEFAULT 'window'::varchar NOT NULL,
|
||||
usage varchar(32) DEFAULT null,
|
||||
primary key(id)
|
||||
);
|
||||
|
@ -64,7 +64,7 @@ CREATE TABLE ir_act_window (
|
|||
view_id integer,
|
||||
res_model varchar(64),
|
||||
view_type varchar(16),
|
||||
"domain" varchar(127),
|
||||
"domain" varchar(250),
|
||||
primary key(id)
|
||||
)
|
||||
INHERITS (ir_actions);
|
||||
|
@ -72,8 +72,8 @@ INHERITS (ir_actions);
|
|||
CREATE TABLE ir_act_report_xml (
|
||||
model varchar(64) NOT NULL,
|
||||
report_name varchar(64) NOT NULL,
|
||||
report_xsl varchar(64),
|
||||
report_xml varchar(64),
|
||||
report_xsl varchar(256),
|
||||
report_xml varchar(256),
|
||||
auto boolean default true,
|
||||
primary key(id)
|
||||
)
|
||||
|
@ -140,7 +140,7 @@ CREATE TABLE res_users (
|
|||
name varchar(64) not null,
|
||||
active boolean default True,
|
||||
login varchar(64) NOT NULL UNIQUE,
|
||||
password varchar(32) default null,
|
||||
password varchar(64) default null,
|
||||
context_tz varchar(64) default null,
|
||||
signature text,
|
||||
-- action_id int references ir_act_window on delete set null,
|
||||
|
@ -151,14 +151,14 @@ alter table res_users add constraint res_users_login_uniq unique (login);
|
|||
|
||||
CREATE TABLE res_groups (
|
||||
id serial NOT NULL,
|
||||
name varchar(32) NOT NULL,
|
||||
name varchar(64) NOT NULL,
|
||||
primary key(id)
|
||||
);
|
||||
|
||||
create table res_roles (
|
||||
id serial NOT NULL,
|
||||
parent_id int references res_roles on delete set null,
|
||||
name varchar(32) NOT NULL,
|
||||
name varchar(64) NOT NULL,
|
||||
primary key(id)
|
||||
);
|
||||
|
||||
|
|
|
@ -2748,7 +2748,6 @@
|
|||
<field name="code">COP</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="CZK" model="res.currency">
|
||||
|
@ -2756,7 +2755,6 @@
|
|||
<field name="code">CZK</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="DKK" model="res.currency">
|
||||
|
@ -2777,7 +2775,6 @@
|
|||
<field name="code">HUF</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="IDR" model="res.currency">
|
||||
|
@ -2785,7 +2782,6 @@
|
|||
<field name="code">IDR</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="LVL" model="res.currency">
|
||||
|
@ -2832,7 +2828,6 @@
|
|||
<field name="code">PLN</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="SEK" model="res.currency">
|
||||
|
@ -2840,7 +2835,6 @@
|
|||
<field name="code">SEK</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="GBP" model="res.currency">
|
||||
|
@ -2860,9 +2854,20 @@
|
|||
<field name="code">ARS</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="INR" model="res.currency">
|
||||
<field name="name">INR</field>
|
||||
<field name="code">Rs</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
</record>
|
||||
<record id="rateINR" model="res.currency.rate">
|
||||
<field name="rate">0.634</field>
|
||||
<field name="currency_id" ref="INR"/>
|
||||
<field eval="time.strftime('%Y-01-01')" name="name"/>
|
||||
</record>
|
||||
|
||||
<!-- Basic Company -->
|
||||
<record id="main_company" model="res.company">
|
||||
<field name="name">Tiny sprl</field>
|
||||
|
|
|
@ -1234,8 +1234,8 @@
|
|||
</page>
|
||||
<page string="SMS Configuration" attrs="{'invisible':[('state','!=','sms')]}">
|
||||
<separator colspan="4" string="SMS Configuration"/>
|
||||
<field name="mobile" domain="[('model_id','=',model_id)]" attrs="{'required':[('state','=','email')]}"/>
|
||||
<field name="sms" colspan="4" attrs="{'required':[('state','=','email')]}"/>
|
||||
<field name="mobile" domain="[('model_id','=',model_id)]" attrs="{'required':[('state','=','sms')]}"/>
|
||||
<field name="sms" colspan="4" attrs="{'required':[('state','=','sms')]}"/>
|
||||
<newline/>
|
||||
<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>
|
||||
|
|
|
@ -77,47 +77,47 @@ class ir_cron(osv.osv, netsvc.Agent):
|
|||
def _poolJobs(self, db_name, check=False):
|
||||
try:
|
||||
db, pool = pooler.get_db_and_pool(db_name)
|
||||
if pool._init:
|
||||
# retry in a few minutes
|
||||
self.setAlarm(self._poolJobs, int(time.time())+10*60, [db_name])
|
||||
cr = db.cursor()
|
||||
except:
|
||||
return False
|
||||
|
||||
now = DateTime.now()
|
||||
#FIXME: multidb. Solution: a l'instanciation d'une nouvelle connection bd (ds pooler) fo que j'instancie
|
||||
# un nouveau pooljob avec comme parametre la bd
|
||||
|
||||
try:
|
||||
cr.execute('select * from ir_cron where numbercall<>0 and active and nextcall<=now() order by priority')
|
||||
for job in cr.dictfetchall():
|
||||
nextcall = DateTime.strptime(job['nextcall'], '%Y-%m-%d %H:%M:%S')
|
||||
numbercall = job['numbercall']
|
||||
if pool._init:
|
||||
# retry in a few minutes
|
||||
next_call = 600
|
||||
else:
|
||||
next_call = next_wait
|
||||
cr = db.cursor()
|
||||
now = DateTime.now()
|
||||
try:
|
||||
cr.execute('select * from ir_cron where numbercall<>0 and active and nextcall<=now() order by priority')
|
||||
for job in cr.dictfetchall():
|
||||
nextcall = DateTime.strptime(job['nextcall'], '%Y-%m-%d %H:%M:%S')
|
||||
numbercall = job['numbercall']
|
||||
|
||||
ok = False
|
||||
while nextcall<now and numbercall:
|
||||
if numbercall > 0:
|
||||
numbercall -= 1
|
||||
if not ok or job['doall']:
|
||||
self._callback(cr, job['user_id'], job['model'], job['function'], job['args'])
|
||||
if numbercall:
|
||||
nextcall += _intervalTypes[job['interval_type']](job['interval_number'])
|
||||
ok = True
|
||||
addsql=''
|
||||
if not numbercall:
|
||||
addsql = ', active=False'
|
||||
cr.execute("update ir_cron set nextcall=%s, numbercall=%s"+addsql+" where id=%s", (nextcall.strftime('%Y-%m-%d %H:%M:%S'), numbercall, job['id']))
|
||||
cr.commit()
|
||||
ok = False
|
||||
while nextcall < now and numbercall:
|
||||
if numbercall > 0:
|
||||
numbercall -= 1
|
||||
if not ok or job['doall']:
|
||||
self._callback(cr, job['user_id'], job['model'], job['function'], job['args'])
|
||||
if numbercall:
|
||||
nextcall += _intervalTypes[job['interval_type']](job['interval_number'])
|
||||
ok = True
|
||||
addsql=''
|
||||
if not numbercall:
|
||||
addsql = ', active=False'
|
||||
cr.execute("update ir_cron set nextcall=%s, numbercall=%s"+addsql+" where id=%s", (nextcall.strftime('%Y-%m-%d %H:%M:%S'), numbercall, job['id']))
|
||||
cr.commit()
|
||||
except:
|
||||
print "Exception!"
|
||||
finally:
|
||||
cr.close()
|
||||
finally:
|
||||
cr.close()
|
||||
|
||||
#
|
||||
# Can be improved to do at the min(min(nextcalls), time()+next_wait)
|
||||
# Can be improved to do at the min(min(nextcalls), time()+next_call)
|
||||
# But is this an improvement ?
|
||||
#
|
||||
if not check:
|
||||
self.setAlarm(self._poolJobs, int(time.time())+next_wait, [db_name])
|
||||
self.setAlarm(self._poolJobs, int(time.time()) + next_call, db_name, db_name)
|
||||
return None
|
||||
|
||||
ir_cron()
|
||||
|
|
|
@ -437,14 +437,16 @@ class ir_model_data(osv.osv):
|
|||
if (not xml_id) and (not self.doinit):
|
||||
return False
|
||||
action_id = False
|
||||
|
||||
if xml_id:
|
||||
cr.execute('select id,res_id from ir_model_data where module=%s and name=%s', (module,xml_id))
|
||||
results = cr.fetchall()
|
||||
for action_id2,res_id2 in results:
|
||||
cr.execute('select id from '+self.pool.get(model)._table+' where id=%s', (res_id2,))
|
||||
cr.execute('select id from '+model_obj._table+' where id=%s', (res_id2,))
|
||||
result3 = cr.fetchone()
|
||||
if not result3:
|
||||
cr.execute('delete from ir_model_data where id=%s', (action_id2,))
|
||||
res_id = False
|
||||
else:
|
||||
res_id,action_id = res_id2,action_id2
|
||||
|
||||
|
@ -512,7 +514,7 @@ class ir_model_data(osv.osv):
|
|||
#self.pool.get(model).unlink(cr, uid, ids)
|
||||
for id in ids:
|
||||
self.unlink_mark[(model, id)]=False
|
||||
cr.execute('delete from ir_model_data where res_id=%s and model=\'%s\'', (id,model))
|
||||
cr.execute('delete from ir_model_data where res_id=%s and model=%s', (id, model))
|
||||
return True
|
||||
|
||||
def ir_set(self, cr, uid, key, key2, name, models, value, replace=True, isobject=False, meta=None, xml_id=False):
|
||||
|
@ -563,18 +565,20 @@ class ir_model_data(osv.osv):
|
|||
|
||||
cr.commit()
|
||||
if not config.get('import_partial', False):
|
||||
for (model,id) in self.unlink_mark.keys():
|
||||
logger = netsvc.Logger()
|
||||
for (model, res_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))
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'Deleting %s@%s' % (res_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),))
|
||||
self.pool.get(model).unlink(cr, uid, [res_id])
|
||||
id = self.unlink_mark[(model, res_id)]
|
||||
if id:
|
||||
self.unlink(cr, uid, [id])
|
||||
cr.execute('DELETE FROM ir_values WHERE value=%s', ('%s,%s' % (model, res_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))
|
||||
cr.rollback()
|
||||
logger.notifyChannel('init', netsvc.LOG_ERROR, 'Could not delete id: %d of model %s\nThere should be some relation that points to this resource\nYou should manually fix this and restart --update=module' % (res_id, model))
|
||||
return True
|
||||
ir_model_data()
|
||||
|
||||
|
|
|
@ -105,18 +105,17 @@ class ir_rule(osv.osv):
|
|||
def _domain_force_get(self, cr, uid, ids, field_name, arg, context={}):
|
||||
res = {}
|
||||
for rule in self.browse(cr, uid, ids, context):
|
||||
eval_user_data = {'user': self.pool.get('res.users').browse(cr, 1, uid),
|
||||
'time':time}
|
||||
if rule.domain_force:
|
||||
res[rule.id] = eval(rule.domain_force, {'user': self.pool.get('res.users').browse(cr, 1, uid),
|
||||
'time':time})
|
||||
res[rule.id] = eval(rule.domain_force, eval_user_data)
|
||||
else:
|
||||
if rule.operator in ('in', 'child_of'):
|
||||
dom = eval("[('%s', '%s', [%s])]" % (rule.field_id.name, rule.operator,
|
||||
rule.operand), {'user': self.pool.get('res.users').browse(cr, 1, uid),
|
||||
'time':time})
|
||||
eval(rule.operand,eval_user_data)), eval_user_data)
|
||||
else:
|
||||
dom = eval("[('%s', '%s', %s)]" % (rule.field_id.name, rule.operator,
|
||||
rule.operand), {'user': self.pool.get('res.users').browse(cr, 1, uid),
|
||||
'time':time})
|
||||
rule.operand), eval_user_data)
|
||||
res[rule.id] = dom
|
||||
return res
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ class view(osv.osv):
|
|||
'type': fields.selection((
|
||||
('tree','Tree'),
|
||||
('form','Form'),
|
||||
('mdx','mdx'),
|
||||
('graph', 'Graph'),
|
||||
('calendar', 'Calendar'),
|
||||
('gantt', 'Gantt')), 'View Type', required=True),
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
##############################################################################
|
||||
|
||||
from osv import osv,fields
|
||||
from osv.orm import except_orm
|
||||
import pickle
|
||||
from tools.translate import _
|
||||
|
||||
|
@ -225,7 +226,10 @@ class ir_values(osv.osv):
|
|||
del fields[pos]
|
||||
else:
|
||||
pos+=1
|
||||
datas = self.pool.get(model).read(cr, uid, [id], fields, context)
|
||||
try:
|
||||
datas = self.pool.get(model).read(cr, uid, [id], fields, context)
|
||||
except except_orm:
|
||||
return False
|
||||
datas= datas and datas[0] or None
|
||||
if not datas:
|
||||
#ir_del(cr, uid, x[0])
|
||||
|
|
|
@ -398,12 +398,12 @@ class module(osv.osv):
|
|||
if not download:
|
||||
continue
|
||||
zipfile = urllib.urlopen(mod.url).read()
|
||||
fname = addons.get_module_path(mod.name+'.zip')
|
||||
fname = addons.get_module_path(str(mod.name)+'.zip', downloaded=True)
|
||||
try:
|
||||
fp = file(fname, 'wb')
|
||||
fp.write(zipfile)
|
||||
fp.close()
|
||||
except IOError, e:
|
||||
except Exception, e:
|
||||
raise orm.except_orm(_('Error'), _('Can not create the module file:\n %s') % (fname,))
|
||||
terp = self.get_module_info(mod.name)
|
||||
self.write(cr, uid, mod.id, {
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
<?xml version = '1.0' encoding="utf-8"?>
|
||||
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
|
||||
<xsl:variable name="signature" select="//corporate-header/user/signature"/>
|
||||
<xsl:variable name="title">Open ERP Report</xsl:variable>
|
||||
<xsl:variable name="leftMargin">1cm</xsl:variable>
|
||||
<xsl:variable name="rightMargin">1cm</xsl:variable>
|
||||
<xsl:variable name="topMargin">1cm</xsl:variable>
|
||||
<xsl:variable name="bottomMargin">1cm</xsl:variable>
|
||||
<xsl:variable name="pageSize">21cm,29.7cm</xsl:variable>
|
||||
|
||||
<xsl:variable name="page_format">a4_letter</xsl:variable>
|
||||
|
||||
<xsl:template name="first_page_graphics_corporation">
|
||||
<!--logo-->
|
||||
<setFont name="Helvetica" size="14"/>
|
||||
<fill color="black"/>
|
||||
<stroke color="black"/>
|
||||
<drawString x="1cm" y="27.6cm"><xsl:value-of select="//corporate-header/corporation/name"/></drawString>
|
||||
<lines>1cm 25.4cm 20cm 25.4cm</lines>
|
||||
<!-- <lines>1cm 25.7cm 7cm 25.7cm</lines>-->
|
||||
|
||||
<setFont name="Helvetica" size="10"/>
|
||||
<drawRightString x="1cm" y="27.5cm"><xsl:value-of select="//corporate-header/corporation/rml_header1"/></drawRightString>
|
||||
<drawString x="1cm" y="27cm"><xsl:value-of select="//corporate-header/corporation/address/street"/></drawString>
|
||||
<drawString x="1cm" y="26.5cm">
|
||||
<xsl:value-of select="//corporate-header/corporation/address/zip"/>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="//corporate-header/corporation/address/city"/>
|
||||
<xsl:text> - </xsl:text>
|
||||
<xsl:value-of select="//corporate-header/corporation/address/country"/>
|
||||
</drawString>
|
||||
<drawString x="1cm" y="26cm">Phone:</drawString>
|
||||
<drawRightString x="7cm" y="26cm"><xsl:value-of select="//corporate-header/corporation/address/phone"/></drawRightString>
|
||||
<drawString x="1cm" y="25.5cm">Mail:</drawString>
|
||||
<drawRightString x="7cm" y="25.5cm"><xsl:value-of select="//corporate-header/corporation/address/email"/></drawRightString>
|
||||
|
||||
|
||||
<!--page bottom-->
|
||||
|
||||
<lines>1.5cm 1.2cm 19.9cm 1.2cm</lines>
|
||||
<drawCentredString x="10.5cm" y="1.7cm"><xsl:value-of select="//corporate-header/corporation/rml_footer1"/></drawCentredString>
|
||||
<drawCentredString x="10.5cm" y="1.25cm"><xsl:value-of select="//corporate-header/corporation/rml_footer2"/></drawCentredString>
|
||||
<drawCentredString x="10.5cm" y="0.8cm">Your contact : <xsl:value-of select="//corporate-header/user/name"/></drawCentredString>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template name="other_pages_graphics_corporation">
|
||||
<!--logo-->
|
||||
<setFont name="Helvetica" size="14"/>
|
||||
<fill color="black"/>
|
||||
<stroke color="black"/>
|
||||
<drawString x="1cm" y="27.6cm"><xsl:value-of select="//corporate-header/corporation/name"/></drawString>
|
||||
<lines>1cm 25.4cm 20cm 25.4cm</lines>
|
||||
<!-- <lines>1cm 25.7cm 7cm 25.7cm</lines>-->
|
||||
|
||||
<setFont name="Helvetica" size="10"/>
|
||||
<drawRightString x="1cm" y="27.5cm"><xsl:value-of select="//corporate-header/corporation/rml_header1"/></drawRightString>
|
||||
<drawString x="1cm" y="27cm"><xsl:value-of select="//corporate-header/corporation/address/street"/></drawString>
|
||||
<drawString x="1cm" y="26.5cm">
|
||||
<xsl:value-of select="//corporate-header/corporation/address/zip"/>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:value-of select="//corporate-header/corporation/address/city"/>
|
||||
<xsl:text> - </xsl:text>
|
||||
<xsl:value-of select="//corporate-header/corporation/address/country"/>
|
||||
</drawString>
|
||||
<drawString x="1cm" y="26cm">Phone:</drawString>
|
||||
<drawRightString x="7cm" y="26cm"><xsl:value-of select="//corporate-header/corporation/address/phone"/></drawRightString>
|
||||
<drawString x="1cm" y="25.5cm">Mail:</drawString>
|
||||
<drawRightString x="7cm" y="25.5cm"><xsl:value-of select="//corporate-header/corporation/address/email"/></drawRightString>
|
||||
|
||||
<!--page bottom-->
|
||||
|
||||
<lines>1.5cm 1.2cm 19.9cm 1.2cm</lines>
|
||||
<drawCentredString x="10.5cm" y="1.7cm"><xsl:value-of select="//corporate-header/corporation/rml_footer1"/></drawCentredString>
|
||||
<drawCentredString x="10.5cm" y="1.25cm"><xsl:value-of select="//corporate-header/corporation/rml_footer2"/></drawCentredString>
|
||||
<!-- <drawCentredString x="10.5cm" y="0.8cm">Your contact : <xsl:value-of select="//corporate-header/user/name"/></drawCentredString>-->
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="first_page_frames">
|
||||
<xsl:if test="$page_format='a4_normal'">
|
||||
<frame id="main" x1="1cm" y1="2.5cm" width="19.0cm" height="22.0cm"/>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:if test="$page_format='a4_letter'">
|
||||
<frame id="address" x1="11cm" y1="21.5cm" width="6cm" height="4cm"/>
|
||||
<frame id="main" x1="1cm" y1="2.5cm" width="19.0cm" height="17.5cm"/>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="other_pages_frames">
|
||||
<frame id="main" x1="1cm" y1="2.5cm" width="19.0cm" height="22cm"/>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
|
@ -163,10 +163,6 @@ class res_partner(osv.osv):
|
|||
'customer': lambda *a: 1,
|
||||
'category_id': _default_category,
|
||||
}
|
||||
_sql_constraints = [
|
||||
('name_uniq', 'unique (name)', 'The name of the partner must be unique !')
|
||||
]
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context={}):
|
||||
name = self.read(cr, uid, [id], ['name'])[0]['name']
|
||||
default.update({'name': name+' (copy)'})
|
||||
|
|
|
@ -30,7 +30,7 @@ email_send_form = '''<?xml version="1.0"?>
|
|||
<newline/>
|
||||
<field name="subject"/>
|
||||
<newline/>
|
||||
<field name="text"/>
|
||||
<field name="text" widget="text_html"/>
|
||||
</form>'''
|
||||
|
||||
email_send_fields = {
|
||||
|
|
|
@ -191,15 +191,7 @@
|
|||
<rng:optional><rng:attribute name="position"/></rng:optional>
|
||||
<rng:zeroOrMore>
|
||||
<rng:choice>
|
||||
<rng:ref name="notebook" />
|
||||
<rng:ref name="graph" />
|
||||
<rng:ref name="calendar" />
|
||||
<rng:ref name="gantt" />
|
||||
<rng:ref name="form"/>
|
||||
<rng:ref name="tree"/>
|
||||
<rng:ref name="field"/>
|
||||
<rng:ref name="separator"/>
|
||||
<rng:ref name="page"/>
|
||||
<rng:ref name="any"/>
|
||||
<rng:ref name="button"/>
|
||||
</rng:choice>
|
||||
</rng:zeroOrMore>
|
||||
|
|
|
@ -143,6 +143,14 @@
|
|||
</rng:element>
|
||||
</rng:define>
|
||||
|
||||
<rng:define name="delete">
|
||||
<rng:element name="delete">
|
||||
<rng:attribute name="model" />
|
||||
<rng:optional><rng:attribute name="id" /> </rng:optional>
|
||||
<rng:optional><rng:attribute name="search" /></rng:optional>
|
||||
</rng:element>
|
||||
</rng:define>
|
||||
|
||||
<rng:define name="ir_set">
|
||||
<rng:element name="ir_set">
|
||||
<rng:oneOrMore>
|
||||
|
@ -196,6 +204,7 @@
|
|||
<rng:text/>
|
||||
<rng:ref name="menuitem" />
|
||||
<rng:ref name="record" />
|
||||
<rng:ref name="delete" />
|
||||
<rng:ref name="wizard" />
|
||||
<rng:ref name="act_window" />
|
||||
<rng:ref name="assert" />
|
||||
|
|
|
@ -182,29 +182,33 @@ import tools
|
|||
init_logger()
|
||||
|
||||
class Agent(object):
|
||||
_timers = []
|
||||
_timers = {}
|
||||
_logger = Logger()
|
||||
|
||||
def setAlarm(self, fn, dt, args=None, kwargs=None):
|
||||
if not args:
|
||||
args = []
|
||||
if not kwargs:
|
||||
kwargs = {}
|
||||
def setAlarm(self, fn, dt, db_name, *args, **kwargs):
|
||||
wait = dt - time.time()
|
||||
if wait > 0:
|
||||
self._logger.notifyChannel('timers', LOG_DEBUG, "Job scheduled in %s seconds for %s.%s" % (wait, fn.im_class.__name__, fn.func_name))
|
||||
timer = threading.Timer(wait, fn, args, kwargs)
|
||||
timer.start()
|
||||
self._timers.append(timer)
|
||||
for timer in self._timers[:]:
|
||||
if not timer.isAlive():
|
||||
self._timers.remove(timer)
|
||||
self._timers.setdefault(db_name, []).append(timer)
|
||||
|
||||
for db in self._timers:
|
||||
for timer in self._timers[db]:
|
||||
if not timer.isAlive():
|
||||
self._timers[db].remove(timer)
|
||||
|
||||
@classmethod
|
||||
def cancel(cls, db_name):
|
||||
"""Cancel all timers for a given database. If None passed, all timers are cancelled"""
|
||||
for db in cls._timers:
|
||||
if db_name is None or db == db_name:
|
||||
for timer in cls._timers[db]:
|
||||
timer.cancel()
|
||||
|
||||
@classmethod
|
||||
def quit(cls):
|
||||
for timer in cls._timers:
|
||||
timer.cancel()
|
||||
quit = classmethod(quit)
|
||||
|
||||
cls.cancel(None)
|
||||
|
||||
import traceback
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ class expression(object):
|
|||
if not self.__exp:
|
||||
return self
|
||||
|
||||
def _rec_get(ids, table, parent, left='id', prefix=''):
|
||||
def _rec_get(ids, table, parent=None, left='id', prefix=''):
|
||||
if table._parent_store and (not table.pool._init):
|
||||
# TODO: Improve where joins are implemented for many with '.', replace by:
|
||||
# doms += ['&',(prefix+'.parent_left','<',o.parent_right),(prefix+'.parent_left','>=',o.parent_left)]
|
||||
|
@ -90,7 +90,7 @@ class expression(object):
|
|||
return []
|
||||
ids2 = table.search(cr, uid, [(parent, 'in', ids)], context=context)
|
||||
return ids + rg(ids2, table, parent)
|
||||
return [(left, 'in', rg(ids, table, parent))]
|
||||
return [(left, 'in', rg(ids, table, parent or table._parent_name))]
|
||||
|
||||
self.__main_table = table
|
||||
|
||||
|
@ -114,7 +114,7 @@ class expression(object):
|
|||
field = working_table._columns.get(fargs[0], False)
|
||||
if not field:
|
||||
if left == 'id' and operator == 'child_of':
|
||||
dom = _rec_get(right, working_table, working_table._parent_name)
|
||||
dom = _rec_get(right, working_table)
|
||||
self.__exp = self.__exp[:i] + dom + self.__exp[i+1:]
|
||||
continue
|
||||
|
||||
|
@ -167,7 +167,7 @@ class expression(object):
|
|||
return ids
|
||||
return self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, ids)
|
||||
|
||||
dom = _rec_get(ids2, field_obj, working_table._parent_name)
|
||||
dom = _rec_get(ids2, field_obj)
|
||||
ids2 = field_obj.search(cr, uid, dom, context=context)
|
||||
self.__exp[i] = ('id', 'in', _rec_convert(ids2))
|
||||
else:
|
||||
|
@ -185,9 +185,9 @@ class expression(object):
|
|||
|
||||
self.__operator = 'in'
|
||||
if field._obj != working_table._name:
|
||||
dom = _rec_get(ids2, field_obj, working_table._parent_name, left=left, prefix=field._obj)
|
||||
dom = _rec_get(ids2, field_obj, left=left, prefix=field._obj)
|
||||
else:
|
||||
dom = _rec_get(ids2, working_table, left)
|
||||
dom = _rec_get(ids2, working_table, parent=left)
|
||||
self.__exp = self.__exp[:i] + dom + self.__exp[i+1:]
|
||||
else:
|
||||
if isinstance(right, basestring): # and not isinstance(field, fields.related):
|
||||
|
|
|
@ -308,11 +308,9 @@ class many2one(_column):
|
|||
names = dict(obj.name_get(cr, user, filter(None, res.values()), context))
|
||||
except except_orm:
|
||||
names = {}
|
||||
|
||||
iids = filter(None, res.values())
|
||||
cr.execute('select id,'+obj._rec_name+' from '+obj._table+' where id in ('+','.join(map(str, iids))+')')
|
||||
for res22 in cr.fetchall():
|
||||
names[res22[0]] = res22[1]
|
||||
for iiid in iids:
|
||||
names[iiid] = '// Access Denied //'
|
||||
|
||||
for r in res.keys():
|
||||
if res[r] and res[r] in names:
|
||||
|
@ -626,7 +624,7 @@ class function(_column):
|
|||
|
||||
if self._type == 'binary' and context.get('bin_size', False):
|
||||
# convert the data returned by the function with the size of that data...
|
||||
res = dict(map(lambda (x, y): (x, tools.human_size(len(y))), res.items()))
|
||||
res = dict(map(lambda (x, y): (x, tools.human_size(len(y or ''))), res.items()))
|
||||
return res
|
||||
|
||||
def set(self, cr, obj, id, name, value, user=None, context=None):
|
||||
|
|
177
bin/osv/orm.py
177
bin/osv/orm.py
|
@ -61,7 +61,7 @@ except ImportError:
|
|||
|
||||
from tools.config import config
|
||||
|
||||
regex_order = re.compile('^([a-zA-Z0-9_]+( desc)?( asc)?,?)+$', re.I)
|
||||
regex_order = re.compile('^([a-z0-9_]+( *desc| *asc)?( *, *|))+$', re.I)
|
||||
|
||||
def last_day_of_current_month():
|
||||
import datetime
|
||||
|
@ -101,7 +101,7 @@ class browse_null(object):
|
|||
|
||||
def __nonzero__(self):
|
||||
return False
|
||||
|
||||
|
||||
def __unicode__(self):
|
||||
return u''
|
||||
|
||||
|
@ -323,7 +323,7 @@ class orm_template(object):
|
|||
_inherits = {}
|
||||
_table = None
|
||||
_invalids = set()
|
||||
|
||||
|
||||
CONCURRENCY_CHECK_FIELD = '__last_update'
|
||||
|
||||
def _field_create(self, cr, context={}):
|
||||
|
@ -474,7 +474,7 @@ class orm_template(object):
|
|||
datas += self.__export_row(cr, uid, row, fields, context)
|
||||
return datas
|
||||
|
||||
def import_data(self, cr, uid, fields, datas, mode='init', current_module=None, noupdate=False, context=None, filename=None):
|
||||
def import_data(self, cr, uid, fields, datas, mode='init', current_module='', noupdate=False, context=None, filename=None):
|
||||
if not context:
|
||||
context = {}
|
||||
fields = map(lambda x: x.split('/'), fields)
|
||||
|
@ -735,7 +735,7 @@ class orm_template(object):
|
|||
model_access_obj = self.pool.get('ir.model.access')
|
||||
for parent in self._inherits:
|
||||
res.update(self.pool.get(parent).fields_get(cr, user, fields, context))
|
||||
|
||||
|
||||
if self._columns.keys():
|
||||
for f in self._columns.keys():
|
||||
if fields and f not in fields:
|
||||
|
@ -752,14 +752,14 @@ class orm_template(object):
|
|||
if hasattr(self._columns[f], arg) \
|
||||
and getattr(self._columns[f], arg):
|
||||
res[f][arg] = getattr(self._columns[f], arg)
|
||||
|
||||
|
||||
res_trans = translation_obj._get_source(cr, user, self._name + ',' + f, 'field', context.get('lang', False) or 'en_US')
|
||||
if res_trans:
|
||||
res[f]['string'] = res_trans
|
||||
help_trans = translation_obj._get_source(cr, user, self._name + ',' + f, 'help', context.get('lang', False) or 'en_US')
|
||||
if help_trans:
|
||||
res[f]['help'] = help_trans
|
||||
|
||||
|
||||
if hasattr(self._columns[f], 'selection'):
|
||||
if isinstance(self._columns[f].selection, (tuple, list)):
|
||||
sel = self._columns[f].selection
|
||||
|
@ -781,9 +781,9 @@ class orm_template(object):
|
|||
res[f]['domain'] = self._columns[f]._domain
|
||||
res[f]['context'] = self._columns[f]._context
|
||||
else:
|
||||
#TODO : read the fields from the database
|
||||
#TODO : read the fields from the database
|
||||
pass
|
||||
|
||||
|
||||
if fields:
|
||||
# filter out fields which aren't in the fields list
|
||||
for r in res.keys():
|
||||
|
@ -883,7 +883,7 @@ class orm_template(object):
|
|||
rolesobj = self.pool.get('res.roles')
|
||||
usersobj = self.pool.get('res.users')
|
||||
|
||||
buttons = xpath.Evaluate("//button[@type != 'object']", node)
|
||||
buttons = (n for n in node.getElementsByTagName('button') if n.getAttribute('type') != 'object')
|
||||
for button in buttons:
|
||||
ok = True
|
||||
if user != 1: # admin user has all roles
|
||||
|
@ -953,11 +953,11 @@ class orm_template(object):
|
|||
def fields_view_get(self, cr, user, view_id=None, view_type='form', context=None, toolbar=False):
|
||||
if not context:
|
||||
context = {}
|
||||
|
||||
|
||||
def encode(s):
|
||||
if isinstance(s, unicode):
|
||||
return s.encode('utf8')
|
||||
return s
|
||||
return s
|
||||
|
||||
def _inherit_apply(src, inherit):
|
||||
def _find(node, node2):
|
||||
|
@ -981,7 +981,7 @@ class orm_template(object):
|
|||
if res:
|
||||
return res
|
||||
return None
|
||||
|
||||
|
||||
|
||||
doc_src = dom.minidom.parseString(encode(src))
|
||||
doc_dest = dom.minidom.parseString(encode(inherit))
|
||||
|
@ -1390,7 +1390,7 @@ class orm_memory(orm_template):
|
|||
'id': id
|
||||
})
|
||||
return result
|
||||
|
||||
|
||||
def _check_removed_columns(self, cr, log=False):
|
||||
# nothing to check in memory...
|
||||
pass
|
||||
|
@ -1458,7 +1458,7 @@ class orm(orm_template):
|
|||
" AND c.oid=a.attrelid"
|
||||
" AND a.attisdropped=%%s"
|
||||
" AND pg_catalog.format_type(a.atttypid, a.atttypmod) NOT IN ('cid', 'tid', 'oid', 'xid')"
|
||||
" AND a.attname NOT IN (%s)" % ",".join(['%s']*len(columns)),
|
||||
" AND a.attname NOT IN (%s)" % ",".join(['%s']*len(columns)),
|
||||
[self._table, False] + columns)
|
||||
for column in cr.dictfetchall():
|
||||
if log:
|
||||
|
@ -1511,7 +1511,7 @@ class orm(orm_template):
|
|||
if not cr.rowcount:
|
||||
cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, logs[k]))
|
||||
cr.commit()
|
||||
|
||||
|
||||
self._check_removed_columns(cr, log=False)
|
||||
|
||||
# iterate on the "object columns"
|
||||
|
@ -1665,20 +1665,20 @@ class orm(orm_template):
|
|||
if isinstance(f, fields.many2one):
|
||||
ref = self.pool.get(f._obj)._table
|
||||
if ref != 'ir_actions':
|
||||
cr.execute('SELECT confdeltype, conname FROM pg_constraint as con, pg_class as cl1, pg_class as cl2, '
|
||||
'pg_attribute as att1, pg_attribute as att2 '
|
||||
'WHERE con.conrelid = cl1.oid '
|
||||
'AND cl1.relname = %s '
|
||||
'AND con.confrelid = cl2.oid '
|
||||
'AND cl2.relname = %s '
|
||||
'AND array_lower(con.conkey, 1) = 1 '
|
||||
'AND con.conkey[1] = att1.attnum '
|
||||
'AND att1.attrelid = cl1.oid '
|
||||
'AND att1.attname = %s '
|
||||
'AND array_lower(con.confkey, 1) = 1 '
|
||||
'AND con.confkey[1] = att2.attnum '
|
||||
'AND att2.attrelid = cl2.oid '
|
||||
'AND att2.attname = %s '
|
||||
cr.execute('SELECT confdeltype, conname FROM pg_constraint as con, pg_class as cl1, pg_class as cl2, '
|
||||
'pg_attribute as att1, pg_attribute as att2 '
|
||||
'WHERE con.conrelid = cl1.oid '
|
||||
'AND cl1.relname = %s '
|
||||
'AND con.confrelid = cl2.oid '
|
||||
'AND cl2.relname = %s '
|
||||
'AND array_lower(con.conkey, 1) = 1 '
|
||||
'AND con.conkey[1] = att1.attnum '
|
||||
'AND att1.attrelid = cl1.oid '
|
||||
'AND att1.attname = %s '
|
||||
'AND array_lower(con.confkey, 1) = 1 '
|
||||
'AND con.confkey[1] = att2.attnum '
|
||||
'AND att2.attrelid = cl2.oid '
|
||||
'AND att2.attname = %s '
|
||||
"AND con.contype = 'f'", (self._table, ref, k, 'id'))
|
||||
res = cr.dictfetchall()
|
||||
if res:
|
||||
|
@ -1725,7 +1725,7 @@ class orm(orm_template):
|
|||
|
||||
def __init__(self, cr):
|
||||
super(orm, self).__init__(cr)
|
||||
|
||||
|
||||
if not hasattr(self, '_log_access'):
|
||||
# if not access is not specify, it is the same value as _auto
|
||||
self._log_access = not hasattr(self, "_auto") or self._auto
|
||||
|
@ -1790,7 +1790,7 @@ class orm(orm_template):
|
|||
import random
|
||||
_rel1 = field['relation'].replace('.', '_')
|
||||
_rel2 = field['model'].replace('.', '_')
|
||||
_rel_name = 'x_%s_%s_%s_rel' %(_rel1, _rel2, random.randint(0, 10000))
|
||||
_rel_name = 'x_%s_%s_%s_rel' %(_rel1, _rel2, field['name'])
|
||||
self._columns[field['name']] = getattr(fields, field['ttype'])(field['relation'], _rel_name, 'id1', 'id2', **attrs)
|
||||
else:
|
||||
self._columns[field['name']] = getattr(fields, field['ttype'])(**attrs)
|
||||
|
@ -1925,7 +1925,7 @@ class orm(orm_template):
|
|||
|
||||
# all inherited fields + all non inherited fields for which the attribute whose name is in load is True
|
||||
fields_pre = [f for f in fields_to_read if
|
||||
f == self.CONCURRENCY_CHECK_FIELD
|
||||
f == self.CONCURRENCY_CHECK_FIELD
|
||||
or (f in self._columns and getattr(self._columns[f], '_classic_write'))
|
||||
] + self._inherits.values()
|
||||
|
||||
|
@ -2092,8 +2092,8 @@ class orm(orm_template):
|
|||
return "%s,%s" % (self._name, oid)
|
||||
santa = "(id = %s AND %s < COALESCE(write_date, create_date, now())::timestamp)"
|
||||
for i in range(0, len(ids), cr.IN_MAX):
|
||||
sub_ids = tools.flatten(((oid, context[self.CONCURRENCY_CHECK_FIELD][key(oid)])
|
||||
for oid in ids[i:i+cr.IN_MAX]
|
||||
sub_ids = tools.flatten(((oid, context[self.CONCURRENCY_CHECK_FIELD][key(oid)])
|
||||
for oid in ids[i:i+cr.IN_MAX]
|
||||
if key(oid) in context[self.CONCURRENCY_CHECK_FIELD]))
|
||||
if sub_ids:
|
||||
cr.execute("SELECT count(1) FROM %s WHERE %s" % (self._table, " OR ".join([santa]*(len(sub_ids)/2))), sub_ids)
|
||||
|
@ -2108,7 +2108,7 @@ class orm(orm_template):
|
|||
ids = [ids]
|
||||
|
||||
result_store = self._store_get_values(cr, uid, ids, None, context)
|
||||
|
||||
|
||||
self._check_concurrency(cr, ids, context)
|
||||
|
||||
self.pool.get('ir.model.access').check(cr, uid, self._name, 'unlink')
|
||||
|
@ -2147,10 +2147,11 @@ class orm(orm_template):
|
|||
|
||||
for order, object, ids, fields in result_store:
|
||||
if object<>self._name:
|
||||
cr.execute('select id from '+self._table+' where id in ('+','.join(map(str, ids))+')')
|
||||
obj = self.pool.get(object)
|
||||
cr.execute('select id from '+obj._table+' where id in ('+','.join(map(str, ids))+')')
|
||||
ids = map(lambda x: x[0], cr.fetchall())
|
||||
if ids:
|
||||
self.pool.get(object)._store_set_values(cr, uid, ids, fields, context)
|
||||
obj._store_set_values(cr, uid, ids, fields, context)
|
||||
return True
|
||||
|
||||
#
|
||||
|
@ -2302,60 +2303,42 @@ class orm(orm_template):
|
|||
self.pool._init_parent[self._name]=True
|
||||
else:
|
||||
for id in ids:
|
||||
# Find Position of the element
|
||||
if vals[self._parent_name]:
|
||||
cr.execute('select parent_left,parent_right,id from '+self._table+' where '+self._parent_name+'=%s order by '+(self._parent_order or self._order), (vals[self._parent_name],))
|
||||
pleft_old = pright_old = None
|
||||
result_p = cr.fetchall()
|
||||
for (pleft,pright,pid) in result_p:
|
||||
if pid == id:
|
||||
break
|
||||
pleft_old = pleft
|
||||
pright_old = pright
|
||||
if not pleft_old:
|
||||
cr.execute('select parent_left,parent_right from '+self._table+' where id=%s', (vals[self._parent_name],))
|
||||
pleft_old,pright_old = cr.fetchone()
|
||||
res = (pleft_old, pright_old)
|
||||
else:
|
||||
cr.execute('SELECT parent_left,parent_right FROM '+self._table+' WHERE id IS NULL')
|
||||
res = cr.fetchone()
|
||||
if res:
|
||||
pleft,pright = res
|
||||
else:
|
||||
cr.execute('select max(parent_right),max(parent_right)+1 from '+self._table)
|
||||
pleft,pright = cr.fetchone()
|
||||
cr.execute('select parent_left,parent_right,id from '+self._table+' where id in ('+','.join(map(lambda x:'%s',ids))+')', ids)
|
||||
dest = pleft + 1
|
||||
for cleft,cright,cid in cr.fetchall():
|
||||
if cleft > pleft:
|
||||
treeshift = pleft - cleft + 1
|
||||
leftbound = pleft+1
|
||||
rightbound = cleft-1
|
||||
cwidth = cright-cleft+1
|
||||
leftrange = cright
|
||||
rightrange = pleft
|
||||
cr.execute('select parent_left,parent_right,id from '+self._table+' where '+self._parent_name+' is null order by '+(self._parent_order or self._order))
|
||||
result_p = cr.fetchall()
|
||||
position = None
|
||||
for (pleft,pright,pid) in result_p:
|
||||
if pid == id:
|
||||
break
|
||||
position = pright+1
|
||||
|
||||
# It's the first node of the parent: position = parent_left+1
|
||||
if not position:
|
||||
if not vals[self._parent_name]:
|
||||
position = 1
|
||||
else:
|
||||
treeshift = pleft - cright
|
||||
leftbound = cright + 1
|
||||
rightbound = pleft
|
||||
cwidth = cleft-cright-1
|
||||
leftrange = pleft+1
|
||||
rightrange = cleft
|
||||
cr.execute('UPDATE '+self._table+'''
|
||||
SET
|
||||
parent_left = CASE
|
||||
WHEN parent_left BETWEEN %s AND %s THEN parent_left + %s
|
||||
WHEN parent_left BETWEEN %s AND %s THEN parent_left + %s
|
||||
ELSE parent_left
|
||||
END,
|
||||
parent_right = CASE
|
||||
WHEN parent_right BETWEEN %s AND %s THEN parent_right + %s
|
||||
WHEN parent_right BETWEEN %s AND %s THEN parent_right + %s
|
||||
ELSE parent_right
|
||||
END
|
||||
WHERE
|
||||
parent_left<%s OR parent_right>%s;
|
||||
''', (leftbound,rightbound,cwidth,cleft,cright,treeshift,leftbound,rightbound,
|
||||
cwidth,cleft,cright,treeshift,leftrange,rightrange))
|
||||
cr.execute('select parent_left from '+self._table+' where id=%s', (vals[self._parent_name],))
|
||||
position = cr.fetchone()[0]+1
|
||||
|
||||
# We have the new position !
|
||||
cr.execute('select parent_left,parent_right from '+self._table+' where id=%s', (id,))
|
||||
pleft,pright = cr.fetchone()
|
||||
distance = pright - pleft + 1
|
||||
|
||||
if position>pleft and position<=pright:
|
||||
raise except_orm(_('UserError'), _('Recursivity Detected.'))
|
||||
|
||||
if pleft<position:
|
||||
cr.execute('update '+self._table+' set parent_left=parent_left+%s where parent_left>=%s', (distance, position))
|
||||
cr.execute('update '+self._table+' set parent_right=parent_right+%s where parent_right>=%s', (distance, position))
|
||||
cr.execute('update '+self._table+' set parent_left=parent_left+%s, parent_right=parent_right+%s where parent_left>=%s and parent_left<%s', (position-pleft,position-pleft, pleft, pright))
|
||||
else:
|
||||
cr.execute('update '+self._table+' set parent_left=parent_left+%s where parent_left>=%s', (distance, position))
|
||||
cr.execute('update '+self._table+' set parent_right=parent_right+%s where parent_right>=%s', (distance, position))
|
||||
cr.execute('update '+self._table+' set parent_left=parent_left-%s, parent_right=parent_right-%s where parent_left>=%s and parent_left<%s', (pleft-position+distance,pleft-position+distance, pleft+distance, pright+distance))
|
||||
|
||||
result = self._store_get_values(cr, user, ids, vals.keys(), context)
|
||||
for order, object, ids, fields in result:
|
||||
|
@ -2418,12 +2401,12 @@ class orm(orm_template):
|
|||
|
||||
# Try-except added to filter the creation of those records whose filds are readonly.
|
||||
# Example : any dashboard which has all the fields readonly.(due to Views(database views))
|
||||
try:
|
||||
try:
|
||||
cr.execute("SELECT nextval('"+self._sequence+"')")
|
||||
except:
|
||||
raise except_orm(_('UserError'),
|
||||
_('You cannot perform this operation.'))
|
||||
|
||||
_('You cannot perform this operation.'))
|
||||
|
||||
id_new = cr.fetchone()[0]
|
||||
for table in tocreate:
|
||||
id = self.pool.get(table).create(cr, user, tocreate[table])
|
||||
|
@ -2508,15 +2491,20 @@ class orm(orm_template):
|
|||
for id in filter(None, ids2):
|
||||
result[fncts[fnct][0]].setdefault(id, [])
|
||||
result[fncts[fnct][0]][id].append(fnct)
|
||||
result2 = []
|
||||
dict = {}
|
||||
for object in result:
|
||||
k2 = {}
|
||||
for id,fnct in result[object].items():
|
||||
k2.setdefault(tuple(fnct), [])
|
||||
k2[tuple(fnct)].append(id)
|
||||
for fnct,id in k2.items():
|
||||
result2.append((fncts[fnct[0]][4],object,id,map(lambda x: fncts[x][1], fnct)))
|
||||
result2.sort()
|
||||
dict.setdefault(fncts[fnct[0]][4],[])
|
||||
dict[fncts[fnct[0]][4]].append((fncts[fnct[0]][4],object,id,map(lambda x: fncts[x][1], fnct)))
|
||||
result2 = []
|
||||
tmp = dict.keys()
|
||||
tmp.sort()
|
||||
for k in tmp:
|
||||
result2+=dict[k]
|
||||
return result2
|
||||
|
||||
def _store_set_values(self, cr, uid, ids, fields, context):
|
||||
|
@ -2737,6 +2725,7 @@ class orm(orm_template):
|
|||
return data, trans_data
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
trans_obj = self.pool.get('ir.translation')
|
||||
data, trans_data = self.copy_data(cr, uid, id, default, context)
|
||||
new_id=self.create(cr, uid, data)
|
||||
for record in trans_data:
|
||||
|
|
|
@ -57,6 +57,7 @@ def get_db_and_pool(db_name, force_demo=False, status=None, update_module=False)
|
|||
|
||||
def restart_pool(db_name, force_demo=False, status=None, update_module=False):
|
||||
if db_name in pool_dic:
|
||||
pool_dic[db_name].get('ir.cron').cancel(db_name)
|
||||
del pool_dic[db_name]
|
||||
return get_db_and_pool(db_name, force_demo, status, update_module=update_module)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
||||
# $Id$
|
||||
#
|
||||
|
@ -94,7 +94,6 @@ class _flowable(object):
|
|||
if node.hasAttribute('style'):
|
||||
node.setAttribute('class', node.getAttribute('style'))
|
||||
return node.toxml()
|
||||
|
||||
def render(self, node):
|
||||
result = self.template.start()
|
||||
result += self.template.frame_start()
|
||||
|
@ -107,8 +106,7 @@ class _flowable(object):
|
|||
#print 'tag', n.localName, 'not yet implemented!'
|
||||
result += self.template.frame_stop()
|
||||
result += self.template.end()
|
||||
return result
|
||||
|
||||
return result.encode('utf-8').replace('"',"\'").replace('°','°')
|
||||
class _rml_tmpl_tag(object):
|
||||
def __init__(self, *args):
|
||||
pass
|
||||
|
@ -126,7 +124,7 @@ class _rml_tmpl_frame(_rml_tmpl_tag):
|
|||
self.width = width
|
||||
self.posx = posx
|
||||
def tag_start(self):
|
||||
return '<table border="0" width="%d"><tr><td width="%d"> </td><td>' % (self.width+self.posx,self.posx)
|
||||
return "<table border=\'0\' width=\'%d\'><tr><td width=\'%d\'> </td><td>" % (self.width+self.posx,self.posx)
|
||||
def tag_end(self):
|
||||
return True
|
||||
def tag_stop(self):
|
||||
|
@ -152,19 +150,19 @@ class _rml_tmpl_draw_string(_rml_tmpl_tag):
|
|||
|
||||
def tag_start(self):
|
||||
self.pos.sort()
|
||||
res = '<table border="0" cellpadding="0" cellspacing="0"><tr>'
|
||||
res = "<table border='0' cellpadding='0' cellspacing='0'><tr>"
|
||||
posx = 0
|
||||
i = 0
|
||||
for (x,y,align,txt, style, fs) in self.pos:
|
||||
if align=="left":
|
||||
pos2 = len(txt)*fs
|
||||
res+='<td width="%d"></td><td style="%s" width="%d">%s</td>' % (x - posx, style, pos2, txt)
|
||||
res+="<td width=\'%d\'></td><td style=\'%s\' width=\'%d\'>%s</td>" % (x - posx, style, pos2, txt)
|
||||
posx = x+pos2
|
||||
if align=="right":
|
||||
res+='<td width="%d" align="right" style="%s">%s</td>' % (x - posx, style, txt)
|
||||
res+="<td width=\'%d\' align=\'right\' style=\'%s\'>%s</td>" % (x - posx, style, txt)
|
||||
posx = x
|
||||
if align=="center":
|
||||
res+='<td width="%d" align="center" style="%s">%s</td>' % ((x - posx)*2, style, txt)
|
||||
res+="<td width=\'%d\' align=\'center\' style=\'%s\'>%s</td>" % ((x - posx)*2, style, txt)
|
||||
posx = 2*x-posx
|
||||
i+=1
|
||||
res+='</tr></table>'
|
||||
|
@ -185,7 +183,7 @@ class _rml_tmpl_draw_lines(_rml_tmpl_tag):
|
|||
|
||||
def tag_start(self):
|
||||
if self.ok:
|
||||
return '<table border="0" cellpadding="0" cellspacing="0" width="%d"><tr><td width="%d"></td><td><hr width="100%%" style="margin:0px; %s"></td></tr></table>' % (self.posx+self.width,self.posx,self.style)
|
||||
return "<table border=\'0\' cellpadding=\'0\' cellspacing=\'0\' width=\'%d\'><tr><td width=\'%d\'></td><td><hr width=\'100%%\' style=\'margin:0px; %s\'></td></tr></table>" % (self.posx+self.width,self.posx,self.style)
|
||||
else:
|
||||
return ''
|
||||
|
||||
|
@ -207,9 +205,9 @@ class _rml_stylesheet(object):
|
|||
attrs = []
|
||||
for a in attr:
|
||||
if a in self._tags:
|
||||
attrs.append("%s:%s" % self._tags[a](attr[a]))
|
||||
attrs.append('%s:%s' % self._tags[a](attr[a]))
|
||||
if len(attrs):
|
||||
result += "p."+attr['name']+" {"+'; '.join(attrs)+"}\n"
|
||||
result += 'p.'+attr['name']+' {'+'; '.join(attrs)+'}\n'
|
||||
self.result = result
|
||||
|
||||
def render(self):
|
||||
|
@ -338,6 +336,7 @@ class _rml_doc(object):
|
|||
self.result += '''<!DOCTYPE HTML PUBLIC "-//w3c//DTD HTML 4.0 Frameset//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<style type="text/css">
|
||||
p {margin:0px; font-size:12px;}
|
||||
td {font-size:14px;}
|
||||
|
@ -347,14 +346,50 @@ class _rml_doc(object):
|
|||
self.result += s.render()
|
||||
self.result+='''
|
||||
</style>
|
||||
</head>
|
||||
<body>'''
|
||||
'''
|
||||
|
||||
template = _rml_template(self.dom.documentElement.getElementsByTagName('template')[0])
|
||||
f = _flowable(template, self.dom)
|
||||
self.result += f.render(self.dom.documentElement.getElementsByTagName('story')[0])
|
||||
|
||||
# f = _flowable(template, self.dom)
|
||||
list_story =[]
|
||||
storys= self.dom.documentElement.getElementsByTagName('story')
|
||||
for story in storys :
|
||||
template = _rml_template(self.dom.documentElement.getElementsByTagName('template')[0])
|
||||
f = _flowable(template, self.dom)
|
||||
story_text = f.render(story)
|
||||
list_story.append(story_text)
|
||||
del f
|
||||
self.result += '</body></html>'
|
||||
self.result +='''
|
||||
<script type="text/javascript">
|
||||
|
||||
var indexer = 0;
|
||||
var aryTest = %s ;
|
||||
function nextData()
|
||||
{
|
||||
if(indexer < aryTest.length -1)
|
||||
{
|
||||
indexer += 1;
|
||||
document.getElementById("tiny_data").innerHTML=aryTest[indexer];
|
||||
}
|
||||
}
|
||||
function prevData()
|
||||
{
|
||||
if (indexer > 0)
|
||||
{
|
||||
indexer -= 1;
|
||||
document.getElementById("tiny_data").innerHTML=aryTest[indexer];
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="tiny_data">
|
||||
%s
|
||||
</div>
|
||||
<br>
|
||||
<input type="button" value="next" onclick="nextData();">
|
||||
<input type="button" value="prev" onclick="prevData();">
|
||||
|
||||
</body></html>'''%(list_story,list_story[0])
|
||||
out.write( self.result)
|
||||
|
||||
def parseString(data, fout=None):
|
||||
|
@ -383,5 +418,4 @@ if __name__=="__main__":
|
|||
print 'Usage: trml2pdf input.rml >output.pdf'
|
||||
print 'Try \'trml2pdf --help\' for more information.'
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -519,8 +519,8 @@ class rml_parse(object):
|
|||
if not self.logo and rml_head.find('company.logo')>=0:
|
||||
rml_head = rml_head.replace('<image','<!--image')
|
||||
rml_head = rml_head.replace('</image>','</image-->')
|
||||
|
||||
head_dom = xml.dom.minidom.parseString(rml_head)
|
||||
|
||||
head_dom = xml.dom.minidom.parseString(rml_head.encode('utf-8'))
|
||||
#for frame in head_dom.getElementsByTagName('frame'):
|
||||
# frame.parentNode.removeChild(frame)
|
||||
node2 = head_dom.documentElement
|
||||
|
|
|
@ -40,11 +40,10 @@ def check_super(passwd):
|
|||
return True
|
||||
else:
|
||||
raise Exception('AccessDenied')
|
||||
|
||||
|
||||
def check(db, uid, passwd):
|
||||
if _uid_cache.get(db, {}).get(uid) == passwd:
|
||||
return True
|
||||
|
||||
cr = pooler.get_db(db).cursor()
|
||||
cr.execute('select count(*) from res_users where id=%s and password=%s', (int(uid), passwd))
|
||||
res = cr.fetchone()[0]
|
||||
|
|
|
@ -82,7 +82,7 @@ class configmanager(object):
|
|||
|
||||
hasSSL = check_ssl()
|
||||
|
||||
loglevels = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x))
|
||||
self._LOGLEVELS = dict([(getattr(netsvc, 'LOG_%s' % x), getattr(logging, x))
|
||||
for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'DEBUG_RPC', 'NOTSET')])
|
||||
|
||||
version = "%s %s" % (release.description, release.version)
|
||||
|
@ -111,8 +111,8 @@ class configmanager(object):
|
|||
parser.add_option("--stop-after-init", action="store_true", dest="stop_after_init", default=False,
|
||||
help="stop the server after it initializes")
|
||||
parser.add_option('--debug', dest='debug_mode', action='store_true', default=False, help='enable debug mode')
|
||||
parser.add_option("--assert-exit-level", dest='assert_exit_level', type="choice", choices=loglevels.keys(),
|
||||
help="specify the level at which a failed assertion will stop the server. Accepted values: %s" % (loglevels.keys(),))
|
||||
parser.add_option("--assert-exit-level", dest='assert_exit_level', type="choice", choices=self._LOGLEVELS.keys(),
|
||||
help="specify the level at which a failed assertion will stop the server. Accepted values: %s" % (self._LOGLEVELS.keys(),))
|
||||
if hasSSL:
|
||||
group = optparse.OptionGroup(parser, "SSL Configuration")
|
||||
group.add_option("-S", "--secure", dest="secure", action="store_true",
|
||||
|
@ -130,8 +130,8 @@ class configmanager(object):
|
|||
group.add_option("--logfile", dest="logfile", help="file where the server log will be stored")
|
||||
group.add_option("--syslog", action="store_true", dest="syslog",
|
||||
default=False, help="Send the log to the syslog server")
|
||||
group.add_option('--log-level', dest='log_level', type='choice', choices=loglevels.keys(),
|
||||
help='specify the level of the logging. Accepted values: ' + str(loglevels.keys()))
|
||||
group.add_option('--log-level', dest='log_level', type='choice', choices=self._LOGLEVELS.keys(),
|
||||
help='specify the level of the logging. Accepted values: ' + str(self._LOGLEVELS.keys()))
|
||||
parser.add_option_group(group)
|
||||
|
||||
# SMTP Group
|
||||
|
@ -235,10 +235,14 @@ class configmanager(object):
|
|||
self.options[arg] = getattr(opt, arg)
|
||||
|
||||
if opt.assert_exit_level:
|
||||
self.options['assert_exit_level'] = loglevels[opt.assert_exit_level]
|
||||
self.options['assert_exit_level'] = self._LOGLEVELS[opt.assert_exit_level]
|
||||
else:
|
||||
self.options['assert_exit_level'] = self._LOGLEVELS.get(self.options['assert_exit_level']) or int(self.options['assert_exit_level'])
|
||||
|
||||
if opt.log_level:
|
||||
self.options['log_level'] = loglevels[opt.log_level]
|
||||
self.options['log_level'] = self._LOGLEVELS[opt.log_level]
|
||||
else:
|
||||
self.options['log_level'] = self._LOGLEVELS.get(self.options['log_level']) or int(self.options['log_level'])
|
||||
|
||||
if not self.options['root_path'] or self.options['root_path']=='None':
|
||||
self.options['root_path'] = os.path.abspath(os.path.dirname(sys.argv[0]))
|
||||
|
@ -335,9 +339,15 @@ class configmanager(object):
|
|||
|
||||
def save(self):
|
||||
p = ConfigParser.ConfigParser()
|
||||
loglevelnames = dict(zip(self._LOGLEVELS.values(), self._LOGLEVELS.keys()))
|
||||
p.add_section('options')
|
||||
for o in [opt for opt in self.options.keys() if opt not in ('version','language','translate_out','translate_in','init','update')]:
|
||||
p.set('options', o, self.options[o])
|
||||
for opt in self.options.keys():
|
||||
if opt in ('version', 'language', 'translate_out', 'translate_in', 'init', 'update'):
|
||||
continue
|
||||
if opt in ('log_level', 'assert_exit_level'):
|
||||
p.set('options', opt, loglevelnames.get(self.options[opt], self.options[opt]))
|
||||
else:
|
||||
p.set('options', opt, self.options[opt])
|
||||
|
||||
# try to create the directories and write the file
|
||||
try:
|
||||
|
@ -345,6 +355,7 @@ class configmanager(object):
|
|||
os.makedirs(os.path.dirname(self.rcfile))
|
||||
try:
|
||||
p.write(file(self.rcfile, 'w'))
|
||||
os.chmod(self.rcfile, 0600)
|
||||
except IOError:
|
||||
sys.stderr.write("ERROR: couldn't write the config file\n")
|
||||
|
||||
|
|
|
@ -302,7 +302,8 @@ def reverse_enumerate(l):
|
|||
#----------------------------------------------------------
|
||||
# Emails
|
||||
#----------------------------------------------------------
|
||||
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'):
|
||||
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', x_headers=None):
|
||||
"""Send an email."""
|
||||
import smtplib
|
||||
from email.MIMEText import MIMEText
|
||||
|
@ -313,9 +314,15 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
|
|||
from email.Utils import formatdate, COMMASPACE
|
||||
from email import Encoders
|
||||
|
||||
if x_headers is None:
|
||||
x_headers = {}
|
||||
|
||||
if not ssl:
|
||||
ssl = config.get('smtp_ssl', False)
|
||||
|
||||
if not email_from and not config['email_from']:
|
||||
raise Exception("No Email sender by default, see config file")
|
||||
|
||||
if not email_cc:
|
||||
email_cc = []
|
||||
if not email_bcc:
|
||||
|
@ -326,11 +333,13 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
|
|||
else:
|
||||
msg = MIMEMultipart()
|
||||
|
||||
msg['Subject'] = Header(subject.decode('utf8'), 'utf-8')
|
||||
msg['Subject'] = Header(ustr(subject), 'utf-8')
|
||||
msg['From'] = email_from
|
||||
del msg['Reply-To']
|
||||
if reply_to:
|
||||
msg['Reply-To'] = msg['From']+', '+reply_to
|
||||
msg['Reply-To'] = reply_to
|
||||
else:
|
||||
msg['Reply-To'] = msg['From']
|
||||
msg['To'] = COMMASPACE.join(email_to)
|
||||
if email_cc:
|
||||
msg['Cc'] = COMMASPACE.join(email_cc)
|
||||
|
@ -338,6 +347,15 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
|
|||
msg['Bcc'] = COMMASPACE.join(email_bcc)
|
||||
msg['Date'] = formatdate(localtime=True)
|
||||
|
||||
# Add OpenERP Server information
|
||||
msg['X-Generated-By'] = 'OpenERP (http://www.openerp.com)'
|
||||
msg['X-OpenERP-Server-Host'] = socket.gethostname()
|
||||
msg['X-OpenERP-Server-Version'] = release.version
|
||||
|
||||
# Add dynamic X Header
|
||||
for key, value in x_headers.items():
|
||||
msg['X-OpenERP-%s' % key] = str(value)
|
||||
|
||||
if tinycrm:
|
||||
msg['Message-Id'] = "<%s-tinycrm-%s@%s>" % (time.time(), tinycrm, socket.gethostname())
|
||||
|
||||
|
@ -381,9 +399,10 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
|
|||
# text must be latin-1 encoded
|
||||
def sms_send(user, password, api_id, text, to):
|
||||
import urllib
|
||||
params = urllib.urlencode({'user': user, 'password': password, 'api_id': api_id, 'text': text, 'to':to})
|
||||
#f = urllib.urlopen("http://api.clickatell.com/http/sendmsg", params)
|
||||
f = urllib.urlopen("http://196.7.150.220/http/sendmsg", params)
|
||||
url = "http://api.urlsms.com/SendSMS.aspx"
|
||||
#url = "http://196.7.150.220/http/sendmsg"
|
||||
params = urllib.urlencode({'UserID': user, 'Password': password, 'SenderID': api_id, 'MsgText': text, 'RecipientMobileNo':to})
|
||||
f = urllib.urlopen(url+"?"+params)
|
||||
# FIXME: Use the logger if there is an error
|
||||
return True
|
||||
|
||||
|
|
Loading…
Reference in New Issue