mirror of
https://github.com/bringout/oca-ocb-sale.git
synced 2026-04-28 02:31:59 +02:00
Initial commit: Sale packages
This commit is contained in:
commit
14e3d26998
6469 changed files with 2479670 additions and 0 deletions
|
|
@ -0,0 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import product
|
||||
from . import product_pricelist
|
||||
from . import sale_order
|
||||
from . import website
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
# defined for access rules
|
||||
class Product(models.Model):
|
||||
_inherit = 'product.product'
|
||||
|
||||
event_ticket_ids = fields.One2many('event.event.ticket', 'product_id', string='Event Tickets')
|
||||
|
||||
def _is_add_to_cart_allowed(self):
|
||||
# Allow adding event tickets to the cart regardless of product's rules
|
||||
self.ensure_one()
|
||||
res = super()._is_add_to_cart_allowed()
|
||||
return res or any(event.website_published for event in self.event_ticket_ids.event_id)
|
||||
|
||||
class ProductTemplate(models.Model):
|
||||
_inherit = 'product.template'
|
||||
|
||||
@api.model
|
||||
def _get_product_types_allow_zero_price(self):
|
||||
return super()._get_product_types_allow_zero_price() + ["event"]
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import _, api, models
|
||||
|
||||
class PricelistItem(models.Model):
|
||||
_inherit = "product.pricelist.item"
|
||||
|
||||
@api.onchange('applied_on', 'product_id', 'product_tmpl_id', 'min_quantity')
|
||||
def _onchange_event_sale_warning(self):
|
||||
if self.min_quantity > 0:
|
||||
msg = ''
|
||||
if self.applied_on == '3_global' or self.applied_on == '2_product_category':
|
||||
msg = _("A pricelist item with a positive min. quantity will not be applied to the event tickets products.")
|
||||
elif ((self.applied_on == '1_product' and self.product_tmpl_id.detailed_type == 'event') or
|
||||
(self.applied_on == '0_product_variant' and self.product_id.detailed_type == 'event')):
|
||||
msg = _("A pricelist item with a positive min. quantity cannot be applied to this event tickets product.")
|
||||
if msg:
|
||||
return {'warning':
|
||||
{
|
||||
'title': _("Warning"),
|
||||
'message': msg
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import api, models, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class SaleOrder(models.Model):
|
||||
_inherit = "sale.order"
|
||||
|
||||
def _cart_find_product_line(self, product_id=None, line_id=None, event_ticket_id=False, **kwargs):
|
||||
lines = super()._cart_find_product_line(product_id, line_id, **kwargs)
|
||||
if line_id or not event_ticket_id:
|
||||
return lines
|
||||
|
||||
return lines.filtered(
|
||||
lambda line: line.event_ticket_id.id == event_ticket_id
|
||||
)
|
||||
|
||||
def _verify_updated_quantity(self, order_line, product_id, new_qty, event_ticket_id=False, **kwargs):
|
||||
"""Restrict quantity updates for event tickets according to available seats."""
|
||||
new_qty, warning = super()._verify_updated_quantity(order_line, product_id, new_qty, **kwargs)
|
||||
|
||||
if not event_ticket_id:
|
||||
if not order_line.event_ticket_id or new_qty < order_line.product_uom_qty:
|
||||
return new_qty, warning
|
||||
else:
|
||||
return order_line.product_uom_qty, _("You cannot raise manually the event ticket quantity in your cart")
|
||||
|
||||
# Adding new ticket to the cart (might be automatically linked to an existing line)
|
||||
ticket = self.env['event.event.ticket'].browse(event_ticket_id).exists()
|
||||
if not ticket:
|
||||
raise UserError(_("The provided ticket doesn't exist"))
|
||||
|
||||
# TODO TDE consider full cart qty and not only added qty
|
||||
# if event seats are not auto confirmed.
|
||||
# Since created registrations are automatically reserved
|
||||
# We should only consider new added qty and not full quantity
|
||||
# when checking for seat availability
|
||||
existing_qty = order_line.product_uom_qty if order_line else 0
|
||||
qty_added = new_qty - existing_qty
|
||||
warning = ''
|
||||
if ticket.seats_limited and ticket.seats_available <= 0:
|
||||
# Remove existing line if exists and do not add a new one
|
||||
# if no ticket is available anymore
|
||||
new_qty = existing_qty
|
||||
warning = _(
|
||||
'Sorry, The %(ticket)s tickets for the %(event)s event are sold out.',
|
||||
ticket=ticket.name,
|
||||
event=ticket.event_id.name,
|
||||
)
|
||||
elif ticket.seats_limited and qty_added > ticket.seats_available:
|
||||
new_qty = existing_qty + ticket.seats_available
|
||||
warning = _(
|
||||
'Sorry, only %(remaining_seats)d seats are still available for the %(ticket)s ticket for the %(event)s event.',
|
||||
remaining_seats=ticket.seats_available,
|
||||
ticket=ticket.name,
|
||||
event=ticket.event_id.name,
|
||||
)
|
||||
|
||||
return new_qty, warning
|
||||
|
||||
def _prepare_order_line_values(self, product_id, quantity, event_ticket_id=False, **kwargs):
|
||||
"""Add corresponding event to the SOline creation values (if ticket is provided)."""
|
||||
values = super()._prepare_order_line_values(product_id, quantity, **kwargs)
|
||||
|
||||
if not event_ticket_id:
|
||||
return values
|
||||
|
||||
ticket = self.env['event.event.ticket'].browse(event_ticket_id)
|
||||
|
||||
if ticket.product_id.id != product_id:
|
||||
raise UserError(_("The ticket doesn't match with this product."))
|
||||
|
||||
values['event_id'] = ticket.event_id.id
|
||||
values['event_ticket_id'] = ticket.id
|
||||
|
||||
return values
|
||||
|
||||
def _update_cart_line_values(self, order_line, update_values):
|
||||
"""Remove event registrations on quantity decrease."""
|
||||
old_qty = order_line.product_uom_qty
|
||||
|
||||
super()._update_cart_line_values(order_line, update_values)
|
||||
if not order_line.event_ticket_id:
|
||||
return
|
||||
|
||||
new_qty = order_line.product_uom_qty
|
||||
if new_qty < old_qty:
|
||||
attendees = self.env['event.registration'].search([
|
||||
('state', '!=', 'cancel'),
|
||||
('sale_order_id', '=', self.id),
|
||||
('event_ticket_id', '=', order_line.event_ticket_id.id),
|
||||
], offset=new_qty, limit=(old_qty - new_qty), order='create_date asc')
|
||||
attendees.action_cancel()
|
||||
|
||||
def _filter_can_send_abandoned_cart_mail(self):
|
||||
"""Prevent carts with expired/sold out tickets from being subject of reminder emails."""
|
||||
return super()._filter_can_send_abandoned_cart_mail().filtered(
|
||||
lambda so: all(ticket.sale_available for ticket in so.order_line.event_ticket_id)
|
||||
)
|
||||
|
||||
|
||||
class SaleOrderLine(models.Model):
|
||||
_inherit = "sale.order.line"
|
||||
|
||||
@api.depends('product_id.display_name', 'event_ticket_id.display_name')
|
||||
def _compute_name_short(self):
|
||||
""" If the sale order line concerns a ticket, we don't want the product name, but the ticket name instead.
|
||||
"""
|
||||
super(SaleOrderLine, self)._compute_name_short()
|
||||
|
||||
for record in self:
|
||||
if record.event_ticket_id:
|
||||
record.name_short = record.event_ticket_id.display_name
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class Website(models.Model):
|
||||
_inherit = 'website'
|
||||
|
||||
def sale_product_domain(self):
|
||||
# remove product event from the website content grid and list view (not removed in detail view)
|
||||
return ['&'] + super(Website, self).sale_product_domain() + [('detailed_type', '!=', 'event')]
|
||||
Loading…
Add table
Add a link
Reference in a new issue