Consider normal and refund operations separately

Allow to explore all move lines

Spanish translation

Bugfixes

Show negative lines too

Show move type in account.move views

Tests include new fields
This commit is contained in:
Antonio Espinosa
2016-10-21 15:08:38 +02:00
committed by Borruso
parent a48acb15d4
commit 3b74e4813c
9 changed files with 605 additions and 104 deletions

View File

@@ -2,4 +2,5 @@
# © 2016 Lorenzo Battistini - Agile Business Group
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import account_move
from . import account_tax

View File

@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
# © 2016 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api
class AccountMove(models.Model):
_inherit = 'account.move'
move_type = fields.Selection(
string="Move type", selection=[
('other', 'Other'),
('liquidity', 'Liquidity'),
('receivable', 'Receivable'),
('receivable_refund', 'Receivable refund'),
('payable', 'Payable'),
('payable_refund', 'Payable refund'),
], compute='_compute_move_type', store=True, readonly=True)
@api.multi
@api.depends('line_ids.account_id.internal_type', 'line_ids.balance')
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'))
for move in self:
internal_types = move.line_ids.mapped('account_id.internal_type')
if 'liquidity' in internal_types:
move.move_type = 'liquidity'
elif 'payable' in internal_types:
balance = _balance_get(move.line_ids, 'payable')
move.move_type = (
'payable' if balance < 0 else 'payable_refund')
elif 'receivable' in internal_types:
balance = _balance_get(move.line_ids, 'receivable')
move.move_type = (
'receivable' if balance > 0 else 'receivable_refund')
else:
move.move_type = 'other'

View File

