You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
7.4 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2016 Lorenzo Battistini - Agile Business Group
  3. # © 2016 Antonio Espinosa <antonio.espinosa@tecnativa.com>
  4. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  5. from openerp import models, fields, api
  6. from openerp.tools.safe_eval import safe_eval
  7. class AccountTax(models.Model):
  8. _inherit = 'account.tax'
  9. balance = fields.Float(
  10. string="Total Balance", compute="_compute_balance",
  11. search='_search_balance')
  12. base_balance = fields.Float(
  13. string="Total Base Balance", compute="_compute_balance",
  14. search='_search_base_balance')
  15. balance_regular = fields.Float(
  16. string="Balance", compute="_compute_balance",
  17. search='_search_balance_regular')
  18. base_balance_regular = fields.Float(
  19. string="Base Balance", compute="_compute_balance",
  20. search='_search_base_balance_regular')
  21. balance_refund = fields.Float(
  22. string="Balance Refund", compute="_compute_balance",
  23. search='_search_balance_refund')
  24. base_balance_refund = fields.Float(
  25. string="Base Balance Refund", compute="_compute_balance",
  26. search='_search_base_balance_refund')
  27. def _search_balance_field(self, field, operator, value):
  28. operators = {'>', '<', '>=', '<=', '!=', '=', '<>'}
  29. fields = {
  30. 'balance', 'base_balance', 'balance_regular',
  31. 'base_balance_regular', 'balance_refund', 'base_balance_refund',
  32. }
  33. domain = []
  34. if operator in operators and field in fields:
  35. value = float(value) if value else 0
  36. taxes = self.search([]).filtered(
  37. lambda x: safe_eval(
  38. '%.2f %s %.2f' % (x[field], operator, value)))
  39. domain.append(('id', 'in', taxes.ids))
  40. return domain
  41. def _search_balance(self, operator, value):
  42. return self._search_balance_field('balance', operator, value)
  43. def _search_base_balance(self, operator, value):
  44. return self._search_balance_field('base_balance', operator, value)
  45. def _search_balance_regular(self, operator, value):
  46. return self._search_balance_field('balance_regular', operator, value)
  47. def _search_base_balance_regular(self, operator, value):
  48. return self._search_balance_field(
  49. 'base_balance_regular', operator, value)
  50. def _search_balance_refund(self, operator, value):
  51. return self._search_balance_field('balance_refund', operator, value)
  52. def _search_base_balance_refund(self, operator, value):
  53. return self._search_balance_field(
  54. 'base_balance_refund', operator, value)
  55. def get_context_values(self):
  56. context = self.env.context
  57. return (
  58. context.get('from_date', fields.Date.context_today(self)),
  59. context.get('to_date', fields.Date.context_today(self)),
  60. context.get('company_id', self.env.user.company_id.id),
  61. context.get('target_move', 'posted')
  62. )
  63. def _compute_balance(self):
  64. for tax in self:
  65. tax.balance_regular = tax.compute_balance(
  66. tax_or_base='tax', move_type='regular')
  67. tax.base_balance_regular = tax.compute_balance(
  68. tax_or_base='base', move_type='regular')
  69. tax.balance_refund = tax.compute_balance(
  70. tax_or_base='tax', move_type='refund')
  71. tax.base_balance_refund = tax.compute_balance(
  72. tax_or_base='base', move_type='refund')
  73. tax.balance = tax.balance_regular + tax.balance_refund
  74. tax.base_balance = (
  75. tax.base_balance_regular + tax.base_balance_refund)
  76. def get_target_type_list(self, move_type=None):
  77. if move_type == 'refund':
  78. return ['receivable_refund', 'payable_refund']
  79. elif move_type == 'regular':
  80. return ['receivable', 'payable']
  81. return []
  82. def get_target_state_list(self, target_move="posted"):
  83. if target_move == 'posted':
  84. state = ['posted']
  85. elif target_move == 'all':
  86. state = ['posted', 'draft']
  87. else:
  88. state = []
  89. return state
  90. def get_move_line_partial_domain(self, from_date, to_date, company_id):
  91. return [
  92. ('date', '<=', to_date),
  93. ('date', '>=', from_date),
  94. ('company_id', '=', company_id),
  95. ]
  96. def compute_balance(self, tax_or_base='tax', move_type=None):
  97. self.ensure_one()
  98. move_lines = self.get_move_lines_domain(
  99. tax_or_base=tax_or_base, move_type=move_type)
  100. # balance is debit - credit whereas on tax return you want to see what
  101. # vat has to be paid so:
  102. # VAT on sales (credit) - VAT on purchases (debit).
  103. total = -sum([l.balance for l in move_lines])
  104. return total
  105. def get_balance_domain(self, state_list, type_list):
  106. domain = [
  107. ('move_id.state', 'in', state_list),
  108. ('tax_line_id', '=', self.id),
  109. ]
  110. if type_list:
  111. domain.append(('move_id.move_type', 'in', type_list))
  112. return domain
  113. def get_base_balance_domain(self, state_list, type_list):
  114. domain = [
  115. ('move_id.state', 'in', state_list),
  116. ('tax_ids', 'in', self.id),
  117. ]
  118. if type_list:
  119. domain.append(('move_id.move_type', 'in', type_list))
  120. return domain
  121. def get_move_lines_domain(self, tax_or_base='tax', move_type=None):
  122. move_line_model = self.env['account.move.line']
  123. from_date, to_date, company_id, target_move = self.get_context_values()
  124. state_list = self.get_target_state_list(target_move)
  125. type_list = self.get_target_type_list(move_type)
  126. domain = self.get_move_line_partial_domain(
  127. from_date, to_date, company_id)
  128. balance_domain = []
  129. if tax_or_base == 'tax':
  130. balance_domain = self.get_balance_domain(state_list, type_list)
  131. elif tax_or_base == 'base':
  132. balance_domain = self.get_base_balance_domain(
  133. state_list, type_list)
  134. domain.extend(balance_domain)
  135. return move_line_model.search(domain)
  136. def get_lines_action(self, tax_or_base='tax', move_type=None):
  137. move_lines = self.get_move_lines_domain(
  138. tax_or_base=tax_or_base, move_type=move_type)
  139. move_line_ids = [l.id for l in move_lines]
  140. action = self.env.ref('account.action_account_moves_all_tree')
  141. vals = action.read()[0]
  142. vals['context'] = {}
  143. vals['domain'] = [('id', 'in', move_line_ids)]
  144. return vals
  145. @api.multi
  146. def view_tax_lines(self):
  147. self.ensure_one()
  148. return self.get_lines_action(tax_or_base='tax')
  149. @api.multi
  150. def view_base_lines(self):
  151. self.ensure_one()
  152. return self.get_lines_action(tax_or_base='base')
  153. @api.multi
  154. def view_tax_regular_lines(self):
  155. self.ensure_one()
  156. return self.get_lines_action(tax_or_base='tax', move_type='regular')
  157. @api.multi
  158. def view_base_regular_lines(self):
  159. self.ensure_one()
  160. return self.get_lines_action(tax_or_base='base', move_type='regular')
  161. @api.multi
  162. def view_tax_refund_lines(self):
  163. self.ensure_one()
  164. return self.get_lines_action(tax_or_base='tax', move_type='refund')
  165. @api.multi
  166. def view_base_refund_lines(self):
  167. self.ensure_one()
  168. return self.get_lines_action(tax_or_base='base', move_type='refund')