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.

171 lines
6.3 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. 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. @api.multi
  63. def onchange_product_id(self, pricelist, product_id, qty=0,
  64. partner_id=False):
  65. result = super(PosOrderLine, self).onchange_product_id(
  66. pricelist=pricelist, product_id=product_id, qty=qty,
  67. partner_id=partner_id)
  68. if product_id:
  69. product = self.env['product.product'].browse(product_id)
  70. result['value']['tax_ids'] = product.product_tmpl_id.taxes_id
  71. return result
  72. class PosOrder(models.Model):
  73. _inherit = "pos.order"
  74. taxes = fields.One2many(comodel_name='pos.order.tax',
  75. inverse_name='pos_order', readonly=True)
  76. @api.model
  77. def _amount_line_tax(self, line):
  78. price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
  79. taxes = line.tax_ids.compute_all(
  80. price, line.qty, product=line.product_id,
  81. partner=line.order_id.partner_id)['taxes']
  82. val = 0.0
  83. for c in taxes:
  84. val += c.get('amount', 0.0)
  85. return val
  86. @api.multi
  87. def _tax_list_get(self):
  88. agg_taxes = {}
  89. tax_lines = []
  90. for order in self:
  91. for line in order.lines:
  92. tax_lines.append({
  93. 'base': line.price_subtotal,
  94. 'taxes': line._compute_taxes()['taxes']
  95. })
  96. for tax_line in tax_lines:
  97. base = tax_line['base']
  98. for tax in tax_line['taxes']:
  99. tax_id = str(tax['id'])
  100. if tax_id in agg_taxes:
  101. agg_taxes[tax_id]['base'] += base
  102. agg_taxes[tax_id]['amount'] += tax['amount']
  103. else:
  104. agg_taxes[tax_id] = {
  105. 'tax_id': tax_id,
  106. 'name': tax['name'],
  107. 'base': base,
  108. 'amount': tax['amount'],
  109. }
  110. return agg_taxes
  111. @api.multi
  112. def compute_tax_detail(self):
  113. taxes_to_delete = False
  114. for order in self:
  115. taxes_to_delete = self.env['pos.order.tax'].search(
  116. [('pos_order', '=', order.id)])
  117. # Update order taxes list
  118. for key, tax in order._tax_list_get().iteritems():
  119. current = taxes_to_delete.filtered(
  120. lambda r: r.tax.id == tax['tax_id'])
  121. if current:
  122. current.write({
  123. 'base': tax['base'],
  124. 'amount': tax['amount'],
  125. })
  126. taxes_to_delete -= current
  127. else:
  128. self.env['pos.order.tax'].create({
  129. 'pos_order': order.id,
  130. 'tax': tax['tax_id'],
  131. 'name': tax['name'],
  132. 'base': tax['base'],
  133. 'amount': tax['amount'],
  134. })
  135. if taxes_to_delete:
  136. taxes_to_delete.unlink()
  137. @api.multi
  138. def action_paid(self):
  139. result = super(PosOrder, self).action_paid()
  140. self.compute_tax_detail()
  141. return result
  142. @api.model
  143. def _install_tax_detail(self):
  144. """Create tax details to pos.order's already paid, done or invoiced.
  145. """
  146. # Find orders with state : paid, done or invoiced
  147. orders = self.search([('state', 'in', ('paid', 'done', 'invoiced')),
  148. ('taxes', '=', False)])
  149. # Compute tax detail
  150. orders.compute_tax_detail()
  151. _logger.info("%d orders computed installing module.", len(orders))