Denis Ledoux 2013-12-09 16:57:21 +01:00
commit 20be322c45
12 changed files with 135 additions and 72 deletions

View File

@ -28,7 +28,7 @@ import time
import openerp
from openerp import SUPERUSER_ID
from openerp import tools
from openerp.osv import fields, osv
from openerp.osv import fields, osv, expression
from openerp.tools.translate import _
from openerp.tools.float_utils import float_round
@ -579,15 +579,18 @@ class account_account(osv.osv):
except:
pass
if name:
ids = self.search(cr, user, [('code', '=like', name+"%")]+args, limit=limit)
if not ids:
ids = self.search(cr, user, [('shortcut', '=', name)]+ args, limit=limit)
if not ids:
ids = self.search(cr, user, [('name', operator, name)]+ args, limit=limit)
if not ids and len(name.split()) >= 2:
#Separating code and name of account for searching
operand1,operand2 = name.split(' ',1) #name can contain spaces e.g. OpenERP S.A.
ids = self.search(cr, user, [('code', operator, operand1), ('name', operator, operand2)]+ args, limit=limit)
if operator not in expression.NEGATIVE_TERM_OPERATORS:
ids = self.search(cr, user, ['|', ('code', '=like', name+"%"), '|', ('shortcut', '=', name), ('name', operator, name)]+args, limit=limit)
if not ids and len(name.split()) >= 2:
#Separating code and name of account for searching
operand1,operand2 = name.split(' ',1) #name can contain spaces e.g. OpenERP S.A.
ids = self.search(cr, user, [('code', operator, operand1), ('name', operator, operand2)]+ args, limit=limit)
else:
ids = self.search(cr, user, ['&','!', ('code', '=like', name+"%"), ('name', operator, name)]+args, limit=limit)
# as negation want to restric, do if already have results
if ids and len(name.split()) >= 2:
operand1,operand2 = name.split(' ',1) #name can contain spaces e.g. OpenERP S.A.
ids = self.search(cr, user, [('code', operator, operand1), ('name', operator, operand2), ('id', 'in', ids)]+ args, limit=limit)
else:
ids = self.search(cr, user, args, context=context, limit=limit)
return self.name_get(cr, user, ids, context=context)
@ -1573,11 +1576,6 @@ class account_move(osv.osv):
obj_analytic_line = self.pool.get('account.analytic.line')
obj_move_line = self.pool.get('account.move.line')
for move in self.browse(cr, uid, ids, context):
# Unlink old analytic lines on move_lines
for obj_line in move.line_id:
for obj in obj_line.analytic_lines:
obj_analytic_line.unlink(cr,uid,obj.id)
journal = move.journal_id
amount = 0
line_ids = []

View File

@ -193,6 +193,8 @@ class account_move_line(osv.osv):
if obj_line.analytic_account_id:
if not obj_line.journal_id.analytic_journal_id:
raise osv.except_osv(_('No Analytic Journal!'),_("You have to define an analytic journal on the '%s' journal!") % (obj_line.journal_id.name, ))
if obj_line.analytic_lines:
acc_ana_line_obj.unlink(cr,uid,[obj.id for obj in obj_line.analytic_lines])
vals_line = self._prepare_analytic_line(cr, uid, obj_line, context=context)
acc_ana_line_obj.create(cr, uid, vals_line)
return True
@ -1207,20 +1209,6 @@ class account_move_line(osv.osv):
if not ok:
raise osv.except_osv(_('Bad Account!'), _('You cannot use this general account in this journal, check the tab \'Entry Controls\' on the related journal.'))
if vals.get('analytic_account_id',False):
if journal.analytic_journal_id:
vals['analytic_lines'] = [(0,0, {
'name': vals['name'],
'date': vals.get('date', time.strftime('%Y-%m-%d')),
'account_id': vals.get('analytic_account_id', False),
'unit_amount': vals.get('quantity', 1.0),
'amount': vals.get('debit', 0.0) or vals.get('credit', 0.0),
'general_account_id': vals.get('account_id', False),
'journal_id': journal.analytic_journal_id.id,
'ref': vals.get('ref', False),
'user_id': uid
})]
result = super(account_move_line, self).create(cr, uid, vals, context=context)
# CREATE Taxes
if vals.get('account_tax_id', False):

View File