@@ -1,16 +1,68 @@
# -*- coding: utf-8 -*-
# © 2016 Lorenzo Battistini - Agile Business Group
# © 2016 Antonio Espinosa <antonio.espinosa@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api
from openerp.tools.safe_eval import safe_eval
class AccountTax(models.Model):
_inherit = 'account.tax'
balance = fields.Float(string="Balance", compute="_compute_balance")
balance = fields.Float(
string="Total Balance", compute="_compute_balance",
search='_search_balance')
base_balance = fields.Float(
string="Base Balance", compute="_compute_balance")
string="Total Base Balance", compute="_compute_balance",
search='_search_base_balance')
balance_regular = fields.Float(
string="Balance", compute="_compute_balance",
search='_search_balance_regular')
base_balance_regular = fields.Float(
string="Base Balance", compute="_compute_balance",
search='_search_base_balance_regular')
balance_refund = fields.Float(
string="Balance Refund", compute="_compute_balance",
search='_search_balance_refund')
base_balance_refund = fields.Float(
string="Base Balance Refund", compute="_compute_balance",
search='_search_base_balance_refund')
def _search_balance_field(self, field, operator, value):
operators = {'>', '<', '>=', '<=', '!=', '=', '<>'}
fields = {
'balance', 'base_balance', 'balance_regular',
'base_balance_regular', 'balance_refund', 'base_balance_refund',
}
domain = []
if operator in operators and field in fields:
value = float(value) if value else 0
taxes = self.search([]).filtered(
lambda x: safe_eval(
'%.2f %s %.2f' % (x[field], operator, value)))
domain.append(('id', 'in', taxes.ids))
return domain
def _search_balance(self, operator, value):
return self._search_balance_field('balance', operator, value)
def _search_base_balance(self, operator, value):
return self._search_balance_field('base_balance', operator, value)
def _search_balance_regular(self, operator, value):
return self._search_balance_field('balance_regular', operator, value)
def _search_base_balance_regular(self, operator, value):
return self._search_balance_field(
'base_balance_regular', operator, value)
def _search_balance_refund(self, operator, value):
return self._search_balance_field('balance_refund', operator, value)
def _search_base_balance_refund(self, operator, value):
return self._search_balance_field(
'base_balance_refund', operator, value)
def get_context_values(self):
context = self.env.context
@@ -23,8 +75,24 @@ class AccountTax(models.Model):
def _compute_balance(self):
for tax in self:
tax.balance = tax.compute_balance(tax_or_base='tax')
tax.base_balance = tax.compute_balance(tax_or_base='base')
tax.balance_regular = tax.compute_balance(
tax_or_base='tax', move_type='regular')
tax.base_balance_regular = tax.compute_balance(
tax_or_base='base', move_type='regular')
tax.balance_refund = tax.compute_balance(
tax_or_base='tax', move_type='refund')
tax.base_balance_refund = tax.compute_balance(
tax_or_base='base', move_type='refund')
tax.balance = tax.balance_regular + tax.balance_refund
tax.base_balance = (
tax.base_balance_regular + tax.base_balance_refund)
def get_target_type_list(self, move_type=None):
if move_type == 'refund':
return ['receivable_refund', 'payable_refund']
elif move_type == 'regular':
return ['receivable', 'payable']
return []
def get_target_state_list(self, target_move="posted"):
if target_move == 'posted':
@@ -42,43 +110,53 @@ class AccountTax(models.Model):
('company_id', '=', company_id),
]
def compute_balance(self, tax_or_base='tax'):
def compute_balance(self, tax_or_base='tax', move_type=None):
self.ensure_one()
move_lines = self.get_move_lines_domain(tax_or_base=tax_or_base)
move_lines = self.get_move_lines_domain(
tax_or_base=tax_or_base, move_type=move_type)
# balance is debit - credit whereas on tax return you want to see what
# vat has to be paid so:
# VAT on sales (credit) - VAT on purchases (debit).
total = -sum([l.balance for l in move_lines])
return total
def get_balance_domain(self, state_list):
return [
def get_balance_domain(self, state_list, type_list):
domain = [
('move_id.state', 'in', state_list),
('tax_line_id', '=', self.id),
]
if type_list:
domain.append(('move_id.move_type', 'in', type_list))
return domain
def get_base_balance_domain(self, state_list):
return [
def get_base_balance_domain(self, state_list, type_list):
domain = [
('move_id.state', 'in', state_list),
('tax_ids', 'in', self.id),
]
if type_list:
domain.append(('move_id.move_type', 'in', type_list))
return domain
def get_move_lines_domain(self, tax_or_base='tax'):
def get_move_lines_domain(self, tax_or_base='tax', move_type=None):
move_line_model = self.env['account.move.line']
from_date, to_date, company_id, target_move = self.get_context_values()
state_list = self.get_target_state_list(target_move)
type_list = self.get_target_type_list(move_type)
domain = self.get_move_line_partial_domain(
from_date, to_date, company_id)
balance_domain = []
if tax_or_base == 'tax':
balance_domain = self.get_balance_domain(state_list)
balance_domain = self.get_balance_domain(state_list, type_list)
elif tax_or_base == 'base':
balance_domain = self.get_base_balance_domain(state_list)
balance_domain = self.get_base_balance_domain(
state_list, type_list)
domain.extend(balance_domain)
return move_line_model.search(domain)
def get_lines_action(self, tax_or_base='tax'):
move_lines = self.get_move_lines_domain(tax_or_base=tax_or_base)
def get_lines_action(self, tax_or_base='tax', move_type=None):
move_lines = self.get_move_lines_domain(
tax_or_base=tax_or_base, move_type=move_type)
move_line_ids = [l.id for l in move_lines]
action = self.env.ref('account.action_account_moves_all_tree')
vals = action.read()[0]
@@ -95,3 +173,23 @@ class AccountTax(models.Model):
def view_base_lines(self):
self.ensure_one()
return self.get_lines_action(tax_or_base='base')
@api.multi
def view_tax_regular_lines(self):
self.ensure_one()
return self.get_lines_action(tax_or_base='tax', move_type='regular')
@api.multi
def view_base_regular_lines(self):
self.ensure_one()
return self.get_lines_action(tax_or_base='base', move_type='regular')
@api.multi
def view_tax_refund_lines(self):
self.ensure_one()
return self.get_lines_action(tax_or_base='tax', move_type='refund')
@api.multi
def view_base_refund_lines(self):
self.ensure_one()
return self.get_lines_action(tax_or_base='base', move_type='refund')