product.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. # -*- encoding: utf-8 -*-
  2. ##############################################################################
  3. # For copyright and license notices, see __openerp__.py file in root directory
  4. ##############################################################################
  5. from openerp import fields, models, api, _
  6. from openerp.osv import fields as old_fields
  7. from openerp.exceptions import Warning
  8. import math
  9. class product_product(models.Model):
  10. _inherit = 'product.product'
  11. pack_line_ids = fields.One2many(
  12. 'product.pack.line',
  13. 'parent_product_id',
  14. 'Pack Products',
  15. help='List of products that are part of this pack.'
  16. )
  17. used_pack_line_ids = fields.One2many(
  18. 'product.pack.line',
  19. 'product_id',
  20. 'On Packs',
  21. help='List of packs where product is used.'
  22. )
  23. # def _product_available(
  24. # self, cr, uid, ids, field_names=None, arg=False, context=None):
  25. # """
  26. # For product packs we get availability in a different way
  27. # """
  28. # pack_product_ids = self.search(cr, uid, [
  29. # ('pack', '=', True),
  30. # ('id', 'in', ids),
  31. # ])
  32. # res = super(product_product, self)._product_available(
  33. # cr, uid, list(set(ids) - set(pack_product_ids)),
  34. # field_names, arg, context)
  35. # for product in self.browse(cr, uid, pack_product_ids, context=context):
  36. # pack_qty_available = []
  37. # pack_virtual_available = []
  38. # for subproduct in product.pack_line_ids:
  39. # subproduct_stock = self._product_available(
  40. # cr, uid, [subproduct.product_id.id], field_names, arg,
  41. # context)[subproduct.product_id.id]
  42. # sub_qty = subproduct.quantity
  43. # if sub_qty:
  44. # pack_qty_available.append(math.floor(
  45. # subproduct_stock['qty_available'] / sub_qty))
  46. # pack_virtual_available.append(math.floor(
  47. # subproduct_stock['virtual_available'] / sub_qty))
  48. # # TODO calcular correctamente pack virtual available para negativos
  49. # res[product.id] = {
  50. # 'qty_available': (
  51. # pack_qty_available and min(pack_qty_available) or False),
  52. # 'incoming_qty': 0,
  53. # 'outgoing_qty': 0,
  54. # 'virtual_available': (
  55. # pack_virtual_available and
  56. # max(min(pack_virtual_available), 0) or False),
  57. # }
  58. # return res
  59. # def _search_product_quantity(self, cr, uid, obj, name, domain, context):
  60. # """
  61. # We use original search function
  62. # """
  63. # return super(product_product, self)._search_product_quantity(
  64. # cr, uid, obj, name, domain, context)
  65. # # overwrite ot this fields so that we can modify _product_available
  66. # # function to support packs
  67. # _columns = {
  68. # 'qty_available': old_fields.function(
  69. # _product_available, multi='qty_available',
  70. # fnct_search=_search_product_quantity),
  71. # 'virtual_available': old_fields.function(
  72. # _product_available, multi='qty_available',
  73. # fnct_search=_search_product_quantity),
  74. # 'incoming_qty': old_fields.function(
  75. # _product_available, multi='qty_available',
  76. # fnct_search=_search_product_quantity),
  77. # 'outgoing_qty': old_fields.function(
  78. # _product_available, multi='qty_available',
  79. # fnct_search=_search_product_quantity),
  80. # }
  81. @api.one
  82. @api.constrains('pack_line_ids')
  83. def check_recursion(self):
  84. """
  85. Check recursion on packs
  86. """
  87. pack_lines = self.pack_line_ids
  88. while pack_lines:
  89. if self in pack_lines.mapped('product_id'):
  90. raise Warning(_(
  91. 'Error! You cannot create recursive packs.\n'
  92. 'Product id: %s') % self.id)
  93. pack_lines = pack_lines.mapped('product_id.pack_line_ids')
  94. class product_template(models.Model):
  95. _inherit = 'product.template'
  96. # TODO rename a pack_type
  97. pack_price_type = fields.Selection([
  98. ('components_price', 'Detallado - Precios de los componentes'),
  99. ('totalice_price', 'Detallado - Precio total'),
  100. ('fixed_price', 'Detallado - Precio fijo'),
  101. ('none_detailed_assited_price', 'No detallado - Precio Asistido'),
  102. ('none_detailed_totaliced_price', 'No detallado - Precio total'),
  103. ],
  104. 'Pack Type',
  105. help="* Detailed - Components Prices: Detail lines with prices on "
  106. "sales order.\n"
  107. "* Detailed - Totaliced Price: Detail lines on sales order totalicing "
  108. "lines prices on pack (don't show component prices).\n"
  109. "* Detailed - Fixed Price: Detail lines on sales order and use product"
  110. " pack price (ignore line prices).\n"
  111. "* None Detailed - Assisted Price: Do not detail lines on sales "
  112. "order. Assist to get pack price using pack lines.",
  113. default='fixed_price'
  114. )
  115. pack = fields.Boolean(
  116. 'Pack?',
  117. help='Is a Product Pack?',
  118. )
  119. pack_line_ids = fields.One2many(
  120. related='product_variant_ids.pack_line_ids'
  121. )
  122. used_pack_line_ids = fields.One2many(
  123. related='product_variant_ids.used_pack_line_ids'
  124. )
  125. @api.constrains(
  126. 'product_variant_ids', 'pack_price_type')
  127. def check_relations(self):
  128. """
  129. Check assited packs dont have packs a childs
  130. """
  131. # check assited price has no packs child of them
  132. if self.pack_price_type == 'none_detailed_assited_price':
  133. child_packs = self.mapped(
  134. 'pack_line_ids.product_id').filtered('pack')
  135. if child_packs:
  136. raise Warning(_(
  137. 'A "None Detailed - Assisted Price Pack" can not have a '
  138. 'pack as a child!'))
  139. # TODO we also should check this
  140. # check if we are configuring a pack for a product that is partof a
  141. # assited pack
  142. # if self.pack:
  143. # for product in self.product_variant_ids
  144. # parent_assited_packs = self.env['product.pack.line'].search([
  145. # ('product_id', '=', self.id),
  146. # ('parent_product_id.pack_price_type', '=',
  147. # 'none_detailed_assited_price'),
  148. # ])
  149. # print 'parent_assited_packs', parent_assited_packs
  150. # if parent_assited_packs:
  151. # raise Warning(_(
  152. # 'You can not set this product as pack because it is part'
  153. # ' of a "None Detailed - Assisted Price Pack"'))
  154. @api.one
  155. @api.constrains('company_id', 'product_variant_ids', 'used_pack_line_ids')
  156. def check_pack_line_company(self):
  157. """
  158. Check packs are related to packs of same company
  159. """
  160. for line in self.pack_line_ids:
  161. if line.product_id.company_id != self.company_id:
  162. raise Warning(_(
  163. 'Pack lines products company must be the same as the\
  164. parent product company'))
  165. for line in self.used_pack_line_ids:
  166. if line.parent_product_id.company_id != self.company_id:
  167. raise Warning(_(
  168. 'Pack lines products company must be the same as the\
  169. parent product company'))
  170. @api.multi
  171. def write(self, vals):
  172. """
  173. We remove from prod.prod to avoid error
  174. """
  175. if vals.get('pack_line_ids', False):
  176. self.product_variant_ids.write(
  177. {'pack_line_ids': vals.pop('pack_line_ids')})
  178. return super(product_template, self).write(vals)
  179. @api.model
  180. def _price_get(self, products, ptype='list_price'):
  181. res = super(product_template, self)._price_get(
  182. products, ptype=ptype)
  183. for product in products:
  184. if (
  185. product.pack and
  186. product.pack_price_type in [
  187. 'totalice_price',
  188. 'none_detailed_assited_price',
  189. 'none_detailed_totaliced_price']):
  190. pack_price = 0.0
  191. for pack_line in product.pack_line_ids:
  192. product_line_price = pack_line.product_id.price_get()[
  193. pack_line.product_id.id] * (
  194. 1 - (pack_line.discount or 0.0) / 100.0)
  195. product_line_price
  196. pack_price += (product_line_price * pack_line.quantity)
  197. res[product.id] = pack_price
  198. return res