@ -1,4 +1,7 @@
from . import test_tax
from . import test_search
fast_suite = [test_tax,
]
fast_suite = [
test_tax,
test_search,
]

View File

@ -0,0 +1,60 @@
from openerp.tests.common import TransactionCase
class TestSearch(TransactionCase):
"""Tests for search on name_search (account.account)
The name search on account.account is quite complexe, make sure
we have all the correct results
"""
def setUp(self):
super(TestSearch, self).setUp()
cr, uid = self.cr, self.uid
self.account_model = self.registry('account.account')
self.account_type_model = self.registry('account.account.type')
ac_ids = self.account_type_model.search(cr, uid, [], limit=1)
self.atax = (int(self.account_model.create(cr, uid, dict(
name="Tax Received",
code="121",
user_type=ac_ids[0],
))), "121 Tax Received")
self.apurchase = (int(self.account_model.create(cr, uid, dict(
name="Purchased Stocks",
code="1101",
user_type=ac_ids[0],
))), "1101 Purchased Stocks")
self.asale = (int(self.account_model.create(cr, uid, dict(
name="Product Sales",
code="200",
user_type=ac_ids[0],
))), "200 Product Sales")
self.all_ids = [self.atax[0], self.apurchase[0], self.asale[0]]
def test_name_search(self):
cr, uid = self.cr, self.uid
atax_ids = self.account_model.name_search(cr, uid, name="Tax", operator='ilike', args=[('id', 'in', self.all_ids)])
self.assertEqual(set([self.atax[0]]), set([a[0] for a in atax_ids]), "name_search 'ilike Tax' should have returned Tax Received account only")
atax_ids = self.account_model.name_search(cr, uid, name="Tax", operator='not ilike', args=[('id', 'in', self.all_ids)])
self.assertEqual(set([self.apurchase[0], self.asale[0]]), set([a[0] for a in atax_ids]), "name_search 'not ilike Tax' should have returned all but Tax Received account")
apur_ids = self.account_model.name_search(cr, uid, name='1101', operator='ilike', args=[('id', 'in', self.all_ids)])
self.assertEqual(set([self.apurchase[0]]), set([a[0] for a in apur_ids]), "name_search 'ilike 1101' should have returned Purchased Stocks account only")
apur_ids = self.account_model.name_search(cr, uid, name='1101', operator='not ilike', args=[('id', 'in', self.all_ids)])
self.assertEqual(set([self.atax[0], self.asale[0]]), set([a[0] for a in apur_ids]), "name_search 'not ilike 1101' should have returned all but Purchased Stocks account")
asale_ids = self.account_model.name_search(cr, uid, name='200 Sales', operator='ilike', args=[('id', 'in', self.all_ids)])
self.assertEqual(set([self.asale[0]]), set([a[0] for a in asale_ids]), "name_search 'ilike 200 Sales' should have returned Product Sales account only")
asale_ids = self.account_model.name_search(cr, uid, name='200 Sales', operator='not ilike', args=[('id', 'in', self.all_ids)])
self.assertEqual(set([self.atax[0], self.apurchase[0]]), set([a[0] for a in asale_ids]), "name_search 'not ilike 200 Sales' should have returned all but Product Sales account")
asale_ids = self.account_model.name_search(cr, uid, name='Product Sales', operator='ilike', args=[('id', 'in', self.all_ids)])
self.assertEqual(set([self.asale[0]]), set([a[0] for a in asale_ids]), "name_search 'ilike Product Sales' should have returned Product Sales account only")
asale_ids = self.account_model.name_search(cr, uid, name='Product Sales', operator='not ilike', args=[('id', 'in', self.all_ids)])
self.assertEqual(set([self.atax[0], self.apurchase[0]]), set([a[0] for a in asale_ids]), "name_search 'not ilike Product Sales' should have returned all but Product Sales account")

View File

