# -*- coding: utf-8 -*- # © 2016 Lorenzo Battistini - Agile Business Group # © 2016 Antonio Espinosa # 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="Total Balance", compute="_compute_balance", search='_search_balance') base_balance = fields.Float( 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 return ( context.get('from_date', fields.Date.context_today(self)), context.get('to_date', fields.Date.context_today(self)), context.get('company_id', self.env.user.company_id.id), context.get('target_move', 'posted') ) def _compute_balance(self): for tax in self: 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': state = ['posted'] elif target_move == 'all': state = ['posted', 'draft'] else: state = [] return state def get_move_line_partial_domain(self, from_date, to_date, company_id): return [ ('date', '<=', to_date), ('date', '>=', from_date), ('company_id', '=', company_id), ] 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_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, 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, 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', 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, type_list) elif tax_or_base == 'base': 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_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] vals['context'] = {} vals['domain'] = [('id', 'in', move_line_ids)] return vals @api.multi def view_tax_lines(self): self.ensure_one() return self.get_lines_action(tax_or_base='tax') @api.multi 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')