event_ticket.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. import logging
  4. from odoo import api, fields, models
  5. _logger = logging.getLogger(__name__)
  6. class EventTemplateTicket(models.Model):
  7. _inherit = 'event.type.ticket'
  8. def _default_product_id(self):
  9. return self.env.ref('event_sale.product_product_event', raise_if_not_found=False)
  10. description = fields.Text(compute='_compute_description', readonly=False, store=True)
  11. # product
  12. product_id = fields.Many2one(
  13. 'product.product', string='Product', required=True,
  14. domain=[("detailed_type", "=", "event")], default=_default_product_id)
  15. price = fields.Float(
  16. string='Price', compute='_compute_price',
  17. digits='Product Price', readonly=False, store=True)
  18. price_reduce = fields.Float(
  19. string="Price Reduce", compute="_compute_price_reduce",
  20. compute_sudo=True, digits='Product Price')
  21. @api.depends('product_id')
  22. def _compute_price(self):
  23. for ticket in self:
  24. if ticket.product_id and ticket.product_id.lst_price:
  25. ticket.price = ticket.product_id.lst_price or 0
  26. elif not ticket.price:
  27. ticket.price = 0
  28. @api.depends('product_id')
  29. def _compute_description(self):
  30. for ticket in self:
  31. if ticket.product_id and ticket.product_id.description_sale:
  32. ticket.description = ticket.product_id.description_sale
  33. # initialize, i.e for embedded tree views
  34. if not ticket.description:
  35. ticket.description = False
  36. # TODO clean this feature in master
  37. # Feature broken by design, depending on the hacky `_get_contextual_price` field on products
  38. # context_dependent, core part of the pricelist mess
  39. # This field usage should be restricted to the UX, and any use in effective
  40. # price computation should be replaced by clear calls to the pricelist API
  41. @api.depends_context('uom', 'qty', 'pricelist') # Cf product.price context dependencies
  42. @api.depends('product_id', 'price')
  43. def _compute_price_reduce(self):
  44. for ticket in self:
  45. product = ticket.product_id
  46. pricelist = product.product_tmpl_id._get_contextual_pricelist()
  47. lst_price = product.currency_id._convert(
  48. product.lst_price,
  49. pricelist.currency_id,
  50. self.env.company,
  51. fields.Datetime.now()
  52. )
  53. discount = (lst_price - product._get_contextual_price()) / lst_price if lst_price else 0.0
  54. ticket.price_reduce = (1.0 - discount) * ticket.price
  55. def _init_column(self, column_name):
  56. if column_name != "product_id":
  57. return super(EventTemplateTicket, self)._init_column(column_name)
  58. # fetch void columns
  59. self.env.cr.execute("SELECT id FROM %s WHERE product_id IS NULL" % self._table)
  60. ticket_type_ids = self.env.cr.fetchall()
  61. if not ticket_type_ids:
  62. return
  63. # update existing columns
  64. _logger.debug("Table '%s': setting default value of new column %s to unique values for each row",
  65. self._table, column_name)
  66. default_event_product = self.env.ref('event_sale.product_product_event', raise_if_not_found=False)
  67. if default_event_product:
  68. product_id = default_event_product.id
  69. else:
  70. product_id = self.env['product.product'].create({
  71. 'name': 'Generic Registration Product',
  72. 'list_price': 0,
  73. 'standard_price': 0,
  74. 'type': 'service',
  75. }).id
  76. self.env['ir.model.data'].create({
  77. 'name': 'product_product_event',
  78. 'module': 'event_sale',
  79. 'model': 'product.product',
  80. 'res_id': product_id,
  81. })
  82. self.env.cr._obj.execute(
  83. f'UPDATE {self._table} SET product_id = %s WHERE id IN %s;',
  84. (product_id, tuple(ticket_type_ids))
  85. )
  86. @api.model
  87. def _get_event_ticket_fields_whitelist(self):
  88. """ Add sale specific fields to copy from template to ticket """
  89. return super(EventTemplateTicket, self)._get_event_ticket_fields_whitelist() + ['product_id', 'price']
  90. class EventTicket(models.Model):
  91. _inherit = 'event.event.ticket'
  92. _order = "event_id, price"
  93. # product
  94. price_reduce_taxinc = fields.Float(
  95. string='Price Reduce Tax inc', compute='_compute_price_reduce_taxinc',
  96. compute_sudo=True)
  97. def _compute_price_reduce_taxinc(self):
  98. for event in self:
  99. # sudo necessary here since the field is most probably accessed through the website
  100. tax_ids = event.product_id.taxes_id.filtered(lambda r: r.company_id == event.event_id.company_id)
  101. taxes = tax_ids.compute_all(event.price_reduce, event.event_id.company_id.currency_id, 1.0, product=event.product_id)
  102. event.price_reduce_taxinc = taxes['total_included']
  103. @api.depends('product_id.active')
  104. def _compute_sale_available(self):
  105. inactive_product_tickets = self.filtered(lambda ticket: not ticket.product_id.active)
  106. for ticket in inactive_product_tickets:
  107. ticket.sale_available = False
  108. super(EventTicket, self - inactive_product_tickets)._compute_sale_available()
  109. def _get_ticket_multiline_description(self):
  110. """ If people set a description on their product it has more priority
  111. than the ticket name itself for the SO description. """
  112. self.ensure_one()
  113. if self.product_id.description_sale:
  114. return '%s\n%s' % (self.product_id.description_sale, self.event_id.display_name)
  115. return super(EventTicket, self)._get_ticket_multiline_description()