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.

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