diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 6cfc1298772..e1528f17340 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -166,6 +166,7 @@ for a particular financial year and for preparation of vouchers there is a modul 'test/account_validate_account_move.yml', 'test/test_edi_invoice.yml', 'test/account_report.yml', + 'test/analytic_hierarchy.yml', 'test/account_fiscalyear_close.yml', #last test, as it will definitively close the demo fiscalyear ], 'installable': True, diff --git a/addons/account/test/analytic_hierarchy.yml b/addons/account/test/analytic_hierarchy.yml new file mode 100644 index 00000000000..117d6506b21 --- /dev/null +++ b/addons/account/test/analytic_hierarchy.yml @@ -0,0 +1,56 @@ +- + We create a simple hierarchy like this + Toplevel view account + ├ Real analytic account 1 + └ Real analytic account 2 +- + !record {model: account.analytic.account, id: analytic_account_view1}: + name: 'Toplevel view account' + type: 'view' +- + !record {model: account.analytic.account, id: analytic_account1}: + name: 'Real analytic account 1' + type: 'normal' + parent_id: analytic_account_view1 +- + !record {model: account.analytic.account, id: analytic_account2}: + name: 'Real analytic account 2' + type: 'normal' + parent_id: analytic_account_view1 +- + We add analytic lines in real accounts and journal +- + !record {model: account.analytic.journal, id: analytic_journal1}: + name: 'Analytic journal' +- + !record {model: account.analytic.line, id: analytic_line1}: + name: 'Analytic line 1' + account_id: analytic_account1 + journal_id: analytic_journal1 + general_account_id: account.a_expense +- + !record {model: account.analytic.line, id: analytic_line2}: + name: 'Analytic line 2' + account_id: analytic_account2 + journal_id: analytic_journal1 + general_account_id: account.a_expense +- + Now we copy the toplevel account +- + !function {model: account.analytic.account, name: copy, id: analytic_account_view1}: + - eval: "ref('analytic_account_view1')" +- + !python {model: account.analytic.account}: | + # the toplevel account has been copied with the (copy) suffix + accounts = self.search(cr, uid, [('name', 'like', '%Toplevel view account%')]) + assert len(accounts) == 2, 'The toplevel account has not been copied' + accounts = self.search(cr, uid, [('name', '=', 'Toplevel view account')]) + assert len(accounts) == 1, 'The toplevel account copy has a bad name' + # the sub-accounts and sub-accounts have been copied without the (copy) suffix + accounts = self.search(cr, uid, [('name', '=', 'Real analytic account 1')]) + assert len(accounts) == 2, 'The sub-account has not been copied' + accounts = self.search(cr, uid, [('name', '=', 'Real analytic account 2')]) + assert len(accounts) == 2, 'The sub-account has not been copied' + # the analytic lines should not be duplicated + lines = self.pool.get('account.analytic.line').search(cr, uid, [('name', 'like', '%Analytic line %')]) + assert len(lines) == 2, "The analytic lines shouldn't have been copied" diff --git a/addons/analytic/analytic.py b/addons/analytic/analytic.py index 3a8624139f1..70a416904f4 100644 --- a/addons/analytic/analytic.py +++ b/addons/analytic/analytic.py @@ -272,6 +272,8 @@ class account_analytic_account(osv.osv): raise osv.except_osv(_('Warning'), _("Quick account creation disallowed.")) def copy(self, cr, uid, id, default=None, context=None): + """ executed only on the toplevel copied object of the hierarchy. + Subobject are actually copied with copy_data""" if not default: default = {} analytic = self.browse(cr, uid, id, context=context) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 644f55780cd..da6f4ab78e7 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1761,7 +1761,7 @@ class stock_move(osv.osv): "the product reservation, and should be done with care." ), 'product_uom': fields.many2one('product.uom', 'Unit of Measure', required=True, states={'done': [('readonly', True)]}), - 'product_uos_qty': fields.float('Quantity (UOS)', digits_compute=dp.get_precision('Product Unit of Measure'), states={'done': [('readonly', True)]}), + 'product_uos_qty': fields.float('Quantity (UOS)', digits_compute=dp.get_precision('Product UoS'), states={'done': [('readonly', True)]}), 'product_uos': fields.many2one('product.uom', 'Product UOS', states={'done': [('readonly', True)]}), 'product_tmpl_id': fields.related('product_id', 'product_tmpl_id', type='many2one', relation='product.template', string='Product Template'), @@ -2041,7 +2041,8 @@ class stock_move(osv.osv): break if product_uos and product_uom and (product_uom != product_uos): - result['product_uos_qty'] = product_qty * uos_coeff['uos_coeff'] + precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Product UoS') + result['product_uos_qty'] = float_round(product_qty * uos_coeff['uos_coeff'], precision_digits=precision) else: result['product_uos_qty'] = product_qty @@ -2071,7 +2072,8 @@ class stock_move(osv.osv): # The clients should call onchange_quantity too anyway if product_uos and product_uom and (product_uom != product_uos): - result['product_uom_qty'] = product_uos_qty / uos_coeff['uos_coeff'] + precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Product Unit of Measure') + result['product_uom_qty'] = float_round(product_uos_qty / uos_coeff['uos_coeff'], precision_digits=precision) else: result['product_uom_qty'] = product_uos_qty return {'value': result} diff --git a/openerp/addons/base/ir/ir_attachment.py b/openerp/addons/base/ir/ir_attachment.py index 238de5a460d..82ec746ec6b 100644 --- a/openerp/addons/base/ir/ir_attachment.py +++ b/openerp/addons/base/ir/ir_attachment.py @@ -163,7 +163,7 @@ class ir_attachment(osv.osv): else: result[attach.id] = attach.db_datas if bin_size: - result[attach.id] = int(result[attach.id]) + result[attach.id] = int(result[attach.id] or 0) return result