Browse Source

[FIX] account_tax_balance: Account moves linked to bills/invoices should not be considered as refunds, unless all their lines come from refunds or their balance is negative.

pull/732/head
SimoRubi 4 years ago
parent
commit
50c389ea44
  1. 35
      account_tax_balance/models/account_move.py
  2. 68
      account_tax_balance/tests/test_account_tax_balance.py

35
account_tax_balance/models/account_move.py

@ -2,7 +2,7 @@
# © 2016 Antonio Espinosa <antonio.espinosa@tecnativa.com> # © 2016 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api
from odoo import models, fields, api
class AccountMove(models.Model): class AccountMove(models.Model):
@ -21,25 +21,38 @@ class AccountMove(models.Model):
@api.multi @api.multi
@api.depends( @api.depends(
'line_ids.account_id.internal_type', 'line_ids.balance', 'line_ids.account_id.internal_type', 'line_ids.balance',
'line_ids.account_id.user_type_id.type'
'line_ids.account_id.user_type_id.type', 'line_ids.invoice_id.type'
) )
def _compute_move_type(self): def _compute_move_type(self):
def _balance_get(line_ids, internal_type):
return sum(line_ids.filtered(
lambda x: x.account_id.internal_type == internal_type).mapped(
'balance'))
refund_types = ('in_refund', 'out_refund')
def _is_refund(line_ids, internal_type):
"""Check whether all the lines of type `internal_type`
come from a refund."""
line_ids = line_ids.filtered(
lambda x: x.account_id.internal_type == internal_type)
line_types = line_ids.mapped('invoice_id.type')
if len(line_types) == 1:
res = line_types[0] in refund_types
else:
# Lines are linked to invoices of different types,
# or to no invoice at all.
# If their summed balance is negative, this is a refund.
res = sum(line_ids.mapped('balance')) < 0
return res
for move in self: for move in self:
internal_types = move.line_ids.mapped('account_id.internal_type')
move_lines = move.line_ids
internal_types = move_lines.mapped('account_id.internal_type')
if 'liquidity' in internal_types: if 'liquidity' in internal_types:
move.move_type = 'liquidity' move.move_type = 'liquidity'
elif 'payable' in internal_types: elif 'payable' in internal_types:
balance = _balance_get(move.line_ids, 'payable')
is_refund = _is_refund(move_lines, 'payable')
move.move_type = ( move.move_type = (
'payable' if balance < 0 else 'payable_refund')
'payable' if not is_refund else 'payable_refund')
elif 'receivable' in internal_types: elif 'receivable' in internal_types:
balance = _balance_get(move.line_ids, 'receivable')
is_refund = _is_refund(move_lines, 'receivable')
move.move_type = ( move.move_type = (
'receivable' if balance > 0 else 'receivable_refund')
'receivable' if not is_refund else 'receivable_refund')
else: else:
move.move_type = 'other' move.move_type = 'other'

68
account_tax_balance/tests/test_account_tax_balance.py

@ -179,3 +179,71 @@ class TestAccountTaxBalance(TransactionCase):
tax.refresh() tax.refresh()
self.assertEquals(tax.base_balance, 175.) self.assertEquals(tax.base_balance, 175.)
self.assertEquals(tax.balance, 17.5) self.assertEquals(tax.balance, 17.5)
def test_receivable_move_type(self):
"""
Receivable moves linked to invoices are not considered as refunds.
Also, receivable moves coming from refunds are considered as such.
"""
receivable_account = self.env['account.account'].search(
[('user_type_id', '=', self.env.ref(
'account.data_account_type_receivable'
).id)], limit=1)
invoice = self.env['account.invoice'].create({
'partner_id': self.env.ref('base.res_partner_2').id,
'account_id': receivable_account.id,
'type': 'out_invoice',
'invoice_line_ids': [(0, 0, {
'product_id': self.env.ref('product.product_product_4').id,
'account_id': receivable_account.id,
'quantity': 1.0,
'price_unit': 100.0,
'name': 'product that costs 100',
}), (0, 0, {
'product_id': self.env.ref('product.product_product_4').id,
'account_id': receivable_account.id,
'quantity': 1.0,
'price_unit': -100.0,
'name': 'product that costs -100',
})]
})
invoice.action_invoice_open()
self.assertEqual(invoice.move_id.move_type, 'receivable')
refund = invoice.refund()
refund.action_invoice_open()
self.assertEqual(refund.move_id.move_type, 'receivable_refund')
def test_payable_move_type(self):
"""
Payable moves linked to bills are not considered as refunds.
Also, payable moves coming from refunds are considered as such.
"""
payable_account = self.env['account.account'].search(
[('user_type_id', '=', self.env.ref(
'account.data_account_type_payable'
).id)], limit=1)
bill = self.env['account.invoice'].create({
'partner_id': self.env.ref('base.res_partner_2').id,
'account_id': payable_account.id,
'type': 'in_invoice',
'invoice_line_ids': [(0, 0, {
'product_id': self.env.ref('product.product_product_4').id,
'account_id': payable_account.id,
'quantity': 1.0,
'price_unit': 100.0,
'name': 'product that costs 100',
}), (0, 0, {
'product_id': self.env.ref('product.product_product_4').id,
'account_id': payable_account.id,
'quantity': 1.0,
'price_unit': -100.0,
'name': 'product that costs -100',
})]
})
bill.action_invoice_open()
self.assertEqual(bill.move_id.move_type, 'payable')
refund = bill.refund()
refund.action_invoice_open()
self.assertEqual(refund.move_id.move_type, 'payable_refund')
Loading…
Cancel
Save