diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index 597ed01aa1b..ef4c9379c82 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -884,6 +884,8 @@ class account_voucher(osv.osv): return res def onchange_journal(self, cr, uid, ids, journal_id, line_ids, tax_id, partner_id, date, amount, ttype, company_id, context=None): + if context is None: + context = {} if not journal_id: return False journal_pool = self.pool.get('account.journal') diff --git a/addons/analytic_user_function/analytic_user_function.py b/addons/analytic_user_function/analytic_user_function.py index 1adefb2d59d..2671fc92581 100644 --- a/addons/analytic_user_function/analytic_user_function.py +++ b/addons/analytic_user_function/analytic_user_function.py @@ -42,6 +42,7 @@ class analytic_user_funct_grid(osv.osv): return {} value = {} + prod = False if product_id: prod = self.pool.get('product.product').browse(cr, uid, product_id, context=context) emp = emp_obj.browse(cr, uid, emp_id[0], context=context) diff --git a/addons/lunch/lunch.py b/addons/lunch/lunch.py index efad6fd6944..fbd193709ac 100644 --- a/addons/lunch/lunch.py +++ b/addons/lunch/lunch.py @@ -35,6 +35,16 @@ class lunch_order(osv.Model): _description = 'Lunch Order' _order = 'date desc' + def name_get(self, cr, uid, ids, context=None): + if not ids: + return [] + res = [] + for elmt in self.browse(cr, uid, ids, context=context): + name = _("Lunch Order") + name = name + ' ' + str(elmt.id) + res.append((elmt.id, name)) + return res + def _price_get(self, cr, uid, ids, name, arg, context=None): """ get and sum the order lines' price diff --git a/addons/lunch/lunch_view.xml b/addons/lunch/lunch_view.xml index 2f3af2f461d..a2f22d4dd0a 100644 --- a/addons/lunch/lunch_view.xml +++ b/addons/lunch/lunch_view.xml @@ -7,7 +7,7 @@ - + Search @@ -85,6 +85,40 @@ + + + cashmove tree + lunch.cashmove + + + + + + + + + + + + cashmove form + lunch.cashmove + +
+ + + + + + + +
+
+
+ + New Order @@ -111,6 +145,19 @@ + + + cashmove tree + lunch.cashmove + + + + + + + + + @@ -119,6 +166,7 @@ tree {"search_default_is_mine_group":1} +

Here you can see your cash moves.
A cash moves can be either an expense or a payment. @@ -175,6 +223,7 @@ tree,form {"search_default_group_by_user":1} +

Click to create a new payment. @@ -196,6 +245,7 @@ tree,form {"search_default_is_payment":1} +

Click to create a payment. @@ -389,39 +439,6 @@ - - - cashmove tree - lunch.cashmove - - - - - - - - - - - - cashmove form - lunch.cashmove - -

- - - - - - - -
-
-
- alert tree diff --git a/addons/mail/data/mail_data.xml b/addons/mail/data/mail_data.xml index 4e935e4aa88..e1ca797670b 100644 --- a/addons/mail/data/mail_data.xml +++ b/addons/mail/data/mail_data.xml @@ -40,6 +40,11 @@ () + + + none + + mail.catchall.alias diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index f90baa5a320..bcb66433964 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -679,14 +679,14 @@ class mail_message(osv.Model): - no model, no res_id, I create a private message OR - pid in message_follower_ids if model, res_id OR - mail_notification (parent_id.id, pid) exists, uid has been notified of the parent, OR - - uid have write access on the related document if model, res_id, OR + - uid have write or create access on the related document if model, res_id, OR - otherwise: raise - write: if - author_id == pid, uid is the author, OR - - uid has write access on the related document if model, res_id + - uid has write or create access on the related document if model, res_id - otherwise: raise - unlink: if - - uid has write access on the related document if model, res_id + - uid has write or create access on the related document if model, res_id - otherwise: raise """ def _generate_model_record_ids(msg_val, msg_ids=[]): diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 94e9126f020..ebb7a40c719 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -1038,8 +1038,10 @@ class mail_thread(osv.AbstractModel): # text/plain ->
                 body = tools.append_content_to_html(u'', body, preserve=True)
         else:
