diff --git a/addons/account/models/account.py b/addons/account/models/account.py
index eec37901431..c65819c3bfe 100644
--- a/addons/account/models/account.py
+++ b/addons/account/models/account.py
@@ -703,7 +703,12 @@ class AccountTax(models.Model):
if not round_tax:
prec += 5
- total_excluded = total_included = base = round(price_unit * quantity, prec)
+
+ base_values = self.env.context.get('base_values')
+ if not base_values:
+ total_excluded = total_included = base = round(price_unit * quantity, prec)
+ else:
+ total_excluded, total_included, base = base_values
# Sorting key is mandatory in this case. When no key is provided, sorted() will perform a
# search. However, the search method is overridden in account.tax in order to add a domain
@@ -711,9 +716,10 @@ class AccountTax(models.Model):
# case of group taxes.
for tax in self.sorted(key=lambda r: r.sequence):
if tax.amount_type == 'group':
- ret = tax.children_tax_ids.compute_all(price_unit, currency, quantity, product, partner)
+ children = tax.children_tax_ids.with_context(base_values=(total_excluded, total_included, base))
+ ret = children.compute_all(price_unit, currency, quantity, product, partner)
total_excluded = ret['total_excluded']
- base = ret['base']
+ base = ret['base'] if tax.include_base_amount else base
total_included = ret['total_included']
tax_amount = total_included - total_excluded
taxes += ret['taxes']
diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py
index 204f0161a85..931ae7f41df 100644
--- a/addons/account/models/account_bank_statement.py
+++ b/addons/account/models/account_bank_statement.py
@@ -472,7 +472,7 @@ class AccountBankStatementLine(models.Model):
'details': {
'name': _("Automatically reconciled items"),
'model': 'account.move',
- 'ids': automatic_reconciliation_entries.ids
+ 'ids': automatic_reconciliation_entries.mapped('journal_entry_ids').ids
}
}]
return {
diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py
index 489f5785252..8028355d76e 100644
--- a/addons/account/models/account_invoice.py
+++ b/addons/account/models/account_invoice.py
@@ -612,6 +612,14 @@ class AccountInvoice(models.Model):
'account_analytic_id': tax['analytic'] and line.account_analytic_id.id or False,
'account_id': self.type in ('out_invoice', 'in_invoice') and (tax['account_id'] or line.account_id.id) or (tax['refund_account_id'] or line.account_id.id),
}
+
+ # If the taxes generate moves on the same financial account as the invoice line,
+ # propagate the analytic account from the invoice line to the tax line.
+ # This is necessary in situations were (part of) the taxes cannot be reclaimed,
+ # to ensure the tax move is allocated to the proper analytic account.
+ if not vals.get('account_analytic_id') and line.account_analytic_id and vals['account_id'] == line.account_id.id:
+ vals['account_analytic_id'] = line.account_analytic_id.id
+
return vals
@api.multi
@@ -622,14 +630,6 @@ class AccountInvoice(models.Model):
taxes = line.invoice_line_tax_ids.compute_all(price_unit, self.currency_id, line.quantity, line.product_id, self.partner_id)['taxes']
for tax in taxes:
val = self._prepare_tax_line_vals(line, tax)
-
- # If the taxes generate moves on the same financial account as the invoice line,
- # propagate the analytic account from the invoice line to the tax line.
- # This is necessary in situations were (part of) the taxes cannot be reclaimed,
- # to ensure the tax move is allocated to the proper analytic account.
- if not val.get('account_analytic_id') and line.account_analytic_id and val['account_id'] == line.account_id.id:
- val['account_analytic_id'] = line.account_analytic_id.id
-
key = self.env['account.tax'].browse(tax['id']).get_grouping_key(val)
if key not in tax_grouped:
diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py
index 36ca9718b74..e825ebc4ac1 100644
--- a/addons/account/models/account_move.py
+++ b/addons/account/models/account_move.py
@@ -154,6 +154,7 @@ class AccountMove(models.Model):
'SET state=%s '\
'WHERE id IN %s', ('draft', tuple(self.ids),))
self.invalidate_cache()
+ self._check_lock_date()
return True
@api.multi
@@ -988,6 +989,9 @@ class AccountMoveLine(models.Model):
return True
rec_move_ids = self.env['account.partial.reconcile']
for account_move_line in self:
+ for invoice in account_move_line.payment_id.invoice_ids:
+ if account_move_line in invoice.payment_move_line_ids:
+ account_move_line.payment_id.write({'invoice_ids': [(3, invoice.id, None)]})
rec_move_ids += account_move_line.matched_debit_ids
rec_move_ids += account_move_line.matched_credit_ids
return rec_move_ids.unlink()
diff --git a/addons/account/report/account_invoice_report.py b/addons/account/report/account_invoice_report.py
index 9d0b3d3da27..eb969cadec4 100644
--- a/addons/account/report/account_invoice_report.py
+++ b/addons/account/report/account_invoice_report.py
@@ -45,7 +45,7 @@ class AccountInvoiceReport(models.Model):
user_currency_price_total = fields.Float(string="Total Without Tax", compute='_compute_amounts_in_user_currency', digits=0)
price_average = fields.Float(string='Average Price', readonly=True, group_operator="avg")
user_currency_price_average = fields.Float(string="Average Price", compute='_compute_amounts_in_user_currency', digits=0)
- currency_rate = fields.Float(string='Currency Rate', readonly=True)
+ currency_rate = fields.Float(string='Currency Rate', readonly=True, group_operator="avg")
nbr = fields.Integer(string='# of Lines', readonly=True) # TDE FIXME master: rename into nbr_lines
type = fields.Selection([
('out_invoice', 'Customer Invoice'),
diff --git a/addons/account/tests/test_tax.py b/addons/account/tests/test_tax.py
index d626f4e20e0..84aa784fad3 100644
--- a/addons/account/tests/test_tax.py
+++ b/addons/account/tests/test_tax.py
@@ -43,10 +43,46 @@ class TestTax(AccountTestUsers):
(4, self.percent_tax.id, 0)
]
})
+ self.group_tax_bis = self.tax_model.create({
+ 'name': "Group tax bis",
+ 'amount_type': 'group',
+ 'amount': 0,
+ 'sequence': 6,
+ 'children_tax_ids': [
+ (4, self.fixed_tax.id, 0),
+ (4, self.percent_tax.id, 0)
+ ]
+ })
+ self.group_of_group_tax = self.tax_model.create({
+ 'name': "Group of group tax",
+ 'amount_type': 'group',
+ 'amount': 0,
+ 'sequence': 7,
+ 'children_tax_ids': [
+ (4, self.group_tax.id, 0),
+ (4, self.group_tax_bis.id, 0)
+ ]
+ })
self.bank_journal = self.env['account.journal'].search([('type', '=', 'bank'), ('company_id', '=', self.account_manager.company_id.id)])[0]
self.bank_account = self.bank_journal.default_debit_account_id
self.expense_account = self.env['account.account'].search([('user_type_id.type', '=', 'payable')], limit=1) #Should be done by onchange later
+ def test_tax_group_of_group_tax(self):
+ self.fixed_tax.include_base_amount = True
+ self.group_tax.include_base_amount = True
+ self.group_of_group_tax.include_base_amount = True
+ res = self.group_of_group_tax.compute_all(200.0)
+ self.assertEquals(res['total_excluded'], 200.0)
+ # After calculation of first group
+ # base = 210
+ # total_included = 231
+ # Base of the first grouped is passed
+ # Base after the second group (220) is dropped.
+ # Base of the group of groups is passed out,
+ # so we obtain base as after first group
+ self.assertEquals(res['base'], 210.0)
+ self.assertEquals(res['total_included'], 263.0)
+
def test_tax_group(self):
res = self.group_tax.compute_all(200.0)
self.assertEquals(res['total_excluded'], 200.0)
diff --git a/addons/account/views/account_invoice_view.xml b/addons/account/views/account_invoice_view.xml
index 568bdead85d..e1da859f9d0 100644
--- a/addons/account/views/account_invoice_view.xml
+++ b/addons/account/views/account_invoice_view.xml
@@ -135,8 +135,8 @@
Use in conjunction with contracts to calculate your monthly revenue for multi-month contracts.
- Install Now diff --git a/addons/account_voucher/models/account_voucher.py b/addons/account_voucher/models/account_voucher.py index d621d73dcfa..d677a6490e5 100644 --- a/addons/account_voucher/models/account_voucher.py +++ b/addons/account_voucher/models/account_voucher.py @@ -30,10 +30,10 @@ class AccountVoucher(models.Model): name = fields.Char('Payment Reference', readonly=True, states={'draft': [('readonly', False)]}, default='') date = fields.Date("Bill Date", readonly=True, - select=True, states={'draft': [('readonly', False)]}, + index=True, states={'draft': [('readonly', False)]}, copy=False, default=fields.Date.context_today) account_date = fields.Date("Accounting Date", - readonly=True, select=True, states={'draft': [('readonly', False)]}, + readonly=True, index=True, states={'draft': [('readonly', False)]}, help="Effective date for accounting entries", copy=False, default=fields.Date.context_today) journal_id = fields.Many2one('account.journal', 'Journal', required=True, readonly=True, states={'draft': [('readonly', False)]}, default=_default_journal) diff --git a/addons/base_import/static/src/xml/base_import.xml b/addons/base_import/static/src/xml/base_import.xml index dce2ab6fe36..0d23096f691 100644 --- a/addons/base_import/static/src/xml/base_import.xml +++ b/addons/base_import/static/src/xml/base_import.xml @@ -8,7 +8,7 @@