@ -247,13 +247,10 @@ class mail_thread(osv.AbstractModel):
new = set(command[2])
# remove partners that are no longer followers
fol_ids = fol_obj.search(cr, SUPERUSER_ID,
[('res_model', '=', self._name), ('res_id', '=', id), ('partner_id', 'not in', list(new))])
fol_obj.unlink(cr, SUPERUSER_ID, fol_ids)
self.message_unsubscribe(cr, uid, [id], list(old-new))
# add new followers
for partner_id in new - old:
fol_obj.create(cr, SUPERUSER_ID, {'res_model': self._name, 'res_id': id, 'partner_id': partner_id})
self.message_subscribe(cr, uid, [id], list(new-old))
def _search_followers(self, cr, uid, obj, name, args, context):
"""Search function for message_follower_ids
@ -319,6 +316,7 @@ class mail_thread(osv.AbstractModel):
"""
if context is None:
context = {}
thread_id = super(mail_thread, self).create(cr, uid, values, context=context)
# automatic logging unless asked not to (mainly for various testing purpose)
@ -328,6 +326,7 @@ class mail_thread(osv.AbstractModel):
# subscribe uid unless asked not to
if not context.get('mail_create_nosubscribe'):
self.message_subscribe_users(cr, uid, [thread_id], [uid], context=context)
# auto_subscribe: take values and defaults into account
create_values = dict(values)
for key, val in context.iteritems():
@ -1494,35 +1493,33 @@ class mail_thread(osv.AbstractModel):
else:
self.check_access_rights(cr, uid, 'write')
for record in self.browse(cr, SUPERUSER_ID, ids, context=context):
existing_pids = set([f.id for f in record.message_follower_ids
if f.id in partner_ids])
existing_pids_dict = {}
fol_ids = mail_followers_obj.search(cr, SUPERUSER_ID, [('res_model', '=', self._name), ('res_id', 'in', ids)])
for fol in mail_followers_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context):
existing_pids_dict.setdefault(fol.res_id, set()).add(fol.partner_id.id)
# subtype_ids specified: update already subscribed partners
if subtype_ids and fol_ids:
mail_followers_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
# subtype_ids not specified: do not update already subscribed partner, fetch default subtypes for new partners
if subtype_ids is None:
subtype_ids = subtype_obj.search(
cr, uid, [
('default', '=', True), '|', ('res_model', '=', self._name), ('res_model', '=', False)], context=context)
for id in ids:
existing_pids = existing_pids_dict.get(id, set())
new_pids = set(partner_ids) - existing_pids
# subtype_ids specified: update already subscribed partners
if subtype_ids and existing_pids:
fol_ids = mail_followers_obj.search(cr, SUPERUSER_ID, [
('res_model', '=', self._name),
('res_id', '=', record.id),
('partner_id', 'in', list(existing_pids)),
], context=context)
mail_followers_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
# subtype_ids not specified: do not update already subscribed partner, fetch default subtypes for new partners
elif subtype_ids is None:
subtype_ids = subtype_obj.search(cr, uid, [
('default', '=', True),
'|',
('res_model', '=', self._name),
('res_model', '=', False)
], context=context)
# subscribe new followers
for new_pid in new_pids:
mail_followers_obj.create(cr, SUPERUSER_ID, {
'res_model': self._name,
'res_id': record.id,
'partner_id': new_pid,
'subtype_ids': [(6, 0, subtype_ids)],
}, context=context)
mail_followers_obj.create(
cr, SUPERUSER_ID, {
'res_model': self._name,
'res_id': id,
'partner_id': new_pid,
'subtype_ids': [(6, 0, subtype_ids)],
}, context=context)
return True
@ -1541,7 +1538,14 @@ class mail_thread(osv.AbstractModel):
self.check_access_rights(cr, uid, 'read')
else:
self.check_access_rights(cr, uid, 'write')
return self.write(cr, SUPERUSER_ID, ids, {'message_follower_ids': [(3, pid) for pid in partner_ids]}, context=context)
fol_obj = self.pool['mail.followers']
fol_ids = fol_obj.search(
cr, SUPERUSER_ID, [
('res_model', '=', self._name),
('res_id', 'in', ids),
('partner_id', 'in', partner_ids)
], context=context)
return fol_obj.unlink(cr, SUPERUSER_ID, fol_ids, context=context)
def _message_get_auto_subscribe_fields(self, cr, uid, updated_fields, auto_follow_fields=['user_id'], context=None):
""" Returns the list of relational fields linking to res.users that should

View File

@ -560,6 +560,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
this.handler = function(e){
if(e.which === 13){ //ignore returns
e.preventDefault();
return;
}

View File

@ -242,6 +242,8 @@ class ir_attachment(osv.osv):
# performed in batch as much as possible.
ima = self.pool.get('ir.model.access')
for model, targets in model_attachments.iteritems():
if model not in self.pool:
continue
if not ima.check(cr, uid, model, 'read', False):
# remove all corresponding attachment ids
for attach_id in itertools.chain(*targets.values()):

View File

@ -533,15 +533,19 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
return res
def execute(self, cr, uid, ids, context=None):
if uid != SUPERUSER_ID and not self.pool['res.users'].has_group(cr, uid, 'base.group_erp_manager'):
raise openerp.exceptions.AccessError(_("Only administrators can change the settings"))
ir_values = self.pool['ir.values']
ir_module = self.pool['ir.module.module']
classified = self._get_classified_fields(cr, uid, context)
config = self.browse(cr, uid, ids[0], context)
# default values fields
for name, model, field in classified['default']:
ir_values.set_default(cr, uid, model, field, config[name])
ir_values.set_default(cr, SUPERUSER_ID, model, field, config[name])
# group fields: modify group / implied groups
for name, group, implied_group in classified['group']:

View File

@ -239,7 +239,7 @@
<field eval="18" name="priority"/>
<field name="arch" type="xml">
<form string="Users" version="7.0">
<field name="image" widget='image' class="oe_right oe_avatar" options='{"preview_image": "image_small"}'/>
<field name="image" readonly="0" widget='image' class="oe_right oe_avatar" options='{"preview_image": "image_small"}'/>
<h1>
<field name="name" readonly="1" class="oe_inline"/>
</h1>

View File

@ -601,8 +601,10 @@ class one2many(_column):
else:
cr.execute('update '+_table+' set '+self._fields_id+'=null where id=%s', (act[1],))
elif act[0] == 4:
# Must use write() to recompute parent_store structure if needed
obj.write(cr, user, [act[1]], {self._fields_id:id}, context=context or {})
cr.execute("select 1 from {0} where id=%s and {1}=%s".format(_table, self._fields_id), (act[1], id))
if not cr.fetchone():
# Must use write() to recompute parent_store structure if needed and check access rules
obj.write(cr, user, [act[1]], {self._fields_id:id}, context=context or {})
elif act[0] == 5:
reverse_rel = obj._all_columns.get(self._fields_id)
assert reverse_rel, 'Trying to unlink the content of a o2m but the pointed model does not have a m2o'

View File

@ -3681,11 +3681,6 @@ class BaseModel(object):
if fields_to_read is None:
fields_to_read = self._columns.keys()
# Construct a clause for the security rules.
# 'tables' hold the list of tables necessary for the SELECT including the ir.rule clauses,
# or will at least contain self._table.
rule_clause, rule_params, tables = self.pool.get('ir.rule').domain_get(cr, user, self._name, 'read', context=context)
# 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
@ -3706,6 +3701,11 @@ class BaseModel(object):
return 'length(%s) as "%s"' % (f_qual, f)
return f_qual
# Construct a clause for the security rules.
# 'tables' hold the list of tables necessary for the SELECT including the ir.rule clauses,
# or will at least contain self._table.
rule_clause, rule_params, tables = self.pool.get('ir.rule').domain_get(cr, user, self._name, 'read', context=context)
fields_pre2 = map(convert_field, fields_pre)
order_by = self._parent_order or self._order
select_fields = ','.join(fields_pre2 + ['%s.id' % self._table])
@ -3720,6 +3720,7 @@ class BaseModel(object):
self._check_record_rules_result_count(cr, user, sub_ids, result_ids, 'read', context=context)
res.extend(results)
else:
self.check_access_rule(cr, user, ids, 'read', context=context)
res = map(lambda x: {'id': x}, ids)
if context.get('lang'):

View File

@ -952,7 +952,7 @@ def convert_csv_import(cr, module, fname, csvcontent, idref=None, mode='init',
result, rows, warning_msg, dummy = registry[model].import_data(cr, uid, fields, datas,mode, module, noupdate, filename=fname_partial)
if result < 0:
# Report failed import and abort module install
raise Exception(_('Module loading failed: file %s/%s could not be processed:\n %s') % (module, fname, warning_msg))
raise Exception(_('Module loading %s failed: file %s could not be processed:\n %s') % (module, fname, warning_msg))
if config.get('import_partial'):
data = pickle.load(file(config.get('import_partial')))
data[fname_partial] = 0