-            alternative = (message.get_content_type() == 'multipart/alternative')
+            alternative = False
             for part in message.walk():
+                if part.get_content_type() == 'multipart/alternative':
+                    alternative = True
                 if part.get_content_maintype() == 'multipart':
                     continue  # skip container
                 filename = part.get_filename()  # None if normal part
diff --git a/addons/mail/tests/test_mail_features.py b/addons/mail/tests/test_mail_features.py
index ae5555c01ca..e9563e19246 100644
--- a/addons/mail/tests/test_mail_features.py
+++ b/addons/mail/tests/test_mail_features.py
@@ -294,7 +294,7 @@ class test_mail(TestMailBase):
         # Data creation
         # --------------------------------------------------
         # 0 - Update existing users-partners
-        self.res_users.write(cr, uid, [uid], {'email': 'a@a'})
+        self.res_users.write(cr, uid, [uid], {'email': 'a@a', 'notification_email_send': 'comment'})
         self.res_users.write(cr, uid, [self.user_raoul_id], {'email': 'r@r'})
         # 1 - Bert Tartopoils, with email, should receive emails for comments and emails
         p_b_id = self.res_partner.create(cr, uid, {'name': 'Bert Tartopoils', 'email': 'b@b'})
diff --git a/addons/mail/tests/test_mail_gateway.py b/addons/mail/tests/test_mail_gateway.py
index fade38869f1..3fd8ebd3101 100644
--- a/addons/mail/tests/test_mail_gateway.py
+++ b/addons/mail/tests/test_mail_gateway.py
@@ -81,6 +81,67 @@ Please call me as soon as possible this afternoon!
 Sylvie
 """
 
+MAIL_MULTIPART_MIXED = """Return-Path: 
+X-Original-To: raoul@grosbedon.fr
+Delivered-To: raoul@grosbedon.fr
+Received: by mail1.grosbedon.com (Postfix, from userid 10002)
+    id E8166BFACA; Fri, 23 Aug 2013 13:18:01 +0200 (CEST)
+X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail1.grosbedon.com
+X-Spam-Level: 
+X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,FREEMAIL_FROM,
+    HTML_MESSAGE,RCVD_IN_DNSWL_LOW autolearn=unavailable version=3.3.1
+Received: from mail-ie0-f173.google.com (mail-ie0-f173.google.com [209.85.223.173])
+    by mail1.grosbedon.com (Postfix) with ESMTPS id 9BBD7BFAAA
+    for ; Fri, 23 Aug 2013 13:17:55 +0200 (CEST)
+Received: by mail-ie0-f173.google.com with SMTP id qd12so575130ieb.4
+        for ; Fri, 23 Aug 2013 04:17:54 -0700 (PDT)
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
+        d=gmail.com; s=20120113;
+        h=mime-version:date:message-id:subject:from:to:content-type;
+        bh=dMNHV52EC7GAa7+9a9tqwT9joy9z+1950J/3A6/M/hU=;
+        b=DGuv0VjegdSrEe36ADC8XZ9Inrb3Iu+3/52Bm+caltddXFH9yewTr0JkCRQaJgMwG9
+         qXTQgP8qu/VFEbCh6scu5ZgU1hknzlNCYr3LT+Ih7dAZVUEHUJdwjzUU1LFV95G2RaCd
+         /Lwff6CibuUvrA+0CBO7IRKW0Sn5j0mukYu8dbaKsm6ou6HqS8Nuj85fcXJfHSHp6Y9u
+         dmE8jBh3fHCHF/nAvU+8aBNSIzl1FGfiBYb2jCoapIuVFitKR4q5cuoodpkH9XqqtOdH
+         DG+YjEyi8L7uvdOfN16eMr7hfUkQei1yQgvGu9/5kXoHg9+Gx6VsZIycn4zoaXTV3Nhn
+         nu4g==
+MIME-Version: 1.0
+X-Received: by 10.50.124.65 with SMTP id mg1mr1144467igb.43.1377256674216;
+ Fri, 23 Aug 2013 04:17:54 -0700 (PDT)
+Received: by 10.43.99.71 with HTTP; Fri, 23 Aug 2013 04:17:54 -0700 (PDT)
+Date: Fri, 23 Aug 2013 13:17:54 +0200
+Message-ID: 
+Subject: Test mail multipart/mixed
+From: =?ISO-8859-1?Q?Raoul Grosbedon=E9e?= 
+To: Followers of ASUSTeK-Joseph-Walters 
+Content-Type: multipart/mixed; boundary=089e01536c4ed4d17204e49b8e96
+
+--089e01536c4ed4d17204e49b8e96
+Content-Type: multipart/alternative; boundary=089e01536c4ed4d16d04e49b8e94
+
+--089e01536c4ed4d16d04e49b8e94
+Content-Type: text/plain; charset=ISO-8859-1
+
+Should create a multipart/mixed: from gmail, *bold*, with attachment.
+
+-- 
+Marcel Boitempoils.
+
+--089e01536c4ed4d16d04e49b8e94
+Content-Type: text/html; charset=ISO-8859-1
+
+
Should create a multipart/mixed: from gmail, bold, with attachment.

