[MERGE] merged latest fixes from 6.0 branch up to rev 3348
Rev 3348 is odo@openerp.com-20110221101549-vp0ha2g91yl30cmk. bzr revid: odo@openerp.com-20110221103235-6tdy5tpb6zvkbzs3
This commit is contained in:
commit
2621b707e0
|
@ -1086,7 +1086,7 @@
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="VEB" model="res.currency">
|
<record id="VEB" model="res.currency">
|
||||||
<field name="name">Bs</field>
|
<field name="name">VEB</field>
|
||||||
<field name="symbol">Bs</field>
|
<field name="symbol">Bs</field>
|
||||||
<field name="rounding">2.95</field>
|
<field name="rounding">2.95</field>
|
||||||
<field name="accuracy">4</field>
|
<field name="accuracy">4</field>
|
||||||
|
@ -1166,7 +1166,7 @@
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="CZK" model="res.currency">
|
<record id="CZK" model="res.currency">
|
||||||
<field name="name">Kč</field>
|
<field name="name">CZK</field>
|
||||||
<field name="symbol">Kč</field>
|
<field name="symbol">Kč</field>
|
||||||
<field name="rounding">0.01</field>
|
<field name="rounding">0.01</field>
|
||||||
<field name="accuracy">4</field>
|
<field name="accuracy">4</field>
|
||||||
|
@ -1193,7 +1193,7 @@
|
||||||
|
|
||||||
|
|
||||||
<record id="HUF" model="res.currency">
|
<record id="HUF" model="res.currency">
|
||||||
<field name="name">Ft</field>
|
<field name="name">HUF</field>
|
||||||
<field name="symbol">Ft</field>
|
<field name="symbol">Ft</field>
|
||||||
<field name="rounding">0.01</field>
|
<field name="rounding">0.01</field>
|
||||||
<field name="accuracy">4</field>
|
<field name="accuracy">4</field>
|
||||||
|
@ -1206,7 +1206,7 @@
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="IDR" model="res.currency">
|
<record id="IDR" model="res.currency">
|
||||||
<field name="name">Rp</field>
|
<field name="name">IDR</field>
|
||||||
<field name="symbol">Rp</field>
|
<field name="symbol">Rp</field>
|
||||||
<field name="rounding">0.01</field>
|
<field name="rounding">0.01</field>
|
||||||
<field name="accuracy">4</field>
|
<field name="accuracy">4</field>
|
||||||
|
@ -1224,7 +1224,7 @@
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="LVL" model="res.currency">
|
<record id="LVL" model="res.currency">
|
||||||
<field name="name">Ls</field>
|
<field name="name">LVL</field>
|
||||||
<field name="symbol">Ls</field>
|
<field name="symbol">Ls</field>
|
||||||
<field name="rounding">0.01</field>
|
<field name="rounding">0.01</field>
|
||||||
<field name="accuracy">4</field>
|
<field name="accuracy">4</field>
|
||||||
|
@ -1277,7 +1277,7 @@
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="PLN" model="res.currency">
|
<record id="PLN" model="res.currency">
|
||||||
<field name="name">zł</field>
|
<field name="name">PLN</field>
|
||||||
<field name="symbol">zł</field>
|
<field name="symbol">zł</field>
|
||||||
<field name="rounding">0.01</field>
|
<field name="rounding">0.01</field>
|
||||||
<field name="accuracy">4</field>
|
<field name="accuracy">4</field>
|
||||||
|
@ -1329,7 +1329,7 @@
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="INR" model="res.currency">
|
<record id="INR" model="res.currency">
|
||||||
<field name="name">Rs</field>
|
<field name="name">INR</field>
|
||||||
<field name="symbol">Rs</field>
|
<field name="symbol">Rs</field>
|
||||||
<field name="rounding">0.01</field>
|
<field name="rounding">0.01</field>
|
||||||
<field name="accuracy">4</field>
|
<field name="accuracy">4</field>
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
|
import itertools
|
||||||
|
|
||||||
from osv import fields,osv
|
from osv import fields,osv
|
||||||
from osv.orm import except_orm
|
from osv.orm import except_orm
|
||||||
import tools
|
import tools
|
||||||
|
@ -40,17 +42,17 @@ class ir_attachment(osv.osv):
|
||||||
for rmod, rid in cr.fetchall():
|
for rmod, rid in cr.fetchall():
|
||||||
if not (rmod and rid):
|
if not (rmod and rid):
|
||||||
continue
|
continue
|
||||||
res_ids.setdefault(rmod,[]).append(rid)
|
res_ids.setdefault(rmod,set()).add(rid)
|
||||||
if values:
|
if values:
|
||||||
if 'res_model' in values and 'res_id' in values:
|
if 'res_model' in values and 'res_id' in values:
|
||||||
res_ids.setdefault(values['res_model'],[]).append(values['res_id'])
|
res_ids.setdefault(values['res_model'],set()).add(values['res_id'])
|
||||||
|
|
||||||
for model, mids in res_ids.items():
|
for model, mids in res_ids.items():
|
||||||
# ignore attachments that are not attached to a resource anymore when checking access rights
|
# ignore attachments that are not attached to a resource anymore when checking access rights
|
||||||
# (resource was deleted but attachment was not)
|
# (resource was deleted but attachment was not)
|
||||||
cr.execute('select id from '+self.pool.get(model)._table+' where id in %s', (tuple(mids),))
|
cr.execute('select id from '+self.pool.get(model)._table+' where id in %s', (tuple(mids),))
|
||||||
mids = [x[0] for x in cr.fetchall()]
|
mids = [x[0] for x in cr.fetchall()]
|
||||||
|
ima.check(cr, uid, model, mode, context=context)
|
||||||
self.pool.get(model).check_access_rule(cr, uid, mids, mode, context=context)
|
self.pool.get(model).check_access_rule(cr, uid, mids, mode, context=context)
|
||||||
|
|
||||||
def search(self, cr, uid, args, offset=0, limit=None, order=None,
|
def search(self, cr, uid, args, offset=0, limit=None, order=None,
|
||||||
|
@ -62,17 +64,35 @@ class ir_attachment(osv.osv):
|
||||||
if count:
|
if count:
|
||||||
return 0
|
return 0
|
||||||
return []
|
return []
|
||||||
models = super(ir_attachment,self).read(cr, uid, ids, ['id', 'res_model'])
|
|
||||||
cache = {}
|
|
||||||
ima = self.pool.get('ir.model.access')
|
|
||||||
for m in models:
|
|
||||||
if m['res_model']:
|
|
||||||
if m['res_model'] not in cache:
|
|
||||||
cache[m['res_model']] = ima.check(cr, uid, m['res_model'], 'read',
|
|
||||||
raise_exception=False, context=context)
|
|
||||||
if not cache[m['res_model']]:
|
|
||||||
ids.remove(m['id'])
|
|
||||||
|
|
||||||
|
# For attachments, the permissions of the document they are attached to
|
||||||
|
# apply, so we must remove attachments for which the user cannot access
|
||||||
|
# the linked document.
|
||||||
|
targets = super(ir_attachment,self).read(cr, uid, ids, ['id', 'res_model', 'res_id'])
|
||||||
|
model_attachments = {}
|
||||||
|
for target_dict in targets:
|
||||||
|
if not (target_dict['res_id'] and target_dict['res_model']):
|
||||||
|
continue
|
||||||
|
# model_attachments = { 'model': { 'res_id': [id1,id2] } }
|
||||||
|
model_attachments.setdefault(target_dict['res_model'],{}).setdefault(target_dict['res_id'],set()).add(target_dict['id'])
|
||||||
|
|
||||||
|
# To avoid multiple queries for each attachment found, checks are
|
||||||
|
# performed in batch as much as possible.
|
||||||
|
ima = self.pool.get('ir.model.access')
|
||||||
|
for model, targets in model_attachments.iteritems():
|
||||||
|
if not ima.check(cr, uid, model, 'read', raise_exception=False, context=context):
|
||||||
|
# remove all corresponding attachment ids
|
||||||
|
for attach_id in itertools.chain(*targets.values()):
|
||||||
|
ids.remove(attach_id)
|
||||||
|
continue # skip ir.rule processing, these ones are out already
|
||||||
|
|
||||||
|
# filter ids according to what access rules permit
|
||||||
|
target_ids = targets.keys()
|
||||||
|
allowed_ids = self.pool.get(model).search(cr, uid, [('id', 'in', target_ids)], context=context)
|
||||||
|
disallowed_ids = set(target_ids).difference(allowed_ids)
|
||||||
|
for res_id in disallowed_ids:
|
||||||
|
for attach_id in targets[res_id]:
|
||||||
|
ids.remove(attach_id)
|
||||||
if count:
|
if count:
|
||||||
return len(ids)
|
return len(ids)
|
||||||
return ids
|
return ids
|
||||||
|
@ -135,7 +155,7 @@ class ir_attachment(osv.osv):
|
||||||
'create_uid': fields.many2one('res.users', 'Owner', readonly=True),
|
'create_uid': fields.many2one('res.users', 'Owner', readonly=True),
|
||||||
'company_id': fields.many2one('res.company', 'Company', change_default=True),
|
'company_id': fields.many2one('res.company', 'Company', change_default=True),
|
||||||
}
|
}
|
||||||
|
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'type': 'binary',
|
'type': 'binary',
|
||||||
'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'ir.attachment', context=c),
|
'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'ir.attachment', context=c),
|
||||||
|
|
|
@ -149,22 +149,31 @@ class ir_cron(osv.osv, netsvc.Agent):
|
||||||
# Reschedule cron processing job asap, but not in the current thread
|
# Reschedule cron processing job asap, but not in the current thread
|
||||||
self.setAlarm(self._poolJobs, time.time(), dbname, dbname)
|
self.setAlarm(self._poolJobs, time.time(), dbname, dbname)
|
||||||
|
|
||||||
|
def update_running_cron(self, cr):
|
||||||
|
# Verify whether the server is already started and thus whether we need to commit
|
||||||
|
# immediately our changes and restart the cron agent in order to apply the change
|
||||||
|
# immediately. The commit() is needed because as soon as the cron is (re)started it
|
||||||
|
# will query the database with its own cursor, possibly before the end of the
|
||||||
|
# current transaction.
|
||||||
|
# This commit() is not an issue in most cases, but we must absolutely avoid it
|
||||||
|
# when the server is only starting or loading modules (hence the test on pool._init).
|
||||||
|
if not self.pool._init:
|
||||||
|
cr.commit()
|
||||||
|
self.restart(cr.dbname)
|
||||||
|
|
||||||
def create(self, cr, uid, vals, context=None):
|
def create(self, cr, uid, vals, context=None):
|
||||||
res = super(ir_cron, self).create(cr, uid, vals, context=context)
|
res = super(ir_cron, self).create(cr, uid, vals, context=context)
|
||||||
cr.commit()
|
self.update_running_cron(cr)
|
||||||
self.restart(cr.dbname)
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def write(self, cr, user, ids, vals, context=None):
|
def write(self, cr, user, ids, vals, context=None):
|
||||||
res = super(ir_cron, self).write(cr, user, ids, vals, context=context)
|
res = super(ir_cron, self).write(cr, user, ids, vals, context=context)
|
||||||
cr.commit()
|
self.update_running_cron(cr)
|
||||||
self.restart(cr.dbname)
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def unlink(self, cr, uid, ids, context=None):
|
def unlink(self, cr, uid, ids, context=None):
|
||||||
res = super(ir_cron, self).unlink(cr, uid, ids, context=context)
|
res = super(ir_cron, self).unlink(cr, uid, ids, context=context)
|
||||||
cr.commit()
|
self.update_running_cron(cr)
|
||||||
self.restart(cr.dbname)
|
|
||||||
return res
|
return res
|
||||||
ir_cron()
|
ir_cron()
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,9 @@ class res_currency(osv.osv):
|
||||||
_name = "res.currency"
|
_name = "res.currency"
|
||||||
_description = "Currency"
|
_description = "Currency"
|
||||||
_columns = {
|
_columns = {
|
||||||
'name': fields.char('Currency', size=32, required=True),
|
# Note: 'code' column was removed as of v6.0, the 'name' should now hold the ISO code.
|
||||||
'symbol': fields.char('Symbol', size=3),
|
'name': fields.char('Currency', size=32, required=True, help="Currency Code (ISO 4217)"),
|
||||||
|
'symbol': fields.char('Symbol', size=3, help="Currency sign, to be used when printing amounts"),
|
||||||
'rate': fields.function(_current_rate, method=True, string='Current Rate', digits=(12,6),
|
'rate': fields.function(_current_rate, method=True, string='Current Rate', digits=(12,6),
|
||||||
help='The rate of the currency to the currency of rate 1'),
|
help='The rate of the currency to the currency of rate 1'),
|
||||||
'rate_ids': fields.one2many('res.currency.rate', 'currency_id', 'Rates'),
|
'rate_ids': fields.one2many('res.currency.rate', 'currency_id', 'Rates'),
|
||||||
|
|
|
@ -240,6 +240,13 @@ class browse_record(object):
|
||||||
# testing to be sure we got the right
|
# testing to be sure we got the right
|
||||||
# object and not the parent one.
|
# object and not the parent one.
|
||||||
if not isinstance(value, browse_record):
|
if not isinstance(value, browse_record):
|
||||||
|
if obj is None:
|
||||||
|
# In some cases the target model is not available yet, so we must ignore it,
|
||||||
|
# which is safe in most cases, this value will just be loaded later when needed.
|
||||||
|
# This situation can be caused by custom fields that connect objects with m2o without
|
||||||
|
# respecting module dependencies, causing relationships to be connected to soon when
|
||||||
|
# the target is not loaded yet.
|
||||||
|
continue
|
||||||
new_data[field_name] = browse_record(self._cr,
|
new_data[field_name] = browse_record(self._cr,
|
||||||
self._uid, value, obj, self._cache,
|
self._uid, value, obj, self._cache,
|
||||||
context=self._context,
|
context=self._context,
|
||||||
|
@ -272,7 +279,7 @@ class browse_record(object):
|
||||||
self._data[result_line['id']].update(new_data)
|
self._data[result_line['id']].update(new_data)
|
||||||
|
|
||||||
if not name in self._data[self._id]:
|
if not name in self._data[self._id]:
|
||||||
#how did this happen?
|
# How did this happen? Could be a missing model due to custom fields used too soon, see above.
|
||||||
self.logger.notifyChannel("browse_record", netsvc.LOG_ERROR,
|
self.logger.notifyChannel("browse_record", netsvc.LOG_ERROR,
|
||||||
"Fields to fetch: %s, Field values: %s"%(field_names, field_values))
|
"Fields to fetch: %s, Field values: %s"%(field_names, field_values))
|
||||||
self.logger.notifyChannel("browse_record", netsvc.LOG_ERROR,
|
self.logger.notifyChannel("browse_record", netsvc.LOG_ERROR,
|
||||||
|
|
Loading…
Reference in New Issue