[IMP] event: clean code about synchronizing partner / sale order line
PURPOSE
This commit is part of ticket model support directly in event application.
SPECIFICATIONS
In this commit we make a quixotic attempt to clean call chain implied by
making registrations online, either in event frontend (website_event) or
with eCommerce inclusion (website_event_sale). Purpose is to get rid of some
preparation and data management methods to handle most of the code directly
at CRUD level whenever it makes sense.
We notably
* move at create and write level support of partner_id update: updating
its name / email / phone / mobile;
* move at create and write level support of sale_order-id update: updating
event, ticket, partner;
Using that and some code cleaning some methods are removed and call chain
is a bit reduced.
LINKS
Task ID 2177281
Community PR #43488
This commit is contained in:
@@ -49,52 +49,53 @@ class EventRegistration(models.Model):
|
||||
if registration.event_id.seats_availability == 'limited' and registration.event_id.seats_max and registration.event_id.seats_available < (1 if registration.state == 'draft' else 0):
|
||||
raise ValidationError(_('No more seats available for this event.'))
|
||||
|
||||
def _check_auto_confirmation(self):
|
||||
if self._context.get('registration_force_draft'):
|
||||
return False
|
||||
if any(not registration.event_id.auto_confirm or
|
||||
(not registration.event_id.seats_available and registration.event_id.seats_availability == 'limited') for registration in self):
|
||||
return False
|
||||
return True
|
||||
@api.onchange('partner_id')
|
||||
def _onchange_partner(self):
|
||||
if self.partner_id:
|
||||
self.update(self._synchronize_partner_values(self.partner_id))
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# CRUD
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
# update missing pieces of information from partner
|
||||
if vals.get('partner_id'):
|
||||
partner_vals = self._synchronize_partner_values(
|
||||
self.env['res.partner'].browse(vals['partner_id'])
|
||||
)
|
||||
vals = dict(partner_vals, **vals)
|
||||
|
||||
registration = super(EventRegistration, self).create(vals)
|
||||
if registration._check_auto_confirmation():
|
||||
registration.sudo().action_confirm()
|
||||
|
||||
return registration
|
||||
|
||||
def write(self, vals):
|
||||
if vals.get('state') == 'done' and 'date_closed' not in vals:
|
||||
vals['date_closed'] = fields.Datetime.now()
|
||||
|
||||
ret = super(EventRegistration, self).write(vals)
|
||||
|
||||
# update missing pieces of information from partner
|
||||
if vals.get('partner_id'):
|
||||
partner_vals = self._synchronize_partner_values(
|
||||
self.env['res.partner'].browse(vals['partner_id'])
|
||||
)
|
||||
for registration in self:
|
||||
partner_info = dict((key, val) for key, val in partner_vals.items() if not registration[key])
|
||||
if partner_info:
|
||||
registration.write(partner_info)
|
||||
|
||||
if vals.get('state') == 'open':
|
||||
# auto-trigger after_sub (on subscribe) mail schedulers, if needed
|
||||
onsubscribe_schedulers = self.mapped('event_id.event_mail_ids').filtered(lambda s: s.interval_type == 'after_sub')
|
||||
onsubscribe_schedulers.execute()
|
||||
elif vals.get('state') == 'done' and 'date_closed' not in vals:
|
||||
vals['date_closed'] = fields.Datetime.now()
|
||||
|
||||
return ret
|
||||
|
||||
@api.model
|
||||
def _prepare_attendee_values(self, registration):
|
||||
""" Method preparing the values to create new attendees based on a
|
||||
sales order line. It takes some registration data (dict-based) that are
|
||||
optional values coming from an external input like a web page. This method
|
||||
is meant to be inherited in various addons that sell events. """
|
||||
partner_id = registration.pop('partner_id', self.env.user.partner_id)
|
||||
event_id = registration.pop('event_id', False)
|
||||
data = {
|
||||
'name': registration.get('name', partner_id.name),
|
||||
'phone': registration.get('phone', partner_id.phone),
|
||||
'mobile': registration.get('mobile', partner_id.mobile),
|
||||
'email': registration.get('email', partner_id.email),
|
||||
'partner_id': partner_id.id,
|
||||
'event_id': event_id and event_id.id or False,
|
||||
}
|
||||
data.update({key: value for key, value in registration.items() if key in self._fields})
|
||||
return data
|
||||
|
||||
def name_get(self):
|
||||
""" Custom name_get implementation to better differentiate registrations
|
||||
linked to a given partner but with different name (one partner buying
|
||||
@@ -116,6 +117,26 @@ class EventRegistration(models.Model):
|
||||
ret_list.append((registration.id, name))
|
||||
return ret_list
|
||||
|
||||
def _check_auto_confirmation(self):
|
||||
if self._context.get('registration_force_draft'):
|
||||
return False
|
||||
if any(not registration.event_id.auto_confirm or
|
||||
(not registration.event_id.seats_available and registration.event_id.seats_availability == 'limited') for registration in self):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _synchronize_partner_values(self, partner):
|
||||
if partner:
|
||||
contact_id = partner.address_get().get('contact', False)
|
||||
if contact_id:
|
||||
contact = self.env['res.partner'].browse(contact_id)
|
||||
return dict((fname, contact[fname]) for fname in ['name', 'email', 'phone', 'mobile'] if contact[fname])
|
||||
return {}
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# ACTIONS / BUSINESS
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def action_set_draft(self):
|
||||
self.write({'state': 'draft'})
|
||||
|
||||
@@ -129,17 +150,6 @@ class EventRegistration(models.Model):
|
||||
def action_cancel(self):
|
||||
self.write({'state': 'cancel'})
|
||||
|
||||
@api.onchange('partner_id')
|
||||
def _onchange_partner(self):
|
||||
if self.partner_id:
|
||||
contact_id = self.partner_id.address_get().get('contact', False)
|
||||
if contact_id:
|
||||
contact = self.env['res.partner'].browse(contact_id)
|
||||
self.name = contact.name or self.name
|
||||
self.email = contact.email or self.email
|
||||
self.phone = contact.phone or self.phone
|
||||
self.mobile = contact.mobile or self.mobile
|
||||
|
||||
def _message_get_suggested_recipients(self):
|
||||
recipients = super(EventRegistration, self)._message_get_suggested_recipients()
|
||||
public_users = self.env['res.users'].sudo()
|
||||
|
||||
@@ -41,29 +41,38 @@ class EventRegistration(models.Model):
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('sale_order_line_id'):
|
||||
so_line_vals = self._synchronize_so_line_values(
|
||||
self.env['sale.order.line'].browse(vals['sale_order_line_id'])
|
||||
)
|
||||
vals.update(so_line_vals)
|
||||
res = super(EventRegistration, self).create(vals)
|
||||
if res.origin or res.sale_order_id:
|
||||
res.message_post_with_view('mail.message_origin_link',
|
||||
res.message_post_with_view(
|
||||
'mail.message_origin_link',
|
||||
values={'self': res, 'origin': res.sale_order_id},
|
||||
subtype_id=self.env.ref('mail.mt_note').id)
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _prepare_attendee_values(self, registration):
|
||||
""" Override to add sale related stuff """
|
||||
line_id = registration.get('sale_order_line_id')
|
||||
if line_id:
|
||||
registration.setdefault('partner_id', line_id.order_id.partner_id)
|
||||
att_data = super(EventRegistration, self)._prepare_attendee_values(registration)
|
||||
if line_id and line_id.event_ticket_id.sale_available:
|
||||
att_data.update({
|
||||
'event_id': line_id.event_id.id,
|
||||
'event_ticket_id': line_id.event_ticket_id.id,
|
||||
'origin': line_id.order_id.name,
|
||||
'sale_order_id': line_id.order_id.id,
|
||||
'sale_order_line_id': line_id.id,
|
||||
})
|
||||
return att_data
|
||||
def write(self, vals):
|
||||
if vals.get('sale_order_line_id'):
|
||||
so_line_vals = self._synchronize_so_line_values(
|
||||
self.env['sale.order.line'].browse(vals['sale_order_line_id'])
|
||||
)
|
||||
vals.update(so_line_vals)
|
||||
return super(EventRegistration, self).write(vals)
|
||||
|
||||
def _synchronize_so_line_values(self, so_line):
|
||||
if so_line:
|
||||
return {
|
||||
'partner_id': so_line.order_id.partner_id.id,
|
||||
'event_id': so_line.event_id.id,
|
||||
'event_ticket_id': so_line.event_ticket_id.id,
|
||||
'origin': so_line.order_id.name,
|
||||
'sale_order_id': so_line.order_id.id,
|
||||
'sale_order_line_id': so_line.id,
|
||||
}
|
||||
return {}
|
||||
|
||||
def summary(self):
|
||||
res = super(EventRegistration, self).summary()
|
||||
|
||||
@@ -60,13 +60,12 @@ class SaleOrderLine(models.Model):
|
||||
existing_registrations.filtered(lambda self: self.state == 'cancel').action_set_draft()
|
||||
|
||||
for count in range(int(so_line.product_uom_qty) - len(existing_registrations)):
|
||||
registration = {}
|
||||
registration_vals = {}
|
||||
if registration_data:
|
||||
registration = registration_data.pop()
|
||||
registration_vals = registration_data.pop()
|
||||
# TDE CHECK: auto confirmation
|
||||
registration['sale_order_line_id'] = so_line
|
||||
Registration.with_context(registration_force_draft=True).create(
|
||||
Registration._prepare_attendee_values(registration))
|
||||
registration_vals['sale_order_line_id'] = so_line.id
|
||||
Registration.with_context(registration_force_draft=True).create(registration_vals)
|
||||
return True
|
||||
|
||||
@api.onchange('product_id')
|
||||
|
||||
@@ -290,10 +290,11 @@ class WebsiteEventController(http.Controller):
|
||||
Attendees = request.env['event.registration']
|
||||
registrations = self._process_registration_details(post)
|
||||
|
||||
for registration in registrations:
|
||||
registration['event_id'] = event
|
||||
Attendees += Attendees.sudo().create(
|
||||
Attendees._prepare_attendee_values(registration))
|
||||
for registration_vals in registrations:
|
||||
registration_vals['event_id'] = event.id
|
||||
if not registration_vals.get('partner_id'):
|
||||
registration_vals['partner_id'] = request.env.user.partner_id.id
|
||||
Attendees += Attendees.sudo().create(registration_vals)
|
||||
|
||||
urls = event._get_event_resource_urls()
|
||||
return request.render("website_event.registration_complete", {
|
||||
|
||||
@@ -29,6 +29,12 @@ class WebsiteEventSaleController(WebsiteEventController):
|
||||
tickets = request.env['event.event.ticket'].browse(tuple(ticket_post))
|
||||
return [{'id': ticket.id, 'name': ticket.name, 'quantity': ticket_post[ticket.id], 'price': ticket.price} for ticket in tickets if ticket_post[ticket.id]]
|
||||
|
||||
def _process_registration_details(self, details):
|
||||
res = super(WebsiteEventSaleController, self)._process_registration_details(details)
|
||||
for registration_vals in res:
|
||||
registration_vals['event_ticket_id'] = int(registration_vals.pop('ticket_id')) if registration_vals.get('ticket_id') else False
|
||||
return res
|
||||
|
||||
@http.route()
|
||||
def registration_confirm(self, event, **post):
|
||||
order = request.website.sale_get_order(force_create=1)
|
||||
@@ -36,7 +42,7 @@ class WebsiteEventSaleController(WebsiteEventController):
|
||||
|
||||
registrations = self._process_registration_details(post)
|
||||
for registration in registrations:
|
||||
ticket = request.env['event.event.ticket'].sudo().browse(int(registration['ticket_id']))
|
||||
ticket = request.env['event.event.ticket'].sudo().browse(int(registration['event_ticket_id']))
|
||||
cart_values = order.with_context(event_ticket_id=ticket.id, fixed_price=True)._cart_update(product_id=ticket.product_id.id, add_qty=1, registration_data=[registration])
|
||||
attendee_ids |= set(cart_values.get('attendee_ids', []))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user