--
Marcel Boitempoils.
+ +--089e01536c4ed4d16d04e49b8e94-- +--089e01536c4ed4d17204e49b8e96 +Content-Type: text/plain; charset=US-ASCII; name="test.txt" +Content-Disposition: attachment; filename="test.txt" +Content-Transfer-Encoding: base64 +X-Attachment-Id: f_hkpb27k00 + +dGVzdAo= +--089e01536c4ed4d17204e49b8e96--""" + class TestMailgateway(TestMailBase): @@ -248,6 +309,24 @@ class TestMailgateway(TestMailBase): self.assertEqual(mail.reply_to, 'someone@example.com', 'mail_mail: reply_to should equal the rpely_to given to create') + def test_09_message_parse(self): + """ Testing incoming emails parsing """ + cr, uid = self.cr, self.uid + + res = self.mail_thread.message_parse(cr, uid, MAIL_TEMPLATE_PLAINTEXT) + self.assertIn('Please call me as soon as possible this afternoon!', res.get('body', ''), + 'message_parse: missing text in text/plain body after parsing') + + res = self.mail_thread.message_parse(cr, uid, MAIL_TEMPLATE) + self.assertIn('

Please call me as soon as possible this afternoon!

', res.get('body', ''), + 'message_parse: missing html in multipart/alternative body after parsing') + + res = self.mail_thread.message_parse(cr, uid, MAIL_MULTIPART_MIXED) + self.assertNotIn('Should create a multipart/mixed: from gmail, *bold*, with attachment', res.get('body', ''), + 'message_parse: text version should not be in body after parsing multipart/mixed') + self.assertIn('
Should create a multipart/mixed: from gmail, bold, with attachment.

', res.get('body', ''), + 'message_parse: html version should be in body after parsing multipart/mixed') + @mute_logger('openerp.addons.mail.mail_thread', 'openerp.osv.orm') def test_10_message_process(self): """ Testing incoming emails processing. """ diff --git a/addons/mrp/mrp_view.xml b/addons/mrp/mrp_view.xml index 47abeeaf9a9..65fa21f4709 100644 --- a/addons/mrp/mrp_view.xml +++ b/addons/mrp/mrp_view.xml @@ -422,6 +422,7 @@ + @@ -511,7 +512,18 @@

- + + product.search.bom + product.product + + + + + + + + + Products product.product @@ -535,16 +547,16 @@ action="mrp_bom_form_action2" id="menu_mrp_bom_form_action2" parent="menu_mrp_configuration" - groups="base.group_no_one" sequence="20"/> Bill of Materials Structure ir.actions.act_window mrp.bom - [('bom_id', '=',active_ids)] + [('id', 'in', active_ids)] tree + tree @@ -692,7 +704,7 @@ - + @@ -708,7 +720,7 @@ - + @@ -722,7 +734,7 @@ - + @@ -1015,6 +1027,7 @@ Bill of Materials [('bom_id','=',False)] mrp.bom + tree {'search_default_product_id': [active_id]} diff --git a/addons/mrp/tests/__init__.py b/addons/mrp/tests/__init__.py new file mode 100644 index 00000000000..39ebd5e451f --- /dev/null +++ b/addons/mrp/tests/__init__.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2012-TODAY OpenERP S.A. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from . import test_multicompany + +checks = [ + test_multicompany, +] + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mrp/tests/test_multicompany.py b/addons/mrp/tests/test_multicompany.py new file mode 100644 index 00000000000..78986bd41b2 --- /dev/null +++ b/addons/mrp/tests/test_multicompany.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2012-TODAY OpenERP S.A. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.tests import common + + +class TestMrpMulticompany(common.TransactionCase): + + def setUp(self): + super(TestMrpMulticompany, self).setUp() + cr, uid = self.cr, self.uid + + # Usefull models + self.ir_model_data = self.registry('ir.model.data') + self.res_users = self.registry('res.users') + self.stock_location = self.registry('stock.location') + + model, self.multicompany_user_id = self.ir_model_data.get_object_reference(cr, uid, 'stock', 'multicompany_user') + + + def test_00_multicompany_user(self): + """check no error on getting default mrp.production values in multicompany setting""" + cr, uid, context = self.cr, self.multicompany_user_id, {} + fields = ['location_src_id', 'location_dest_id'] + defaults = self.stock_location.default_get(cr, uid, ['location_id', 'location_dest_id', 'type'], context) + for field in fields: + print field, uid, defaults + if defaults.get(field): + try: + self.stock_location.check_access_rule(cr, uid, [defaults[field]], 'read', context) + except Exception, exc: + assert False, "unreadable location %s: %s" % (field, exc) diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index e743a9323e4..a6ad5e321dd 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -959,11 +959,12 @@ class pos_order(osv.osv): user_company = user_proxy.browse(cr, order.user_id.id, order.user_id.id).company_id group_tax = {} - account_def = property_obj.get(cr, uid, 'property_account_receivable', 'res.partner', context=context).id + account_def = property_obj.get(cr, uid, 'property_account_receivable', 'res.partner', context=context) order_account = order.partner_id and \ order.partner_id.property_account_receivable and \ - order.partner_id.property_account_receivable.id or account_def or current_company.account_receivable.id + order.partner_id.property_account_receivable.id or \ + account_def and account_def.id or current_company.account_receivable.id if move_id is None: # Create an entry for the sale diff --git a/addons/portal/portal_demo.xml b/addons/portal/portal_demo.xml index 3660754b4ad..5ec23c0addb 100644 --- a/addons/portal/portal_demo.xml +++ b/addons/portal/portal_demo.xml @@ -8,6 +8,7 @@ demo@portal.example.com + none diff --git a/addons/project/project.py b/addons/project/project.py index db2052224f9..d0649290df6 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -61,6 +61,13 @@ class project(osv.osv): "mail.alias": "alias_id"} _inherit = ['mail.thread', 'ir.needaction_mixin'] + def _auto_init(self, cr, context=None): + """ Installation hook: aliases, project.project """ + # create aliases for all projects and avoid constraint errors + alias_context = dict(context, alias_model_name='project.task') + self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(project, self)._auto_init, + self._columns['alias_id'], 'id', alias_prefix='project+', alias_defaults={'project_id':'id'}, context=alias_context) + def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False): if user == 1: return super(project, self).search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count) diff --git a/addons/stock/report/picking.py b/addons/stock/report/picking.py index 512d124ee0c..603e815fc10 100644 --- a/addons/stock/report/picking.py +++ b/addons/stock/report/picking.py @@ -21,20 +21,23 @@ import time from openerp.report import report_sxw -from openerp.osv import osv class picking(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): super(picking, self).__init__(cr, uid, name, context=context) self.localcontext.update({ 'time': time, - 'get_product_desc':self.get_product_desc + 'get_product_desc': self.get_product_desc, }) - def get_product_desc(self,move_line): + def get_product_desc(self, move_line): desc = move_line.product_id.name if move_line.product_id.default_code: desc = '[' + move_line.product_id.default_code + ']' + ' ' + desc return desc -report_sxw.report_sxw('report.stock.picking.list','stock.picking','addons/stock/report/picking.rml',parser=picking) +for suffix in ['', '.in', '.out']: + report_sxw.report_sxw('report.stock.picking.list' + suffix, + 'stock.picking' + suffix, + 'addons/stock/report/picking.rml', + parser=picking) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/stock.py b/addons/stock/stock.py index dba506d22ee..7d2a1282cb0 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -2930,12 +2930,22 @@ class stock_warehouse(osv.osv): } def _default_lot_input_stock_id(self, cr, uid, context=None): - lot_input_stock = self.pool.get('ir.model.data').get_object(cr, uid, 'stock', 'stock_location_stock') - return lot_input_stock.id + try: + lot_input_stock_model, lot_input_stock_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'stock_location_stock') + self.pool.get('stock.location').check_access_rule(cr, uid, [lot_input_stock_id], 'read', context=context) + except (ValueError, orm.except_orm): + # the user does not have read access on the location or it does not exists + lot_input_stock_id = False + return lot_input_stock_id def _default_lot_output_id(self, cr, uid, context=None): - lot_output = self.pool.get('ir.model.data').get_object(cr, uid, 'stock', 'stock_location_output') - return lot_output.id + try: + lot_input_stock_model, lot_input_stock_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'stock_location_output') + self.pool.get('stock.location').check_access_rule(cr, uid, [lot_input_stock_id], 'read', context=context) + except (ValueError, orm.except_orm): + # the user does not have read access on the location or it does not exists + lot_output_id = False + return lot_output_id _defaults = { 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.inventory', context=c), diff --git a/addons/stock/stock_demo.xml b/addons/stock/stock_demo.xml index eb5a6c46380..94844ee8904 100644 --- a/addons/stock/stock_demo.xml +++ b/addons/stock/stock_demo.xml @@ -287,6 +287,16 @@ + + multicomp + multicomp + multicomp + + + + + + diff --git a/addons/stock/stock_report.xml b/addons/stock/stock_report.xml index 540e6a8f902..53b89dcf41f 100644 --- a/addons/stock/stock_report.xml +++ b/addons/stock/stock_report.xml @@ -3,8 +3,8 @@ - - + + diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 14b3ba04eb5..8940309dc12 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -161,7 +161,7 @@
- + @@ -786,7 +786,7 @@ - + @@ -921,7 +921,7 @@ - +
@@ -1048,7 +1048,7 @@ - +
diff --git a/addons/stock/tests/__init__.py b/addons/stock/tests/__init__.py new file mode 100644 index 00000000000..39ebd5e451f --- /dev/null +++ b/addons/stock/tests/__init__.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2012-TODAY OpenERP S.A. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from . import test_multicompany + +checks = [ + test_multicompany, +] + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/tests/test_multicompany.py b/addons/stock/tests/test_multicompany.py new file mode 100644 index 00000000000..d30e7d0ef2b --- /dev/null +++ b/addons/stock/tests/test_multicompany.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2012-TODAY OpenERP S.A. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.tests import common + + +class TestStockMulticompany(common.TransactionCase): + + def setUp(self): + super(TestStockMulticompany, self).setUp() + cr, uid = self.cr, self.uid + + # Usefull models + self.ir_model_data = self.registry('ir.model.data') + self.res_users = self.registry('res.users') + self.stock_location = self.registry('stock.location') + self.stock_move = self.registry('stock.move') + self.stock_fill_inventory = self.registry('stock.fill.inventory') + self.stock_warehouse = self.registry('stock.warehouse') + + model, self.multicompany_user_id = self.ir_model_data.get_object_reference(cr, uid, 'stock', 'multicompany_user') + + def test_00_multicompany_default_stock_move(self): + """check no error on getting default stock.move values in multicompany setting""" + cr, uid, context = self.cr, self.multicompany_user_id, {} + fields = ['location_id', 'location_dest_id'] + for type in ('in', 'internal', 'out'): + context['picking_type'] = type + defaults = self.stock_move.default_get(cr, uid, ['location_id', 'location_dest_id', 'type'], context) + for field in fields: + if defaults.get(field): + try: + self.stock_location.check_access_rule(cr, uid, [defaults[field]], 'read', context) + except Exception, exc: + assert False, "unreadable location %s: %s" % (field, exc) + self.assertEqual(defaults['type'], type, "wrong move type") + + + def test_10_multicompany_onchange_move_type(self): + """check onchange_move_type does not return unreadable in multicompany setting""" + cr, uid, context = self.cr, self.multicompany_user_id, {} + fields = ['location_id', 'location_dest_id'] + for type in ('in', 'internal', 'out'): + result = self.stock_move.onchange_move_type(cr, uid, [], type, context)['value'] + for field in fields: + if result.get(field): + try: + self.stock_location.check_access_rule(cr, uid, [result[field]], 'read', context) + except Exception, exc: + assert False, "unreadable location %s: %s" % (field, exc) + + + def test_20_multicompany_default_stock_fill_inventory(self): + """check default location readability for stock_fill_inventory in multicompany setting""" + cr, uid, context = self.cr, self.multicompany_user_id, {} + defaults = self.stock_fill_inventory.default_get(cr, uid, ['location_id'], context) + if defaults.get('location_id'): + try: + self.stock_location.check_access_rule(cr, uid, [defaults['location_id']], 'read', context) + except Exception, exc: + assert False, "unreadable source location: %s" % exc + + + def test_30_multicompany_default_warehouse_location(self): + """check default locations for warehouse in multicompany setting""" + cr, uid, context = self.cr, self.multicompany_user_id, {} + fields = ['lot_input_id', 'lot_stock_id', 'lot_output_id'] + defaults = self.stock_warehouse.default_get(cr, uid, fields, context) + for field in fields: + if defaults.get(field): + try: + self.stock_location.check_access_rule(cr, uid, [defaults[field]], 'read', context) + except Exception, exc: + assert False, "unreadable default %s: %s" % (field, exc) diff --git a/addons/stock/wizard/stock_fill_inventory.py b/addons/stock/wizard/stock_fill_inventory.py index e3341bd6a80..b367e6069d8 100644 --- a/addons/stock/wizard/stock_fill_inventory.py +++ b/addons/stock/wizard/stock_fill_inventory.py @@ -19,7 +19,7 @@ # ############################################################################## -from openerp.osv import fields, osv +from openerp.osv import fields, osv, orm from openerp.tools.translate import _ class stock_fill_inventory(osv.osv_memory): @@ -28,8 +28,10 @@ class stock_fill_inventory(osv.osv_memory): def _default_location(self, cr, uid, ids, context=None): try: - loc_model, location_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'stock_location_stock') - except ValueError, e: + location = self.pool.get('ir.model.data').get_object(cr, uid, 'stock', 'stock_location_stock') + location.check_access_rule('read', context=context) + location_id = location.id + except (ValueError, orm.except_orm), e: return False return location_id or False