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.

168 lines
6.2 KiB

10 years ago
10 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. from openerp.addons.point_of_sale.point_of_sale import pos_order as base_order
  23. from openerp.addons.pos_pricelist.models.pos_order_patch import (
  24. _create_account_move_line)
  25. import logging
  26. _logger = logging.getLogger(__name__)
  27. class PosOrderTax(models.Model):
  28. _name = 'pos.order.tax'
  29. pos_order = fields.Many2one('pos.order', string='POS Order',
  30. ondelete='cascade', index=True)
  31. tax = fields.Many2one('account.tax', string='Tax')
  32. name = fields.Char(string='Tax Description', required=True)
  33. base = fields.Float(string='Base', digits=dp.get_precision('Account'))
  34. amount = fields.Float(string='Amount', digits=dp.get_precision('Account'))
  35. class PosOrderLine(models.Model):
  36. _inherit = "pos.order.line"
  37. @api.multi
  38. def _compute_taxes(self):
  39. res = {
  40. 'total': 0,
  41. 'total_included': 0,
  42. 'taxes': [],
  43. }
  44. for line in self:
  45. price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
  46. taxes = line.tax_ids.compute_all(
  47. price, line.qty, product=line.product_id,
  48. partner=line.order_id.partner_id)
  49. res['total'] += taxes['total']
  50. res['total_included'] += taxes['total_included']
  51. res['taxes'] += taxes['taxes']
  52. return res
  53. @api.one
  54. @api.depends('tax_ids', 'qty', 'price_unit',
  55. 'product_id', 'discount', 'order_id.partner_id')
  56. def _amount_line_all(self):
  57. taxes = self._compute_taxes()
  58. self.price_subtotal = taxes['total']
  59. self.price_subtotal_incl = taxes['total_included']
  60. tax_ids = fields.Many2many(
  61. 'account.tax', 'pline_tax_rel', 'pos_line_id', 'tax_id',
  62. "Taxes", domain=[('type_tax_use', 'in', ['sale', 'all'])])
  63. price_subtotal = fields.Float(compute="_amount_line_all", store=True)
  64. price_subtotal_incl = fields.Float(compute="_amount_line_all", store=True)
  65. class PosOrder(models.Model):
  66. _inherit = "pos.order"
  67. taxes = fields.One2many(comodel_name='pos.order.tax',
  68. inverse_name='pos_order', readonly=True)
  69. @api.model
  70. def _amount_line_tax(self, line):
  71. price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
  72. taxes = line.tax_ids.compute_all(
  73. price, line.qty, product=line.product_id,
  74. partner=line.order_id.partner_id)['taxes']
  75. val = 0.0
  76. for c in taxes:
  77. val += c.get('amount', 0.0)
  78. return val
  79. @api.multi
  80. def _tax_list_get(self):
  81. agg_taxes = {}
  82. tax_lines = []
  83. for order in self:
  84. for line in order.lines:
  85. tax_lines.append({
  86. 'base': line.price_subtotal,
  87. 'taxes': line._compute_taxes()['taxes']
  88. })
  89. for tax_line in tax_lines:
  90. base = tax_line['base']
  91. for tax in tax_line['taxes']:
  92. tax_id = str(tax['id'])
  93. if tax_id in agg_taxes:
  94. agg_taxes[tax_id]['base'] += base
  95. agg_taxes[tax_id]['amount'] += tax['amount']
  96. else:
  97. agg_taxes[tax_id] = {
  98. 'tax_id': tax_id,
  99. 'name': tax['name'],
  100. 'base': base,
  101. 'amount': tax['amount'],
  102. }
  103. return agg_taxes
  104. @api.multi
  105. def compute_tax_detail(self):
  106. taxes_to_delete = False
  107. for order in self:
  108. taxes_to_delete = self.env['pos.order.tax'].search(
  109. [('pos_order', '=', order.id)])
  110. # Update order taxes list
  111. for key, tax in order._tax_list_get().iteritems():
  112. current = taxes_to_delete.filtered(
  113. lambda r: r.tax.id == tax['tax_id'])
  114. if current:
  115. current.write({
  116. 'base': tax['base'],
  117. 'amount': tax['amount'],
  118. })
  119. taxes_to_delete -= current
  120. else:
  121. self.env['pos.order.tax'].create({
  122. 'pos_order': order.id,
  123. 'tax': tax['tax_id'],
  124. 'name': tax['name'],
  125. 'base': tax['base'],
  126. 'amount': tax['amount'],
  127. })
  128. if taxes_to_delete:
  129. taxes_to_delete.unlink()
  130. @api.multi
  131. def action_paid(self):
  132. result = super(PosOrder, self).action_paid()
  133. self.compute_tax_detail()
  134. return result
  135. @api.model
  136. def _install_tax_detail(self):
  137. """Create tax details to pos.order's already paid, done or invoiced.
  138. """
  139. # Find orders with state : paid, done or invoiced
  140. orders = self.search([('state', 'in', ('paid', 'done', 'invoiced')),
  141. ('taxes', '=', False)])
  142. # Compute tax detail
  143. orders.compute_tax_detail()
  144. _logger.info("%d orders computed installing module.", len(orders))
  145. def _register_hook(self, cr):
  146. res = super(PosOrder, self)._register_hook(cr)
  147. base_order._create_account_move_line = _create_account_move_line
  148. return res