diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py
index 4468d3e129a..b9ef598ff3e 100644
--- a/addons/account/models/account_bank_statement.py
+++ b/addons/account/models/account_bank_statement.py
@@ -81,7 +81,7 @@ class AccountBankStatement(models.Model):
@api.multi
def _is_difference_zero(self):
for bank_stmt in self:
- bank_stmt.is_difference_zero = float_is_zero(bank_stmt.difference, bank_stmt.currency_id.decimal_places)
+ bank_stmt.is_difference_zero = float_is_zero(bank_stmt.difference, precision_digits=bank_stmt.currency_id.decimal_places)
@api.one
@api.depends('journal_id')
diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py
index 7ad8561a6b2..e2395272e26 100644
--- a/addons/account/models/account_invoice.py
+++ b/addons/account/models/account_invoice.py
@@ -97,7 +97,7 @@ class AccountInvoice(models.Model):
self.residual_signed = abs(residual) * sign
self.residual = abs(residual)
digits_rounding_precision = self.currency_id.rounding
- if float_is_zero(self.residual, digits_rounding_precision):
+ if float_is_zero(self.residual, precision_rounding=digits_rounding_precision):
self.reconciled = True
else:
self.reconciled = False
diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py
index da7ea8e6152..aa3d81ef3b4 100644
--- a/addons/account/models/account_move.py
+++ b/addons/account/models/account_move.py
@@ -241,20 +241,26 @@ class AccountMoveLine(models.Model):
sign = 1 if (line.debit - line.credit) > 0 else -1
for partial_line in (line.matched_debit_ids + line.matched_credit_ids):
- amount -= partial_line.amount
+ # If line is a credit (sign = -1) we:
+ # - subtract matched_debit_ids (partial_line.credit_move_id == line)
+ # - add matched_credit_ids (partial_line.credit_move_id != line)
+ # If line is a debit (sign = 1), do the opposite.
+ sign_partial_line = sign if partial_line.credit_move_id == line else (-1 * sign)
+
+ amount += sign_partial_line * partial_line.amount
#getting the date of the matched item to compute the amount_residual in currency
date = partial_line.credit_move_id.date if partial_line.debit_move_id == line else partial_line.debit_move_id.date
if line.currency_id:
if partial_line.currency_id and partial_line.currency_id == line.currency_id:
- amount_residual_currency -= partial_line.amount_currency
+ amount_residual_currency += sign_partial_line * partial_line.amount_currency
else:
- amount_residual_currency -= line.company_id.currency_id.with_context(date=date).compute(partial_line.amount, line.currency_id)
+ amount_residual_currency += sign_partial_line * line.company_id.currency_id.with_context(date=date).compute(partial_line.amount, line.currency_id)
#computing the `reconciled` field. As we book exchange rate difference on each partial matching,
#we can only check the amount in company currency
reconciled = False
digits_rounding_precision = line.company_id.currency_id.rounding
- if float_is_zero(amount, digits_rounding_precision) and (line.debit or line.credit):
+ if float_is_zero(amount, precision_rounding=digits_rounding_precision) and (line.debit or line.credit):
reconciled = True
line.reconciled = reconciled
diff --git a/addons/account/models/chart_template.py b/addons/account/models/chart_template.py
index 8257b6a4555..8f716482293 100644
--- a/addons/account/models/chart_template.py
+++ b/addons/account/models/chart_template.py
@@ -19,7 +19,8 @@ def migrate_set_tags_and_taxes_updatable(cr, registry, module):
that need migration (for example in case of VAT report improvements)
'''
xml_record_ids = registry['ir.model.data'].search(cr, SUPERUSER_ID, [('model', 'in', ['account.tax.template', 'account.account.tag']), ('module', 'like', module)])
- cr.execute("update ir_model_data set noupdate = 'f' where id in %s", (tuple(xml_record_ids),))
+ if xml_record_ids:
+ cr.execute("update ir_model_data set noupdate = 'f' where id in %s", (tuple(xml_record_ids),))
def migrate_tags_on_taxes(cr, registry):
''' This is a utiliy function to help migrate the tags of taxes when the localization has been modified on stable version. If
diff --git a/addons/account/report/account_aged_partner_balance.py b/addons/account/report/account_aged_partner_balance.py
index 6dfcd6a7e8b..ef922719c7f 100644
--- a/addons/account/report/account_aged_partner_balance.py
+++ b/addons/account/report/account_aged_partner_balance.py
@@ -12,6 +12,7 @@ class ReportAgedPartnerBalance(models.AbstractModel):
res = []
self.total_account = []
cr = self.env.cr
+ user_company = self.env.user.company_id.id
move_state = ['draft', 'posted']
if target_move == 'posted':
move_state = ['posted']
@@ -25,7 +26,8 @@ class ReportAgedPartnerBalance(models.AbstractModel):
AND l.reconciled IS FALSE\
AND (l.partner_id = res_partner.id)\
AND (l.date <= %s)\
- ORDER BY res_partner.name', (tuple(move_state), tuple(account_type), date_from))
+ AND l.company_id = %s \
+ ORDER BY res_partner.name', (tuple(move_state), tuple(account_type), date_from, user_company))
partners = cr.dictfetchall()
# put a total of 0
@@ -46,7 +48,8 @@ class ReportAgedPartnerBalance(models.AbstractModel):
AND (account_account.internal_type IN %s)\
AND (l.partner_id IN %s)\
AND (l.date <= %s)\
- GROUP BY l.partner_id ', (tuple(move_state), tuple(account_type), tuple(partner_ids), date_from,))
+ AND l.company_id = %s \
+ GROUP BY l.partner_id ', (tuple(move_state), tuple(account_type), tuple(partner_ids), date_from, user_company))
partner_totals = cr.fetchall()
for partner_id, amount in partner_totals:
totals[partner_id] = amount
@@ -62,7 +65,8 @@ class ReportAgedPartnerBalance(models.AbstractModel):
AND (l.partner_id IN %s)\
AND l.reconciled IS FALSE\
AND l.date <= %s \
- GROUP BY l.partner_id', (tuple(move_state), tuple(account_type), date_from, tuple(partner_ids), date_from))
+ AND l.company_id = %s \
+ GROUP BY l.partner_id', (tuple(move_state), tuple(account_type), date_from, tuple(partner_ids), date_from, user_company))
partner_totals = cr.fetchall()
for partner_id, amount in partner_totals:
future_past[partner_id] = amount
@@ -83,7 +87,7 @@ class ReportAgedPartnerBalance(models.AbstractModel):
else:
dates_query += ' <= %s)'
args_list += (form[str(i)]['stop'],)
- args_list += (date_from,)
+ args_list += (date_from, user_company)
query = '''SELECT l.id
FROM account_move_line AS l, account_account, account_move am
@@ -93,11 +97,11 @@ class ReportAgedPartnerBalance(models.AbstractModel):
AND (l.partner_id IN %s)
AND ''' + dates_query + '''
AND (l.date <= %s)
- GROUP BY l.partner_id, l.id'''
+ AND l.company_id = %s'''
cr.execute(query, args_list)
partners_amount = {}
aml_ids = cr.fetchall()
- aml_ids = aml_ids and aml_ids[0] or []
+ aml_ids = aml_ids and [x[0] for x in aml_ids] or []
for line in self.env['account.move.line'].browse(aml_ids):
if line.partner_id.id not in partners_amount:
partners_amount[line.partner_id.id] = 0.0
@@ -150,6 +154,7 @@ class ReportAgedPartnerBalance(models.AbstractModel):
if target_move == 'posted':
move_state = ['posted']
+ user_company = self.env.user.company_id.id
## put a total of 0
for i in range(7):
self.total_account.append(0)
@@ -162,7 +167,8 @@ class ReportAgedPartnerBalance(models.AbstractModel):
AND (account_account.internal_type IN %s)\
AND l.reconciled IS FALSE \
AND (l.date <= %s)\
- ',(tuple(move_state), tuple(account_type), date_from,))
+ AND l.company_id = %s\
+ ',(tuple(move_state), tuple(account_type), date_from, user_company))
total_amount = cr.fetchall()
for amount in total_amount:
totals['Unknown Partner'] = amount[0]
@@ -175,7 +181,8 @@ class ReportAgedPartnerBalance(models.AbstractModel):
AND (account_account.internal_type IN %s)\
AND (COALESCE(l.date_maturity,l.date) > %s)\
AND l.reconciled IS FALSE\
- ', (tuple(move_state), tuple(account_type), date_from,))
+ AND l.company_id = %s\
+ ', (tuple(move_state), tuple(account_type), date_from, user_company))
total_amount = cr.fetchall()
for amount in total_amount:
future_past['Unknown Partner'] = amount[0]
@@ -193,7 +200,7 @@ class ReportAgedPartnerBalance(models.AbstractModel):
else:
dates_query += ' < %s)'
args_list += (form[str(i)]['stop'],)
- args_list += (date_from,)
+ args_list += (date_from, user_company)
cr.execute('SELECT SUM(l.debit - l.credit)\
FROM account_move_line AS l, account_account, account_move am \
WHERE (l.account_id = account_account.id) AND (l.move_id = am.id)\
@@ -203,6 +210,7 @@ class ReportAgedPartnerBalance(models.AbstractModel):
AND l.reconciled IS FALSE\
AND ' + dates_query + '\
AND (l.date <= %s)\
+ AND l.company_id = %s\
GROUP BY l.partner_id', args_list)
total_amount = cr.fetchall()
history_data = {}
diff --git a/addons/account_extra_reports/report/account_journal.py b/addons/account_extra_reports/report/account_journal.py
index 77d7d8222cf..90bfba7cba0 100644
--- a/addons/account_extra_reports/report/account_journal.py
+++ b/addons/account_extra_reports/report/account_journal.py
@@ -17,12 +17,12 @@ class ReportJournal(models.AbstractModel):
query_get_clause = self._get_query_get_clause(data)
params = [tuple(move_state), tuple(journal_ids)] + query_get_clause[2]
- query = 'SELECT "account_move_line".id FROM ' + query_get_clause[0] + ', account_move am WHERE "account_move_line".move_id=am.id AND am.state IN %s AND "account_move_line".journal_id IN %s AND ' + query_get_clause[1] + ' ORDER BY '
+ query = 'SELECT "account_move_line".id FROM ' + query_get_clause[0] + ', account_move am, account_account acc WHERE "account_move_line".account_id = acc.id AND "account_move_line".move_id=am.id AND am.state IN %s AND "account_move_line".journal_id IN %s AND ' + query_get_clause[1] + ' ORDER BY '
if sort_selection == 'date':
query += '"account_move_line".date'
else:
query += 'am.name'
- query += ', "account_move_line".move_id'
+ query += ', "account_move_line".move_id, acc.code'
self.env.cr.execute(query, tuple(params))
ids = map(lambda x: x[0], self.env.cr.fetchall())
return self.env['account.move.line'].browse(ids)
@@ -58,23 +58,32 @@ class ReportJournal(models.AbstractModel):
query_get_clause = self._get_query_get_clause(data)
params = [tuple(move_state), tuple(journal_id.ids)] + query_get_clause[2]
- self.env.cr.execute('SELECT DISTINCT tax_line_id FROM ' + query_get_clause[0] + ', account_move am '
- 'WHERE "account_move_line".move_id=am.id AND am.state IN %s AND "account_move_line".journal_id IN %s AND ' + query_get_clause[1] + ' AND tax_line_id is not null',
- tuple(params))
- ids = map(lambda x: x[0], self.env.cr.fetchall())
- taxes = self.env['account.tax'].browse(ids)
+ query = """
+ SELECT rel.account_tax_id, SUM("account_move_line".balance) AS base_amount
+ FROM account_move_line_account_tax_rel rel, """ + query_get_clause[0] + """
+ LEFT JOIN account_move am ON "account_move_line".move_id = am.id
+ WHERE "account_move_line".id = rel.account_move_line_id
+ AND am.state IN %s
+ AND "account_move_line".journal_id IN %s
+ AND """ + query_get_clause[1] + """
+ GROUP BY rel.account_tax_id"""
+ self.env.cr.execute(query, tuple(params))
+ ids = []
+ base_amounts = {}
+ for row in self.env.cr.fetchall():
+ ids.append(row[0])
+ base_amounts[row[0]] = row[1]
+
+
res = {}
- for tax in taxes:
- res[tax] = {}
+ for tax in self.env['account.tax'].browse(ids):
self.env.cr.execute('SELECT sum(debit - credit) FROM ' + query_get_clause[0] + ', account_move am '
'WHERE "account_move_line".move_id=am.id AND am.state IN %s AND "account_move_line".journal_id IN %s AND ' + query_get_clause[1] + ' AND tax_line_id = %s',
tuple(params + [tax.id]))
- res[tax]['tax_amount'] = self.env.cr.fetchone()[0] or 0.0
- amls = self.env['account.move.line'].search([('tax_ids', 'in', [tax.id])])
- self.env.cr.execute('SELECT sum(debit - credit) FROM ' + query_get_clause[0] + ', account_move am '
- 'WHERE "account_move_line".move_id=am.id AND am.state IN %s AND "account_move_line".journal_id IN %s AND ' + query_get_clause[1] + ' AND "account_move_line".id in %s',
- tuple(params + [tuple(amls.ids)]))
- res[tax]['base_amount'] = self.env.cr.fetchone()[0] or 0.0
+ res[tax] = {
+ 'base_amount': base_amounts[tax.id],
+ 'tax_amount': self.env.cr.fetchone()[0] or 0.0,
+ }
if journal_id.type == 'sale':
#sales operation are credits
res[tax]['base_amount'] = res[tax]['base_amount'] * -1
diff --git a/addons/product/pricelist.py b/addons/product/pricelist.py
index d1b01f15de0..28160e6b92c 100644
--- a/addons/product/pricelist.py
+++ b/addons/product/pricelist.py
@@ -242,8 +242,7 @@ class product_pricelist(osv.osv):
break
# Final price conversion into pricelist currency
if suitable_rule and suitable_rule.compute_price != 'fixed' and suitable_rule.base != 'pricelist':
- user_company = self.pool['res.users'].browse(cr, uid, uid, context=context).company_id
- price = self.pool['res.currency'].compute(cr, uid, user_company.currency_id.id, pricelist.currency_id.id, price, context=context)
+ price = self.pool['res.currency'].compute(cr, uid, product.currency_id.id, pricelist.currency_id.id, price, context=context)
results[product.id] = (price, suitable_rule and suitable_rule.id or False)
return results
diff --git a/addons/product/product.py b/addons/product/product.py
index 0bc1ec3de85..3440b03ee41 100644
--- a/addons/product/product.py
+++ b/addons/product/product.py
@@ -421,6 +421,17 @@ class product_template(osv.osv):
return product.write({'list_price': value})
+ def _product_currency(self, cr, uid, ids, name, arg, context=None):
+ try:
+ main_company = self.pool['ir.model.data'].get_object(cr, uid, 'base', 'main_company')
+ except ValueError:
+ company_ids = self.pool['res.company'].search(cr, uid, [], limit=1, order="id", context=context)
+ main_company = self.pool['res.company'].browse(cr, uid, company_ids[0], context=context)
+ res = {}
+ for product in self.browse(cr, uid, ids, context=context):
+ res[product.id] = product.company_id.currency_id.id or main_company.currency_id.id
+ return res
+
def _get_product_variant_count(self, cr, uid, ids, name, arg, context=None):
res = {}
for product in self.browse(cr, uid, ids, context=context):
@@ -477,11 +488,7 @@ class product_template(osv.osv):
'rental': fields.boolean('Can be Rent'),
'categ_id': fields.many2one('product.category','Internal Category', required=True, change_default=True, domain="[('type','=','normal')]" ,help="Select category for the current product"),
'price': fields.function(_product_template_price, fnct_inv=_set_product_template_price, type='float', string='Price', digits_compute=dp.get_precision('Product Price')),
- 'currency_id': fields.related(
- 'company_id', 'currency_id',
- type='many2one',
- relation='res.currency',
- string='Currency'),
+ 'currency_id': fields.function(_product_currency, type='many2one', relation='res.currency', string='Currency'),
'list_price': fields.float('Sale Price', digits_compute=dp.get_precision('Product Price'), help="Base price to compute the customer price. Sometimes called the catalog price."),
'lst_price' : fields.related('list_price', type="float", string='Public Price', digits_compute=dp.get_precision('Product Price')),
'standard_price': fields.function(_compute_product_template_field, fnct_inv=_set_product_template_field, fnct_search=_search_by_standard_price, multi='_compute_product_template_field', type='float', string='Cost', digits_compute=dp.get_precision('Product Price'),
@@ -556,8 +563,6 @@ class product_template(osv.osv):
if context is None:
context = {}
- if 'currency_id' in context:
- currency_id = self.pool['res.users'].browse(cr, uid, uid, context=context).company_id.currency_id.id
res = {}
product_uom_obj = self.pool.get('product.uom')
for product in products:
@@ -580,7 +585,7 @@ class product_template(osv.osv):
if 'currency_id' in context:
# Take current user company currency.
# This is right cause a field cannot be in more than one currency
- res[product.id] = self.pool.get('res.currency').compute(cr, uid, currency_id,
+ res[product.id] = self.pool.get('res.currency').compute(cr, uid, product.currency_id.id,
context['currency_id'], res[product.id], context=context)
return res
diff --git a/addons/product_visible_discount/product_visible_discount.py b/addons/product_visible_discount/product_visible_discount.py
index 426dea5a9ed..077ec1efa21 100644
--- a/addons/product_visible_discount/product_visible_discount.py
+++ b/addons/product_visible_discount/product_visible_discount.py
@@ -70,7 +70,7 @@ class sale_order_line(osv.osv):
line.discount = 0.0
return res
- @api.onchange('product_uom')
+ @api.onchange('product_uom', 'product_uom_qty')
def product_uom_change(self):
res = super(sale_order_line, self).product_uom_change()
if not self.product_uom:
diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml
index 2a74e6680ad..cd171a98785 100644
--- a/addons/purchase/purchase_view.xml
+++ b/addons/purchase/purchase_view.xml
@@ -415,7 +415,7 @@