pricelist.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. # coding: utf-8
  2. # © 2015 David BEAL @ Akretion
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. from openerp import _, api, fields, models
  5. PRICE_GRID_HELP = _("""Define if the price list items are filled
  6. from product form with a grid of specific values
  7. for each product""")
  8. class ProductPricelist(models.Model):
  9. _inherit = 'product.pricelist'
  10. price_grid = fields.Boolean(
  11. string='Product Price Grid',
  12. help=PRICE_GRID_HELP)
  13. class ProductPricelistVersion(models.Model):
  14. _inherit = 'product.pricelist.version'
  15. @api.depends('tmpl_in_count')
  16. def _compute_count_products(self):
  17. PPItem_m = self.env['product.pricelist.item']
  18. for record in self:
  19. if not isinstance(self.id, models.NewId):
  20. predicats = {
  21. 'tmpl_in_count': ('product_tmpl_id', '!=', False),
  22. }
  23. version_domain = [('price_version_id', '=', record.id)]
  24. for field, predicat in predicats.items():
  25. domain = list(version_domain)
  26. domain.append(predicat)
  27. self[field] = PPItem_m.search_count(domain)
  28. price_grid = fields.Boolean(
  29. related='pricelist_id.price_grid',
  30. domain=[('price_surcharge', '=', 0)],
  31. store=True,
  32. help=PRICE_GRID_HELP)
  33. tmpl_in_count = fields.Integer(
  34. string="Template with this Version",
  35. compute='_compute_count_products',
  36. help="Number of Product Template with this Pricelist version")
  37. item_grid_ids = fields.One2many(
  38. 'product.pricelist.item',
  39. 'price_version_id')
  40. @api.multi
  41. def button_template_in_version(self):
  42. self.ensure_one()
  43. domain = [('pricelist_item_ids.price_version_id', '=', self.id)]
  44. return {
  45. 'type': 'ir.actions.act_window',
  46. 'target': 'current',
  47. 'domain': domain,
  48. 'view_mode': 'tree,form',
  49. 'res_model': 'product.template',
  50. }
  51. class ProductPricelistItem(models.Model):
  52. _inherit = 'product.pricelist.item'
  53. date_end = fields.Date(
  54. related='price_version_id.date_end',
  55. readonly=True)
  56. currency_name = fields.Many2one(
  57. related='price_version_id.pricelist_id.currency_id',
  58. readonly=True)
  59. related_sequence = fields.Integer(
  60. String='Sequence',
  61. related="sequence",
  62. help="Allows to modify the sequence manually because "
  63. "the sequence field is difficult to modify because 'handle'.")
  64. @api.multi
  65. def button_product(self):
  66. self.ensure_one()
  67. if self.product_tmpl_id:
  68. product = self.product_tmpl_id
  69. else:
  70. product = self.product_id.product_tmpl_id
  71. return {
  72. 'type': 'ir.actions.act_window',
  73. 'target': 'current',
  74. 'name': 'Product',
  75. 'view_mode': 'form',
  76. 'res_id': product.id,
  77. 'res_model': 'product.template',
  78. }
  79. @api.model
  80. def _get_sequence_price_grid(self, vals):
  81. """
  82. In sale order line, we want to use as a priority
  83. the product pricelist item associated with the product variant.
  84. But in Odoo, it's the product pricelist item which has the
  85. smallest sequence that is used.
  86. That's why, we put a smaller sequence to the product pricelist item
  87. of the product variant and a larger sequence to
  88. the product pricelist item of the product template.
  89. """
  90. product_id = vals.get('product_id', self.product_id)
  91. product_tmpl_id = vals.get('product_tmpl_id', self.product_tmpl_id)
  92. related_sequence = 15
  93. if product_id:
  94. related_sequence = 5
  95. elif product_tmpl_id:
  96. related_sequence = 10
  97. return related_sequence
  98. @api.model
  99. def create(self, vals):
  100. if not self._is_catch_all_item(vals) and \
  101. self.env['product.pricelist.version'].browse(
  102. vals['price_version_id']).price_grid:
  103. vals.update({
  104. 'price_discount': -1,
  105. 'related_sequence': self._get_sequence_price_grid(vals),
  106. 'base': vals.get('base', 1),
  107. })
  108. return super(ProductPricelistItem, self).create(vals)
  109. @api.multi
  110. def write(self, vals):
  111. for item in self:
  112. if not self._is_catch_all_item(vals) and 'product_id' in vals:
  113. vals['related_sequence'] = item._get_sequence_price_grid(
  114. vals)
  115. super(ProductPricelistItem, item).write(vals)
  116. return True
  117. @api.model
  118. def _is_catch_all_item(self, vals):
  119. """ Sale Pricelists require a pricelist item in order to work.
  120. This item must be based on public price without discount/surcharge
  121. If not, public price from product is not propagated in sale line
  122. and price is 0.0
  123. Here we don't want block this behavior.
  124. """
  125. values = vals.copy()
  126. conditions = {
  127. 'min_quantity': 0,
  128. 'price_surcharge': 0,
  129. 'price_discount': 0,
  130. 'categ_id': False,
  131. 'product_id': False,
  132. 'product_tmpl_id': False,
  133. }
  134. # We complete missing keys in values dict
  135. # (write could have less keys than create)
  136. for key in conditions.keys():
  137. if key not in values:
  138. values[key] = self[key] or False # value in db
  139. # we check 1 condition which prevent to be a catchall
  140. for key, elm in conditions.items():
  141. if key in values and values.get(key) != elm:
  142. return False
  143. return True