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.

160 lines
5.8 KiB

9 years ago
9 years ago
  1. # -*- coding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # Copyright (C) 2015 Aserti Global Solutions (http://www.aserti.es/).
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU Affero General Public License as published
  8. # by the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU Affero General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU Affero General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. #
  19. ##############################################################################
  20. from openerp import models, fields, api
  21. from openerp.addons import decimal_precision as dp
  22. import logging
  23. _logger = logging.getLogger(__name__)
  24. class PosOrderTax(models.Model):
  25. _name = 'pos.order.tax'
  26. pos_order = fields.Many2one('pos.order', string='POS Order',
  27. ondelete='cascade', index=True)
  28. tax = fields.Many2one('account.tax', string='Tax')
  29. name = fields.Char(string='Tax Description', required=True)
  30. base = fields.Float(string='Base', digits=dp.get_precision('Account'))
  31. amount = fields.Float(string='Amount', digits=dp.get_precision('Account'))
  32. class PosOrderLine(models.Model):
  33. _inherit = "pos.order.line"
  34. @api.multi
  35. def _compute_taxes(self):
  36. res = {
  37. 'total': 0,
  38. 'total_included': 0,
  39. 'taxes': [],
  40. }
  41. for line in self:
  42. price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
  43. taxes = line.tax_ids.compute_all(
  44. price, line.qty, product=line.product_id,
  45. partner=line.order_id.partner_id)
  46. res['total'] += taxes['total']
  47. res['total_included'] += taxes['total_included']
  48. res['taxes'] += taxes['taxes']
  49. return res
  50. @api.one
  51. @api.depends('tax_ids', 'qty', 'price_unit',
  52. 'product_id', 'discount', 'order_id.partner_id')
  53. def _amount_line_all(self):
  54. taxes = self._compute_taxes()
  55. self.price_subtotal = taxes['total']
  56. self.price_subtotal_incl = taxes['total_included']
  57. tax_ids = fields.Many2many(
  58. 'account.tax', 'pline_tax_rel', 'pos_line_id', 'tax_id',
  59. "Taxes", domain=[('type_tax_use', '=', 'sale')])
  60. price_subtotal = fields.Float(compute="_amount_line_all", store=True)
  61. price_subtotal_incl = fields.Float(compute="_amount_line_all", store=True)
  62. class PosOrder(models.Model):
  63. _inherit = "pos.order"
  64. taxes = fields.One2many(comodel_name='pos.order.tax',
  65. inverse_name='pos_order', readonly=True)
  66. @api.model
  67. def _amount_line_tax(self, line):
  68. price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
  69. taxes = line.tax_ids.compute_all(
  70. price, line.qty, product=line.product_id,
  71. partner=line.order_id.partner_id)['taxes']
  72. val = 0.0
  73. for c in taxes:
  74. val += c.get('amount', 0.0)
  75. return val
  76. @api.multi
  77. def _tax_list_get(self):
  78. agg_taxes = {}
  79. tax_lines = []
  80. for order in self:
  81. for line in order.lines:
  82. tax_lines.append({
  83. 'base': line.price_subtotal,
  84. 'taxes': line._compute_taxes()['taxes']
  85. })
  86. for tax_line in tax_lines:
  87. base = tax_line['base']
  88. for tax in tax_line['taxes']:
  89. tax_id = str(tax['id'])
  90. if tax_id in agg_taxes:
  91. agg_taxes[tax_id]['base'] += base
  92. agg_taxes[tax_id]['amount'] += tax['amount']
  93. else:
  94. agg_taxes[tax_id] = {
  95. 'tax_id': tax_id,
  96. 'name': tax['name'],
  97. 'base': base,
  98. 'amount': tax['amount'],
  99. }
  100. return agg_taxes
  101. @api.multi
  102. def compute_tax_detail(self):
  103. taxes_to_delete = False
  104. for order in self:
  105. taxes_to_delete = self.env['pos.order.tax'].search(
  106. [('pos_order', '=', order.id)])
  107. # Update order taxes list
  108. for key, tax in order._tax_list_get().iteritems():
  109. current = taxes_to_delete.filtered(
  110. lambda r: r.tax.id == tax['tax_id'])
  111. if current:
  112. current.write({
  113. 'base': tax['base'],
  114. 'amount': tax['amount'],
  115. })
  116. taxes_to_delete -= current
  117. else:
  118. self.env['pos.order.tax'].create({
  119. 'pos_order': order.id,
  120. 'tax': tax['tax_id'],
  121. 'name': tax['name'],
  122. 'base': tax['base'],
  123. 'amount': tax['amount'],
  124. })
  125. if taxes_to_delete:
  126. taxes_to_delete.unlink()
  127. @api.multi
  128. def action_paid(self):
  129. result = super(PosOrder, self).action_paid()
  130. self.compute_tax_detail()
  131. return result
  132. @api.model
  133. def _install_tax_detail(self):
  134. """Create tax details to pos.order's already paid, done or invoiced.
  135. """
  136. # Find orders with state : paid, done or invoiced
  137. orders = self.search([('state', 'in', ('paid', 'done', 'invoiced')),
  138. ('taxes', '=', False)])
  139. # Compute tax detail
  140. orders.compute_tax_detail()
  141. _logger.info("%d orders computed installing module.", len(orders))