From 39d68acd08a7e526c04e72a0b263b655bf07317b Mon Sep 17 00:00:00 2001 From: qdp-odoo Date: Thu, 25 Aug 2016 10:15:27 +0200 Subject: [PATCH] [FIX] account_tax_cash_basis: add the mechanism to report cash basis taxes at the payment time only. Previsouly they were directly included in the tax reports, in the period of the invoice, and even if it was still unpaid. Although this is a bugfix, it involves creation of new fields and thus cannot lands at it on stable versions where our policy disallow database changes. --- addons/account/models/account_move.py | 2 + .../models/account_move.py | 17 +++++- .../models/account_partial_reconcile.py | 57 +++++++++++++------ 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index d5d346628c9..0470655af7b 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -413,6 +413,8 @@ class AccountMoveLine(models.Model): invoice_id = fields.Many2one('account.invoice', oldname="invoice") partner_id = fields.Many2one('res.partner', string='Partner', ondelete='restrict') user_type_id = fields.Many2one('account.account.type', related='account_id.user_type_id', index=True, store=True, oldname="user_type") + tax_exigible = fields.Boolean(string='Appears in VAT report', default=True, + help="Technical field used to mark a tax line as exigible in the vat report or not (only exigible journal items are displayed). By default all new journal items are directly exigible, but with the module account_tax_cash_basis, some will become exigible only when the payment is recorded.") _sql_constraints = [ ('credit_debit1', 'CHECK (credit*debit=0)', 'Wrong credit or debit value in accounting entry !'), diff --git a/addons/account_tax_cash_basis/models/account_move.py b/addons/account_tax_cash_basis/models/account_move.py index 1fac8221343..73b99952501 100644 --- a/addons/account_tax_cash_basis/models/account_move.py +++ b/addons/account_tax_cash_basis/models/account_move.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import models, fields +from odoo import api, models, fields class AccountMoveCashBasis(models.Model): @@ -12,3 +12,18 @@ class AccountMoveCashBasis(models.Model): string='Tax Cash Basis Entry of', help="Technical field used to keep track of the tax cash basis reconciliation." "This is needed when cancelling the source: it will post the inverse journal entry to cancel that part too.") + + +class AccountMoveLine(models.Model): + _inherit = "account.move.line" + + @api.model + def create(self, vals, apply_taxes=True): + taxes = False + if vals.get('tax_line_id'): + taxes = [{'use_cash_basis': self.env['account.tax'].browse(vals['tax_line_id']).use_cash_basis}] + if vals.get('tax_ids'): + taxes = self.env['account.move.line'].resolve_2many_commands('tax_ids', vals['tax_ids']) + if taxes and any([tax['use_cash_basis'] for tax in taxes]) and not vals.get('tax_exigible'): + vals['tax_exigible'] = False + return super(AccountMoveLine, self).create(vals, apply_taxes=apply_taxes) diff --git a/addons/account_tax_cash_basis/models/account_partial_reconcile.py b/addons/account_tax_cash_basis/models/account_partial_reconcile.py index bb6bff7f53c..8cf22009c9e 100644 --- a/addons/account_tax_cash_basis/models/account_partial_reconcile.py +++ b/addons/account_tax_cash_basis/models/account_partial_reconcile.py @@ -12,25 +12,47 @@ class AccountPartialReconcileCashBasis(models.Model): # Search in account_move if we have any taxes account move lines tax_group = {} total_by_cash_basis_account = {} + line_to_create = [] for move in (self.debit_move_id.move_id, self.credit_move_id.move_id): for line in move.line_ids: - if line.tax_line_id and line.tax_line_id.use_cash_basis: + #TOCHECK: normal and cash basis taxes shoudn't be mixed together (on the same invoice line for example) as it will + #create reporting issues. Not sure of the behavior to implement in that case, though. + if not line.tax_exigible: # amount to write is the current cash_basis amount minus the one before the reconciliation matched_percentage = value_before_reconciliation[move.id] amount = (line.credit_cash_basis - line.debit_cash_basis) - (line.credit - line.debit) * matched_percentage - # group by line account - acc = line.account_id.id - if tax_group.get(acc, False): - tax_group[acc] += amount - else: - tax_group[acc] = amount - # Group by cash basis account - acc = line.tax_line_id.cash_basis_account.id - if total_by_cash_basis_account.get(acc, False): - total_by_cash_basis_account[acc] += amount - else: - total_by_cash_basis_account[acc] = amount - line_to_create = [] + if line.tax_line_id and line.tax_line_id.use_cash_basis: + # group by line account + acc = line.account_id.id + if tax_group.get(acc, False): + tax_group[acc] += amount + else: + tax_group[acc] = amount + + # Group by cash basis account and tax + acc = line.tax_line_id.cash_basis_account.id + key = (acc, line.tax_line_id.id) + if key in total_by_cash_basis_account: + total_by_cash_basis_account[key] += amount + else: + total_by_cash_basis_account[key] = amount + for tax in line.tax_ids: + if tax.use_cash_basis: + line_to_create.append((0, 0, { + 'name': '/', + 'debit': line.debit_cash_basis - line.debit * matched_percentage, + 'credit': line.credit_cash_basis - line.credit * matched_percentage, + 'account_id': line.account_id.id, + 'tax_ids': [(6, 0, [tax.id])], + 'tax_exigible': True, + })) + line_to_create.append((0, 0, { + 'name': '/', + 'credit': line.debit_cash_basis - line.debit * matched_percentage, + 'debit': line.credit_cash_basis - line.credit * matched_percentage, + 'account_id': line.account_id.id, + })) + for k, v in tax_group.items(): line_to_create.append((0, 0, { 'name': '/', @@ -40,12 +62,15 @@ class AccountPartialReconcileCashBasis(models.Model): })) # Create counterpart vals - for k, v in total_by_cash_basis_account.items(): + for key, v in total_by_cash_basis_account.items(): + k, tax_id = key line_to_create.append((0, 0, { 'name': '/', 'debit': abs(v) if v < 0 else 0.0, 'credit': v if v > 0 else 0.0, 'account_id': k, + 'tax_line_id': tax_id, + 'tax_exigible': True, })) # Create move @@ -55,7 +80,7 @@ class AccountPartialReconcileCashBasis(models.Model): raise UserError(_('There is no tax cash basis journal defined ' \ 'for this company: "%s" \nConfigure it in Accounting/Configuration/Settings') % \ (self.company_id.name)) - move = self.env['account.move'].create({ + move = self.env['account.move'].with_context(dont_create_taxes=True).create({ 'journal_id': self.company_id.tax_cash_basis_journal_id.id, 'line_ids': line_to_create, 'tax_cash_basis_rec_id': self.id})